From 1ed9dbd38bc26a28ecbf3d59336f2f4cfc65b580 Mon Sep 17 00:00:00 2001 From: SrTobi Date: Sun, 16 Jun 2019 13:39:31 +0200 Subject: [PATCH 1/2] correctly parse enum values enum values can be expressions including - unary operators - binary operators - string and number literals - parenthesis - identifiers See: https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#92-enum-members https://github.com/microsoft/TypeScript/blob/master/doc/spec.md#419-binary-operators Note: this implementation performs a flat parse that neither handles expression-tree-building nor operator precedences. Note: This commit removes the minus from the NumericLit-token and parses it explicitly in TSDefParser.numberLiteral --- samples/valueExpression.d.ts | 12 ++++++ samples/valueExpression.d.ts.scala | 40 +++++++++++++++++++ .../tsimporter/parser/TSDefLexical.scala | 4 +- .../tools/tsimporter/parser/TSDefParser.scala | 31 ++++++++++++-- 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 samples/valueExpression.d.ts create mode 100644 samples/valueExpression.d.ts.scala diff --git a/samples/valueExpression.d.ts b/samples/valueExpression.d.ts new file mode 100644 index 00000000..a428c051 --- /dev/null +++ b/samples/valueExpression.d.ts @@ -0,0 +1,12 @@ +declare module valueExpression { + export enum StringEnum { + A = "test", + B = A, + C = "test" + "test" + } + export enum NumberEnum { + A = 3 + 3, + B = 1 << 3, + C = 10**2+1*8- - -3/3>>2<<3>>>+19%~~~3+ + +9 + } +} \ No newline at end of file diff --git a/samples/valueExpression.d.ts.scala b/samples/valueExpression.d.ts.scala new file mode 100644 index 00000000..fccee1bc --- /dev/null +++ b/samples/valueExpression.d.ts.scala @@ -0,0 +1,40 @@ + +import scala.scalajs.js +import js.annotation._ +import js.| + +package valueExpression { + +package valueExpression { + +@js.native +sealed trait StringEnum extends js.Object { +} + +@js.native +@JSGlobal("valueExpression.StringEnum") +object StringEnum extends js.Object { + var A: StringEnum = js.native + var B: StringEnum = js.native + var C: StringEnum = js.native + @JSBracketAccess + def apply(value: StringEnum): String = js.native +} + +@js.native +sealed trait NumberEnum extends js.Object { +} + +@js.native +@JSGlobal("valueExpression.NumberEnum") +object NumberEnum extends js.Object { + var A: NumberEnum = js.native + var B: NumberEnum = js.native + var C: NumberEnum = js.native + @JSBracketAccess + def apply(value: NumberEnum): String = js.native +} + +} + +} diff --git a/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefLexical.scala b/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefLexical.scala index d04a4a58..46afcb27 100644 --- a/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefLexical.scala +++ b/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefLexical.scala @@ -42,8 +42,8 @@ class TSDefLexical extends Lexical with StdTokens with ImplicitConversions { digits => digits.foldLeft(0L)(_ * 8 + _).toString } ) - | opt('-') ~ stringOf1(digit) ~ opt(stringOf1('.', digit)) ^^ { - case sign ~ part1 ~ part2 => sign.getOrElse("") + part1 + (part2.getOrElse("")) + | stringOf1(digit) ~ opt(stringOf1('.', digit)) ^^ { + case part1 ~ part2 => part1 + part2.getOrElse("") } ) ^^ NumericLit diff --git a/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefParser.scala b/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefParser.scala index cc3c3ea2..7a715517 100644 --- a/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefParser.scala +++ b/src/main/scala/org/scalajs/tools/tsimporter/parser/TSDefParser.scala @@ -46,6 +46,18 @@ class TSDefParser extends StdTokenParsers with ImplicitConversions { "...", "=>" ) + // for value expressions + val binaryValueOperators = Set( + "+", "-", "*", "/", "**", "%", + "<<", ">>>", ">>", "&", "|", "^" + ) + lexical.delimiters ++= binaryValueOperators + + val unaryValueOperators = Set( + "+", "-", "~" + ) + lexical.delimiters ++= unaryValueOperators + def parseDefinitions(input: Reader[Char]) = phrase(ambientDeclarations)(new lexical.Scanner(input)) @@ -105,7 +117,20 @@ class TSDefParser extends StdTokenParsers with ImplicitConversions { "enum" ~> typeName ~ ("{" ~> ambientEnumBody <~ "}") ^^ EnumDecl lazy val ambientEnumBody: Parser[List[Ident]] = - repsep(identifier <~ opt("=" ~ (numericLit | stringLit) ), ",") <~ opt(",") + repsep(identifier <~ opt("=" ~! valueExpression), ",") <~ opt(",") + + lazy val valueExpression: Parser[_] = + rep1sep(success() ~>! rep(unaryValueOperator) ~ + (numericLit | stringLit | identifierName | parenthesizedValueExpression), binaryValueOperator) + + lazy val parenthesizedValueExpression = + "(" ~! valueExpression ~ ")" + + lazy val binaryValueOperator = + elem("binary operator", tok => binaryValueOperators.contains(tok.chars)) + + lazy val unaryValueOperator = + elem("unary operator", tok => unaryValueOperators.contains(tok.chars)) lazy val ambientClassDecl: Parser[DeclTree] = (abstractModifier <~ "class") ~ typeName ~ tparams ~ classParent ~ classImplements ~ memberBlock <~ opt(";") ^^ { @@ -342,8 +367,8 @@ class TSDefParser extends StdTokenParsers with ImplicitConversions { stringLit ^^ StringLiteral lazy val numberLiteral: Parser[NumberLiteral] = - numericLit ^^ { s => - val d = s.toDouble + opt("-") ~ numericLit ^^ { case minus ~ s => + val d = (minus.getOrElse("") + s).toDouble if (!s.contains(".") && d.isValidInt) { IntLiteral(d.toInt) } else { From 5833a6e44887be7abbb2a135ec0929b630e4946e Mon Sep 17 00:00:00 2001 From: SrTobi Date: Sun, 16 Jun 2019 15:18:29 +0200 Subject: [PATCH 2/2] use newest typescript in travis (2.6.2 -> 3.5.2) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b6c9cbe6..2573a03e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ install: - . $HOME/.nvm/nvm.sh - nvm install 8 - nvm use 8 - - npm install typescript@2.6.2 + - npm install typescript@3.5.2 cache: directories: