diff --git a/sjsonnet/src/sjsonnet/Expr.scala b/sjsonnet/src/sjsonnet/Expr.scala index 39cc9c2f..5e3f371f 100644 --- a/sjsonnet/src/sjsonnet/Expr.scala +++ b/sjsonnet/src/sjsonnet/Expr.scala @@ -1,7 +1,6 @@ package sjsonnet -import java.util.BitSet - +import java.util.{Arrays, BitSet} import scala.collection.mutable /** @@ -116,6 +115,11 @@ object Expr{ case class AssertExpr(pos: Position, asserted: Member.AssertStmt, returned: Expr) extends Expr case class LocalExpr(pos: Position, bindings: Array[Bind], returned: Expr) extends Expr { override def toString = s"LocalExpr($pos, ${arrStr(bindings)}, $returned)" + override def equals(o: Any): Boolean = o match { + case o: LocalExpr => + pos == o.pos && Arrays.equals(bindings.asInstanceOf[Array[AnyRef]], o.bindings.asInstanceOf[Array[AnyRef]]) && returned == o.returned + case _ => false + } } case class Bind(pos: Position, name: String, args: Params, rhs: Expr) extends Member diff --git a/sjsonnet/src/sjsonnet/Parser.scala b/sjsonnet/src/sjsonnet/Parser.scala index 7a2d049a..7d75e255 100644 --- a/sjsonnet/src/sjsonnet/Parser.scala +++ b/sjsonnet/src/sjsonnet/Parser.scala @@ -237,10 +237,15 @@ class Parser(val currentFile: Path) { ) def local[_: P] = P( localExpr ) - def importStr[_: P](pos: Position) = P( string.map(Expr.ImportStr(pos, _)) ) - def `import`[_: P](pos: Position) = P( string.map(Expr.Import(pos, _)) ) + def importStr[_: P](pos: Position) = P( importExpr.map(Expr.ImportStr(pos, _)) ) + def `import`[_: P](pos: Position) = P( importExpr.map(Expr.Import(pos, _)) ) def error[_: P](pos: Position) = P(expr.map(Expr.Error(pos, _)) ) + def importExpr[_: P]: P[String] = P(expr.flatMap { + case Val.Str(_, s) => Pass(s) + case _ => Fail.opaque("string literal (computed imports are not allowed)") + }) + def unaryOpExpr[_: P](pos: Position, op: Char) = P( expr1.map{ e => def k2 = op match{ diff --git a/sjsonnet/test/src/sjsonnet/ParserTests.scala b/sjsonnet/test/src/sjsonnet/ParserTests.scala index 94c321c6..6f8f0877 100644 --- a/sjsonnet/test/src/sjsonnet/ParserTests.scala +++ b/sjsonnet/test/src/sjsonnet/ParserTests.scala @@ -27,6 +27,16 @@ object ParserTests extends TestSuite{ test("givenDuplicateFieldsInListComprehension_expectError") { parseErr("""{ ["bar"]: x for x in [1, 2]}""") ==> """Expected no duplicate field: "bar" :1:29, found "}"""" } + + test("computedImports") { + parse("""local foo = import "foo"; 0""") ==> + LocalExpr(pos(6), Array(Bind(pos(6), "foo", null, Import(pos(12), "foo"))), Num(pos(26),0.0)) + parse("""local foo = (import "foo") + bar; 0""") ==> + LocalExpr(pos(6), Array(Bind(pos(6), "foo", null, BinaryOp(pos(27), Import(pos(13), "foo"), 3, Id(pos(29), "bar")))), Num(pos(34),0.0)) + parseErr("""local foo = import ("foo" + bar); 0""") ==> """Expected string literal (computed imports are not allowed):1:33, found "; 0"""" + parseErr("""local foo = import "foo" + bar; 0""") ==> """Expected string literal (computed imports are not allowed):1:31, found "; 0"""" + } + test("id starts with number") { parseErr("""{1_n: "foo",}""") ==> """Expected "}":1:2, found "1_n: \"foo\""""" }