From 90b0c5df5b866f2f1f794b449ce5f8377e235316 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 13 Jan 2025 13:52:14 +1100 Subject: [PATCH 1/2] `BooleanParser` --- .../compiler/parser/soft/BooleanParser.scala | 14 +++++++ .../parser/soft/ExpressionParser.scala | 1 + .../compiler/parser/soft/ast/SoftAST.scala | 13 +++++++ .../compiler/parser/soft/ast/Token.scala | 13 +++++-- .../parser/soft/BooleanParserSpec.scala | 38 +++++++++++++++++++ .../compiler/parser/soft/TestParser.scala | 3 ++ .../parser/soft/ast/TestSoftAST.scala | 12 ++++++ 7 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParser.scala create mode 100644 compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParserSpec.scala diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParser.scala new file mode 100644 index 000000000..bc7c3ae26 --- /dev/null +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParser.scala @@ -0,0 +1,14 @@ +package org.alephium.ralph.lsp.access.compiler.parser.soft + +import fastparse._ +import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} + +object BooleanParser { + + def parseOrFail[Unknown: P]: P[SoftAST.TokenDocumented[Token.PrimitiveBoolean]] = + P(TokenParser.parseOrFail(Token.True) | TokenParser.parseOrFail(Token.False)) + + def parseOrFailExpression[Unknown: P]: P[SoftAST.TokenExpression[Token.PrimitiveBoolean]] = + P(parseOrFail) map (SoftAST.TokenExpression(_)) + +} diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ExpressionParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ExpressionParser.scala index de19158ab..e5f8c8eaf 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ExpressionParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ExpressionParser.scala @@ -83,6 +83,7 @@ private object ExpressionParser { ReferenceCallParser.parseOrFail | AnnotationParser.parseOrFail | TupleParser.parseOrFail | + BooleanParser.parseOrFailExpression | IdentifierParser.parseOrFail } diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/SoftAST.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/SoftAST.scala index f5de87675..724bb32a1 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/SoftAST.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/SoftAST.scala @@ -132,6 +132,19 @@ object SoftAST { extends TokenExpectedErrorAST(token) with TokenDocExpectedAST[T] + /** + * Represents a token that is also an expression, e.g. `true` & `false`. + * + * @param token A token that is also an expression. + * @tparam T Type of token. + */ + case class TokenExpression[+T <: Token.Expression](token: TokenDocumented[T]) extends ExpressionAST { + + override def index: SourceIndex = + token.index + + } + case class Template( index: SourceIndex, templateType: TokenDocumented[Token.TemplateDefinition], diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/Token.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/Token.scala index db370aaf2..168b56f4d 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/Token.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/Token.scala @@ -48,6 +48,7 @@ object Token { */ sealed trait Reserved extends Token sealed trait InfixOperator extends Token + sealed trait Expression extends Token // A token that is also an expression. sealed abstract class Operator(override val lexeme: String) extends Token case object Equality extends Operator("==") with Reserved with InfixOperator @@ -139,10 +140,14 @@ object Token { case object Embeds extends Native("embeds") sealed abstract class Primitive(override val lexeme: String) extends Token - case object True extends Primitive("true") with Reserved - case object False extends Primitive("false") with Reserved - case object Alph_Small extends Primitive("alph") with Reserved - case object Alph_Big extends Primitive("ALPH") with Reserved + + sealed abstract class PrimitiveBoolean(override val lexeme: String) extends Primitive(lexeme) with Expression + case object True extends PrimitiveBoolean("true") with Reserved + case object False extends PrimitiveBoolean("false") with Reserved + + sealed abstract class PrimitiveUnit(override val lexeme: String) extends Primitive(lexeme) + case object Alph_Small extends PrimitiveUnit("alph") with Reserved + case object Alph_Big extends PrimitiveUnit("ALPH") with Reserved sealed trait Term extends Token case class Name(lexeme: String) extends Term diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParserSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParserSpec.scala new file mode 100644 index 000000000..8dacd2840 --- /dev/null +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParserSpec.scala @@ -0,0 +1,38 @@ +package org.alephium.ralph.lsp.access.compiler.parser.soft + +import org.alephium.ralph.lsp.access.compiler.parser.soft.TestParser._ +import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.TestSoftAST._ +import org.alephium.ralph.lsp.access.util.TestCodeUtil._ +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec +import org.scalatest.OptionValues._ + +class BooleanParserSpec extends AnyWordSpec with Matchers { + + "true" in { + parseBoolean("true") shouldBe True(indexOf(">>true<<")) + } + + "false" in { + parseBoolean("false") shouldBe False(indexOf(">>false<<")) + } + + "boolean with comments" in { + Seq("true", "false") foreach { + bool => + val result = + parseBoolean { + s"""// comment + |$bool""".stripMargin + } + + // has comment + result.documentation.value.comments should have size 1 + result.documentation.value.comments.head.text.value.text shouldBe "comment" + + result.code.text shouldBe bool + } + + } + +} diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TestParser.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TestParser.scala index dd00a30fa..090e9c9b6 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TestParser.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TestParser.scala @@ -63,6 +63,9 @@ object TestParser { def parseIdentifier(code: String): SoftAST.IdentifierAST = runSoftParser(IdentifierParser.parseOrFail(_))(code) + def parseBoolean(code: String): SoftAST.TokenDocumented[Token.PrimitiveBoolean] = + runSoftParser(BooleanParser.parseOrFail(_))(code) + def findAnnotation(identifier: String)(code: String): Option[SoftAST.Annotation] = findAnnotation( identifier = identifier, diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/TestSoftAST.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/TestSoftAST.scala index 700240ee9..d7df5cb21 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/TestSoftAST.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ast/TestSoftAST.scala @@ -78,6 +78,18 @@ object TestSoftAST { token = Token.CloseCurly ) + def True(index: SourceIndex): SoftAST.TokenDocumented[Token.True.type] = + TokenDocumented( + index = index, + token = Token.True + ) + + def False(index: SourceIndex): SoftAST.TokenDocumented[Token.False.type] = + TokenDocumented( + index = index, + token = Token.False + ) + def Identifier( index: SourceIndex, text: String): SoftAST.Identifier = From dde53f1ec3b459ebf6d94c24b7a5b2ebe7c8c537 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 13 Jan 2025 19:14:44 +1100 Subject: [PATCH 2/2] private `boolean` always return expression --- .../lsp/access/compiler/parser/soft/BooleanParser.scala | 8 ++++---- .../access/compiler/parser/soft/ExpressionParser.scala | 2 +- .../access/compiler/parser/soft/BooleanParserSpec.scala | 6 +++--- .../lsp/access/compiler/parser/soft/TestParser.scala | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParser.scala index bc7c3ae26..eaaaada4b 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParser.scala @@ -5,10 +5,10 @@ import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} object BooleanParser { - def parseOrFail[Unknown: P]: P[SoftAST.TokenDocumented[Token.PrimitiveBoolean]] = - P(TokenParser.parseOrFail(Token.True) | TokenParser.parseOrFail(Token.False)) + def parseOrFail[Unknown: P]: P[SoftAST.TokenExpression[Token.PrimitiveBoolean]] = + P(boolean) map (SoftAST.TokenExpression(_)) - def parseOrFailExpression[Unknown: P]: P[SoftAST.TokenExpression[Token.PrimitiveBoolean]] = - P(parseOrFail) map (SoftAST.TokenExpression(_)) + private def boolean[Unknown: P]: P[SoftAST.TokenDocumented[Token.PrimitiveBoolean]] = + P(TokenParser.parseOrFail(Token.True) | TokenParser.parseOrFail(Token.False)) } diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ExpressionParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ExpressionParser.scala index e5f8c8eaf..053fbdd0f 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ExpressionParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ExpressionParser.scala @@ -83,7 +83,7 @@ private object ExpressionParser { ReferenceCallParser.parseOrFail | AnnotationParser.parseOrFail | TupleParser.parseOrFail | - BooleanParser.parseOrFailExpression | + BooleanParser.parseOrFail | IdentifierParser.parseOrFail } diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParserSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParserSpec.scala index 8dacd2840..870370c9c 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParserSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BooleanParserSpec.scala @@ -10,11 +10,11 @@ import org.scalatest.OptionValues._ class BooleanParserSpec extends AnyWordSpec with Matchers { "true" in { - parseBoolean("true") shouldBe True(indexOf(">>true<<")) + parseBoolean("true").token shouldBe True(indexOf(">>true<<")) } "false" in { - parseBoolean("false") shouldBe False(indexOf(">>false<<")) + parseBoolean("false").token shouldBe False(indexOf(">>false<<")) } "boolean with comments" in { @@ -24,7 +24,7 @@ class BooleanParserSpec extends AnyWordSpec with Matchers { parseBoolean { s"""// comment |$bool""".stripMargin - } + }.token // has comment result.documentation.value.comments should have size 1 diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TestParser.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TestParser.scala index 090e9c9b6..2efad43d6 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TestParser.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TestParser.scala @@ -63,7 +63,7 @@ object TestParser { def parseIdentifier(code: String): SoftAST.IdentifierAST = runSoftParser(IdentifierParser.parseOrFail(_))(code) - def parseBoolean(code: String): SoftAST.TokenDocumented[Token.PrimitiveBoolean] = + def parseBoolean(code: String): SoftAST.TokenExpression[Token.PrimitiveBoolean] = runSoftParser(BooleanParser.parseOrFail(_))(code) def findAnnotation(identifier: String)(code: String): Option[SoftAST.Annotation] =