From 47b2beafb0898640dd457d2d77a1216d5b884a36 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 13:25:11 +1100 Subject: [PATCH 01/19] display the `text` in the error message --- .../ralph/lsp/access/compiler/parser/soft/ast/SoftAST.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3d53aa0c..0b1461cd 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 @@ -288,7 +288,7 @@ object SoftAST { index: SourceIndex, documentation: Option[Comments], code: CodeString) - extends ErrorAST(s"Cannot resolve '$code'") + extends ErrorAST(s"Cannot resolve '${code.text}'") with CodeDocumentedAST with BodyPartAST From a9df7a942cef36b5b7e98723704a27702884ea25 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 13:27:00 +1100 Subject: [PATCH 02/19] display the error message in the string tree representation --- .../lsp/access/compiler/parser/soft/ast/SoftAST.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 0b1461cd..9cd0b2d8 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 @@ -98,7 +98,14 @@ object SoftAST { } - abstract class ErrorAST(val message: String) extends SoftAST + abstract class ErrorAST(val message: String) extends SoftAST { + + // Also display the error message in the Tree representation + final override def toStringPretty(): String = + s"""${this.getClass.getSimpleName}("$message"): ${this.index}""" + + } + abstract class ExpectedErrorAST(element: String) extends ErrorAST(s"$element expected") abstract class TokenExpectedErrorAST(token: Token) extends ExpectedErrorAST(s"'${token.lexeme}'") From ebc5131867f46862ac29d2c465cc73dee977fb43 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 13:42:26 +1100 Subject: [PATCH 03/19] Rename `Tuple` to `Group` so its parser is reusable in function-params, structs, tuples, contracts, txscript etc --- .../parser/soft/AnnotationParser.scala | 2 +- .../parser/soft/ExpressionParser.scala | 2 +- .../compiler/parser/soft/FunctionParser.scala | 22 ++++- .../{TupleParser.scala => GroupParser.scala} | 82 ++++++++++++++----- .../parser/soft/ParameterParser.scala | 25 ++++-- .../parser/soft/ReferenceCallParser.scala | 4 +- .../parser/soft/TypeAssignmentParser.scala | 2 +- .../compiler/parser/soft/TypeParser.scala | 27 ------ .../compiler/parser/soft/ast/SoftAST.scala | 29 +++---- .../compiler/parser/soft/AnnotationSpec.scala | 4 +- .../parser/soft/FunctionNameSpec.scala | 4 +- .../soft/FunctionReturnClauseSpec.scala | 28 +++---- .../soft/{TupleSpec.scala => GroupSpec.scala} | 34 ++++---- .../parser/soft/MutableBindingSpec.scala | 6 +- .../compiler/parser/soft/TemplateSpec.scala | 4 +- .../compiler/parser/soft/TestParser.scala | 7 +- .../compiler/parser/soft/TypeParserSpec.scala | 61 -------------- .../parser/soft/VariableDeclarationSpec.scala | 4 +- 18 files changed, 163 insertions(+), 184 deletions(-) rename compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{TupleParser.scala => GroupParser.scala} (62%) delete mode 100644 compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeParser.scala rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{TupleSpec.scala => GroupSpec.scala} (83%) delete mode 100644 compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeParserSpec.scala diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationParser.scala index 4b21b5a3..c0844a7b 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationParser.scala @@ -42,7 +42,7 @@ private object AnnotationParser { SpaceParser.parseOrFail.? ~ IdentifierParser.parse ~ SpaceParser.parseOrFail.? ~ - TupleParser.parseOrFail.? ~ + ParameterParser.parseOrFail.? ~ SpaceParser.parseOrFail.? ~ Index } map { 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 5c46c3fa..e8f1fd07 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 @@ -98,7 +98,7 @@ private object ExpressionParser { BlockParser.clause(required = false) | ReferenceCallParser.parseOrFail | AnnotationParser.parseOrFail | - TupleParser.parseOrFail | + ParameterParser.parseOrFail | NumberParser.parseOrFail | BooleanParser.parseOrFail | BStringParser.parseOrFail | diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionParser.scala index 848c13f9..d36c589e 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionParser.scala @@ -18,7 +18,7 @@ package org.alephium.ralph.lsp.access.compiler.parser.soft import fastparse._ import fastparse.NoWhitespace.noWhitespaceImplicit -import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.range +import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.{point, range} import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} private object FunctionParser { @@ -92,7 +92,9 @@ private object FunctionParser { private def returnSignature[Unknown: P]: P[SoftAST.FunctionReturnAST] = P { Index ~ - (TokenParser.parse(Token.ForwardArrow) ~ SpaceParser.parseOrFail.? ~ TypeParser.parse).? ~ + (TokenParser.parse(Token.ForwardArrow) ~ + SpaceParser.parseOrFail.? ~ + returnExpression).? ~ Index } map { case (from, Some((forwardArrow, space, tpe)), to) => @@ -107,4 +109,20 @@ private object FunctionParser { SoftAST.FunctionReturnExpected(range(from, to)) } + private def returnExpression[Unknown: P]: P[SoftAST.ExpressionAST] = + P(Index ~ returnExpressionParserOrFail.?) map { + case (_, Some(expression)) => + expression + + case (from, None) => + SoftAST.ExpressionExpected(point(from)) + } + + private def returnExpressionParserOrFail[Unknown: P]: P[SoftAST.ExpressionAST] = + P { + ParameterParser.parseOrFail | + NumberParser.parseOrFail | + IdentifierParser.parseOrFail + } + } diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TupleParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala similarity index 62% rename from compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TupleParser.scala rename to compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala index 23c108c9..c1a8263f 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TupleParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala @@ -21,16 +21,41 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.{point, range} import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -private object TupleParser { +object GroupParser { - def parseOrFail[Unknown: P]: P[SoftAST.Tuple] = - P(tuple(required = false)) + def parse[Unknown: P, O <: Token, C <: Token]( + open: O, + close: C): P[SoftAST.Group[O, C]] = + P { + group( + required = true, + open = open, + close = close + ) + } - def parse[Unknown: P]: P[SoftAST.Tuple] = - P(tuple(required = true)) + def parse[Unknown: P, O <: Token, C <: Token]( + required: Boolean, + open: O, + close: C): P[SoftAST.Group[O, C]] = + P { + group( + required, + open = open, + close = close + ) + } - def parse[Unknown: P](required: Boolean): P[SoftAST.Tuple] = - P(tuple(required)) + def parseOrFail[Unknown: P, O <: Token, C <: Token]( + open: O, + close: C): P[SoftAST.Group[O, C]] = + P { + group( + required = false, + open = open, + close = close + ) + } /** * Parses a sequence of arguments enclosed within parentheses. @@ -38,18 +63,21 @@ private object TupleParser { * Syntax: (arg1, arg2, (arg3, arg4), arg5) * * @param required Determines if the parser should fail when the opening parenthesis is missing. - * @return An instance of [[SoftAST.Tuple]]. + * @return An instance of [[SoftAST.Group]]. */ - private def tuple[Unknown: P](required: Boolean): P[SoftAST.Tuple] = + private def group[Unknown: P, O <: Token, C <: Token]( + required: Boolean, + open: O, + close: C): P[SoftAST.Group[O, C]] = P { Index ~ - TokenParser.parse(required, Token.OpenParen) ~ + TokenParser.parse(required, open) ~ SpaceParser.parseOrFail.? ~ Index ~ - ExpressionParser.parseOrFail.? ~ + expression.? ~ SpaceParser.parseOrFail.? ~ - tailParams.rep ~ - TokenParser.parse(Token.CloseParen) ~ + tail.rep ~ + TokenParser.parse(close) ~ Index } map { case (from, openParen, preHeadSpace, headParamIndex, headExpression, postHeadSpace, tailParams, closeParen, to) => @@ -61,14 +89,14 @@ private object TupleParser { else headExpression - SoftAST.Tuple( + SoftAST.Group( index = range(from, to), - openParen = openParen, + openToken = openParen, preHeadExpressionSpace = preHeadSpace, headExpression = headExpressionAdjusted, postHeadExpressionSpace = postHeadSpace, tailExpressions = tailParams, - closeParen = closeParen + closeToken = closeParen ) } @@ -78,19 +106,19 @@ private object TupleParser { * * Syntax: (arg1>>, arg2, (arg3, arg4), arg5<<) * - * @return An instance of [[SoftAST.TupleTail]]. + * @return An instance of [[SoftAST.GroupTail]]. */ - private def tailParams[Unknown: P]: P[SoftAST.TupleTail] = + private def tail[Unknown: P]: P[SoftAST.GroupTail] = P { Index ~ TokenParser.parseOrFail(Token.Comma) ~ SpaceParser.parseOrFail.? ~ - ExpressionParser.parse ~ + expression ~ SpaceParser.parseOrFail.? ~ Index } map { case (from, comma, preParamNameSpace, argumentName, postParamNameSpace, to) => - SoftAST.TupleTail( + SoftAST.GroupTail( index = range(from, to), comma = comma, preExpressionSpace = preParamNameSpace, @@ -99,4 +127,18 @@ private object TupleParser { ) } + private def expression[Unknown: P]: P[SoftAST.ExpressionAST] = + P { + TypeAssignmentParser.parseOrFail | + AssignmentParser.parseOrFail | + InfixCallParser.parseOrFail | + MethodCallParser.parseOrFail | + MutableBindingParser.parseOrFail | + ReferenceCallParser.parseOrFail | + NumberParser.parseOrFail | + BooleanParser.parseOrFail | + BStringParser.parseOrFail | + IdentifierParser.parseOrFail + } + } diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ParameterParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ParameterParser.scala index 36756c9b..ad6355e3 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ParameterParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ParameterParser.scala @@ -17,14 +17,27 @@ package org.alephium.ralph.lsp.access.compiler.parser.soft import fastparse._ -import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.SoftAST +import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -private object ParameterParser { +private case object ParameterParser { - def parse[Unknown: P]: P[SoftAST.Tuple] = - TupleParser.parse + def parse[Unknown: P]: P[SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type]] = + GroupParser.parse( + open = Token.OpenParen, + close = Token.CloseParen + ) - def parseOrFail[Unknown: P]: P[SoftAST.Tuple] = - TupleParser.parseOrFail + def parse[Unknown: P](required: Boolean): P[SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type]] = + GroupParser.parse( + required = required, + open = Token.OpenParen, + close = Token.CloseParen + ) + + def parseOrFail[Unknown: P]: P[SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type]] = + GroupParser.parseOrFail( + open = Token.OpenParen, + close = Token.CloseParen + ) } diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ReferenceCallParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ReferenceCallParser.scala index 6bc9f1d9..9d36b372 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ReferenceCallParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ReferenceCallParser.scala @@ -14,7 +14,7 @@ private object ReferenceCallParser { parse(required = false) /** - * Parses a function or object call along with its arguments [[TupleParser]]. + * Parses a function or object call along with its arguments [[GroupParser]]. * * Syntax: reference(arg1, arg2, (arg3, arg4)) * @@ -27,7 +27,7 @@ private object ReferenceCallParser { Index ~ IdentifierParser.parse(required) ~ SpaceParser.parseOrFail.? ~ - TupleParser.parse(required) ~ + ParameterParser.parse(required) ~ Index } map { case (from, identifier, space, arguments, to) => diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParser.scala index c1bd0203..c371d8aa 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParser.scala @@ -15,7 +15,7 @@ private object TypeAssignmentParser { SpaceParser.parseOrFail.? ~ TokenParser.parseOrFail(Token.Colon) ~ SpaceParser.parseOrFail.? ~ - TypeParser.parse ~ + ExpressionParser.parse ~ Index } map { case (from, access, identifier, postIdentifierSpace, equalToken, postEqualSpace, expression, to) => diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeParser.scala deleted file mode 100644 index 0a5f4328..00000000 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeParser.scala +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2024 The Alephium Authors -// This file is part of the alephium project. -// -// The library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the library. If not, see http://www.gnu.org/licenses/. - -package org.alephium.ralph.lsp.access.compiler.parser.soft - -import fastparse._ -import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.SoftAST - -private object TypeParser { - - def parse[Unknown: P]: P[SoftAST.TypeAST] = - P(TupleParser.parseOrFail | IdentifierParser.parse) - -} 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 9cd0b2d8..36105262 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 @@ -158,7 +158,7 @@ object SoftAST { preIdentifierSpace: SpaceAST, identifier: IdentifierAST, preParamSpace: Option[Space], - params: Option[Tuple], + params: Option[Group[Token.OpenParen.type, Token.CloseParen.type]], postParamSpace: Option[Space], inheritance: Seq[TemplateInheritance], block: BlockClause) @@ -170,7 +170,7 @@ object SoftAST { preIdentifierSpace: SpaceAST, identifier: IdentifierAST, preParamSpace: Option[Space], - params: Tuple) + params: Group[Token.OpenParen.type, Token.CloseParen.type]) extends BodyPartAST /** Syntax: `implements or extends contract(arg1, arg2 ...)` */ @@ -219,27 +219,24 @@ object SoftAST { index: SourceIndex, fnName: IdentifierAST, preParamSpace: Option[Space], - params: Tuple, + params: Group[Token.OpenParen.type, Token.CloseParen.type], postParamSpace: Option[Space], returned: FunctionReturnAST) extends SoftAST - sealed trait TypeAST extends SoftAST - /** Multiple arguments. Syntax: (arg1, (arg2, arg3)) */ - case class Tuple( + case class Group[O <: Token, C <: Token]( index: SourceIndex, - openParen: TokenDocExpectedAST[Token.OpenParen.type], + openToken: TokenDocExpectedAST[O], preHeadExpressionSpace: Option[Space], headExpression: Option[ExpressionAST], postHeadExpressionSpace: Option[Space], - tailExpressions: Seq[TupleTail], - closeParen: TokenDocExpectedAST[Token.CloseParen.type]) + tailExpressions: Seq[GroupTail], + closeToken: TokenDocExpectedAST[C]) extends ExpressionAST - with TypeAST /** Syntax: (arg1, >>arg2, (arg3, arg4)<<) */ - case class TupleTail( + case class GroupTail( index: SourceIndex, comma: TokenDocumented[Token.Comma.type], preExpressionSpace: Option[Space], @@ -253,7 +250,7 @@ object SoftAST { index: SourceIndex, forwardArrow: TokenDocExpectedAST[Token.ForwardArrow.type], space: Option[Space], - tpe: TypeAST) + tpe: ExpressionAST) extends FunctionReturnAST case class FunctionReturnExpected( @@ -261,7 +258,7 @@ object SoftAST { extends TokenExpectedErrorAST(Token.ForwardArrow) with FunctionReturnAST - sealed trait IdentifierAST extends TypeAST with ReferenceCallOrIdentifier + sealed trait IdentifierAST extends ReferenceCallOrIdentifier case class Identifier( index: SourceIndex, @@ -305,7 +302,7 @@ object SoftAST { index: SourceIndex, reference: IdentifierAST, preArgumentsSpace: Option[Space], - arguments: Tuple) + arguments: Group[Token.OpenParen.type, Token.CloseParen.type]) extends ExpressionAST with ReferenceCallOrIdentifier @@ -389,7 +386,7 @@ object SoftAST { preColonSpace: Option[Space], colon: TokenDocumented[Token.Colon.type], postColonSpace: Option[Space], - tpe: TypeAST) + tpe: ExpressionAST) extends ExpressionAST case class AssignmentAccessModifier( @@ -424,7 +421,7 @@ object SoftAST { preIdentifierSpace: Option[Space], identifier: IdentifierAST, postIdentifierSpace: Option[Space], - tuple: Option[Tuple], + tuple: Option[Group[Token.OpenParen.type, Token.CloseParen.type]], postTupleSpace: Option[Space]) extends ExpressionAST diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationSpec.scala index 09ccf1ef..c5c8cb6e 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationSpec.scala @@ -49,9 +49,9 @@ class AnnotationSpec extends AnyWordSpec with Matchers { parseAnnotation("@anno(") // opening paren is parsed - annotation.tuple.value.openParen shouldBe OpenParen(indexOf("@anno>>(<<")) + annotation.tuple.value.openToken shouldBe OpenParen(indexOf("@anno>>(<<")) // closing paren is reported as expected - annotation.tuple.value.closeParen shouldBe SoftAST.TokenExpected(indexOf("@anno(>><<"), Token.CloseParen) + annotation.tuple.value.closeToken shouldBe SoftAST.TokenExpected(indexOf("@anno(>><<"), Token.CloseParen) } "reject reserved keyword as annotation identifier" in { diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionNameSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionNameSpec.scala index 49303dbd..cf49e0d5 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionNameSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionNameSpec.scala @@ -167,7 +167,7 @@ class FunctionNameSpec extends AnyWordSpec with Matchers { function .signature .params - .closeParen shouldBe SoftAST.TokenExpected(indexOf("fn abcd(>><<"), Token.CloseParen) + .closeToken shouldBe SoftAST.TokenExpected(indexOf("fn abcd(>><<"), Token.CloseParen) } "missing opening parentheses" in { @@ -183,7 +183,7 @@ class FunctionNameSpec extends AnyWordSpec with Matchers { function .signature .params - .openParen shouldBe SoftAST.TokenExpected(indexOf("fn abcd>><<)"), Token.OpenParen) + .openToken shouldBe SoftAST.TokenExpected(indexOf("fn abcd>><<)"), Token.OpenParen) } } diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionReturnClauseSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionReturnClauseSpec.scala index 358d0639..71653321 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionReturnClauseSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionReturnClauseSpec.scala @@ -35,7 +35,7 @@ class FunctionReturnClauseSpec extends AnyWordSpec with Matchers { index = indexOf("fn >>-> <<"), forwardArrow = ForwardArrow(indexOf("fn >>-><< ")), space = Some(SpaceOne(indexOf("fn __>> <<"))), - tpe = SoftAST.IdentifierExpected(indexOf("fn -> >><<")) + tpe = SoftAST.ExpressionExpected(indexOf("fn -> >><<")) ) } @@ -79,7 +79,7 @@ class FunctionReturnClauseSpec extends AnyWordSpec with Matchers { index = indexOf("fn function >>-> <<"), forwardArrow = ForwardArrow(indexOf("fn function >>-><< ")), space = Some(SpaceOne(indexOf("fn function __>> <<"))), - tpe = SoftAST.IdentifierExpected(indexOf("fn function -> >><<")) + tpe = SoftAST.ExpressionExpected(indexOf("fn function -> >><<")) ) } @@ -117,9 +117,9 @@ class FunctionReturnClauseSpec extends AnyWordSpec with Matchers { text = "function" ) - function.signature.params.openParen shouldBe OpenParen(indexOf("fn function>>(<<-> ")) + function.signature.params.openToken shouldBe OpenParen(indexOf("fn function>>(<<-> ")) - function.signature.params.closeParen shouldBe + function.signature.params.closeToken shouldBe SoftAST.TokenExpected(indexOf("fn function(>><<-> "), Token.CloseParen) function.signature.returned shouldBe @@ -127,7 +127,7 @@ class FunctionReturnClauseSpec extends AnyWordSpec with Matchers { index = indexOf("fn function(>>-> <<"), forwardArrow = ForwardArrow(indexOf("fn function(>>-><< ")), space = Some(SpaceOne(indexOf("fn function(__>> <<"))), - tpe = SoftAST.IdentifierExpected(indexOf("fn function(-> >><<")) + tpe = SoftAST.ExpressionExpected(indexOf("fn function(-> >><<")) ) } @@ -141,8 +141,8 @@ class FunctionReturnClauseSpec extends AnyWordSpec with Matchers { text = "function" ) - function.signature.params.openParen shouldBe OpenParen(indexOf("fn function>>(<<-> Type")) - function.signature.params.closeParen shouldBe SoftAST.TokenExpected(indexOf("fn function(>><<-> Type"), Token.CloseParen) + function.signature.params.openToken shouldBe OpenParen(indexOf("fn function>>(<<-> Type")) + function.signature.params.closeToken shouldBe SoftAST.TokenExpected(indexOf("fn function(>><<-> Type"), Token.CloseParen) function.signature.returned shouldBe SoftAST.FunctionReturn( @@ -169,15 +169,15 @@ class FunctionReturnClauseSpec extends AnyWordSpec with Matchers { text = "function" ) - function.signature.params.openParen shouldBe OpenParen(indexOf("fn function>>(<<) -> ")) - function.signature.params.closeParen shouldBe CloseParen(indexOf("fn function(>>)<< -> ")) + function.signature.params.openToken shouldBe OpenParen(indexOf("fn function>>(<<) -> ")) + function.signature.params.closeToken shouldBe CloseParen(indexOf("fn function(>>)<< -> ")) function.signature.returned shouldBe SoftAST.FunctionReturn( index = indexOf("fn function() >>-> <<"), forwardArrow = ForwardArrow(indexOf("fn function() >>-><< ")), space = Some(SpaceOne(indexOf("fn function() __>> <<"))), - tpe = SoftAST.IdentifierExpected(indexOf("fn function() -> >><<")) + tpe = SoftAST.ExpressionExpected(indexOf("fn function() -> >><<")) ) } @@ -191,8 +191,8 @@ class FunctionReturnClauseSpec extends AnyWordSpec with Matchers { text = "function" ) - function.signature.params.openParen shouldBe OpenParen(indexOf("fn function>>(<<) -> type")) - function.signature.params.closeParen shouldBe CloseParen(indexOf("fn function(>>)<< -> type")) + function.signature.params.openToken shouldBe OpenParen(indexOf("fn function>>(<<) -> type")) + function.signature.params.closeToken shouldBe CloseParen(indexOf("fn function(>>)<< -> type")) function.signature.returned shouldBe SoftAST.FunctionReturn( @@ -225,8 +225,8 @@ class FunctionReturnClauseSpec extends AnyWordSpec with Matchers { text = "function" ) - function.signature.params.openParen shouldBe OpenParen(indexOf("fn function>>(<<) => ABC")) - function.signature.params.closeParen shouldBe CloseParen(indexOf("fn function(>>)<< => ABC")) + function.signature.params.openToken shouldBe OpenParen(indexOf("fn function>>(<<) => ABC")) + function.signature.params.closeToken shouldBe CloseParen(indexOf("fn function(>>)<< => ABC")) /** * Second part is [[SoftAST.Unresolved]] arrow `=>` diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TupleSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupSpec.scala similarity index 83% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TupleSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupSpec.scala index 4a76e3ea..08468331 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TupleSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupSpec.scala @@ -24,22 +24,22 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec import org.scalatest.OptionValues._ -class TupleSpec extends AnyWordSpec with Matchers { +class GroupSpec extends AnyWordSpec with Matchers { "missing opening paren" in { val tuple = parseTuple(")") - tuple.openParen shouldBe SoftAST.TokenExpected(indexOf(">><<)"), Token.OpenParen) - tuple.closeParen shouldBe CloseParen(indexOf(">>)<<")) + tuple.openToken shouldBe SoftAST.TokenExpected(indexOf(">><<)"), Token.OpenParen) + tuple.closeToken shouldBe CloseParen(indexOf(">>)<<")) } "missing closing paren" in { val tuple = parseTuple("(") - tuple.openParen shouldBe OpenParen(indexOf(">>(<<")) - tuple.closeParen shouldBe SoftAST.TokenExpected(indexOf("(>><<"), Token.CloseParen) + tuple.openToken shouldBe OpenParen(indexOf(">>(<<")) + tuple.closeToken shouldBe SoftAST.TokenExpected(indexOf("(>><<"), Token.CloseParen) } "empty tuple" when { @@ -48,14 +48,14 @@ class TupleSpec extends AnyWordSpec with Matchers { parseTuple("()") val expected = - SoftAST.Tuple( + SoftAST.Group( index = indexOf(">>()<<"), - openParen = OpenParen(indexOf(">>(<<)")), + openToken = OpenParen(indexOf(">>(<<)")), preHeadExpressionSpace = None, headExpression = None, postHeadExpressionSpace = None, tailExpressions = Seq.empty, - closeParen = CloseParen(indexOf("(>>)<<)")) + closeToken = CloseParen(indexOf("(>>)<<)")) ) tuple shouldBe expected @@ -66,14 +66,14 @@ class TupleSpec extends AnyWordSpec with Matchers { parseTuple("( )") val expected = - SoftAST.Tuple( + SoftAST.Group( index = indexOf(">>( )<<"), - openParen = OpenParen(indexOf(">>(<< )")), + openToken = OpenParen(indexOf(">>(<< )")), preHeadExpressionSpace = Some(SpaceOne(indexOf("(>> <<)"))), headExpression = None, postHeadExpressionSpace = None, tailExpressions = Seq.empty, - closeParen = CloseParen(indexOf("( >>)<<)")) + closeToken = CloseParen(indexOf("( >>)<<)")) ) tuple shouldBe expected @@ -88,9 +88,9 @@ class TupleSpec extends AnyWordSpec with Matchers { * First body part is Tuple */ val tuple = - body.parts.head.part.asInstanceOf[SoftAST.Tuple] + body.parts.head.part.asInstanceOf[SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type]] - tuple.openParen shouldBe OpenParen(indexOf(">>(<>(<><><>(<>(<>)<<")) + tuple.closeToken shouldBe CloseParen(indexOf("(aaa: typename>>)<<")) } "valid second type assignment expression exists" in { @@ -187,7 +187,7 @@ class TupleSpec extends AnyWordSpec with Matchers { ) // A quick text to check that the tuple is actually a tuple - bbb.tpe shouldBe a[SoftAST.Tuple] + bbb.tpe shouldBe a[SoftAST.Group[_, _]] // Convert the tpe to code and it should be the tuple bbb.tpe.toCode() shouldBe "(tuple1, tuple2)" } diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingSpec.scala index fa7e2cd7..aebb53af 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingSpec.scala @@ -17,7 +17,7 @@ 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.SoftAST +import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} 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 @@ -45,7 +45,7 @@ class MutableBindingSpec extends AnyWordSpec with Matchers { parseSoft("(a, b, mut variable)") body.parts should have size 1 - val tuple = body.parts.head.part.asInstanceOf[SoftAST.Tuple] + val tuple = body.parts.head.part.asInstanceOf[SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type]] tuple.headExpression shouldBe defined tuple.tailExpressions should have size 2 // there are two tail expressions @@ -75,7 +75,7 @@ class MutableBindingSpec extends AnyWordSpec with Matchers { } body.parts should have size 1 - val tuple = body.parts.head.part.asInstanceOf[SoftAST.Tuple] + val tuple = body.parts.head.part.asInstanceOf[SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type]] tuple.headExpression shouldBe defined tuple.tailExpressions should have size 2 // there are two tail expressions diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TemplateSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TemplateSpec.scala index 0e95ea0b..f169ff87 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TemplateSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TemplateSpec.scala @@ -115,8 +115,8 @@ class TemplateSpec extends AnyWordSpec with Matchers { parseTemplate("Contract mycontract(") val params = template.params.value - params.openParen shouldBe OpenParen(indexOf("Contract mycontract>>(<<")) - params.closeParen shouldBe SoftAST.TokenExpected(indexOf("Contract mycontract(>><<"), Token.CloseParen) + params.openToken shouldBe OpenParen(indexOf("Contract mycontract>>(<<")) + params.closeToken shouldBe SoftAST.TokenExpected(indexOf("Contract mycontract(>><<"), Token.CloseParen) } "params are empty" in { 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 afbd94ff..1994be44 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 @@ -45,8 +45,8 @@ object TestParser { def parseFunction(code: String): SoftAST.Function = runSoftParser(FunctionParser.parseOrFail(_))(code) - def parseTuple(code: String): SoftAST.Tuple = - runSoftParser(TupleParser.parse(_))(code) + def parseTuple(code: String): SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type] = + runSoftParser(ParameterParser.parse(_))(code) def parseBlockClause(mandatory: Boolean)(code: String): SoftAST.BlockClause = runSoftParser(BlockParser.clause(mandatory)(_))(code) @@ -57,9 +57,6 @@ object TestParser { def parseComment(code: String): SoftAST.Comments = runSoftParser(CommentParser.parseOrFail(_))(code) - def parseType(code: String): SoftAST.TypeAST = - runSoftParser(TypeParser.parse(_))(code) - def parseReservedToken(remove: Token.Reserved*)(code: String): Token.Reserved = runAnyParser(TokenParser.Reserved(remove: _*)(_))(code) diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeParserSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeParserSpec.scala deleted file mode 100644 index cfc17e49..00000000 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeParserSpec.scala +++ /dev/null @@ -1,61 +0,0 @@ -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.SoftAST -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 - -class TypeParserSpec extends AnyWordSpec with Matchers { - - "type expected" when { - "empty" in { - parseType("") shouldBe SoftAST.IdentifierExpected(indexOf(">><<")) - } - } - - "type is provided" in { - parseType("one") shouldBe - Identifier( - index = indexOf(">>one<<"), - text = "one" - ) - } - - "tuple 1" when { - "closing parentheses is missing" in { - val tpe = parseType("( one") - - tpe shouldBe a[SoftAST.Tuple] - } - - "closing parentheses is provided" in { - val tpe = parseType("( one)") - - tpe shouldBe a[SoftAST.Tuple] - } - } - - "tuple 2" when { - "second type is missing" in { - val tpe = parseType("(one, )") - - tpe shouldBe a[SoftAST.Tuple] - } - - "second type is a simple type name" in { - val tpe = parseType("(one, two)") - - tpe shouldBe a[SoftAST.Tuple] - } - - "second type is another tuple" in { - val tpe = parseType("(one, (two, three))") - - tpe shouldBe a[SoftAST.Tuple] - } - - } - -} diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationSpec.scala index 1d136b8c..3b4b0f3d 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationSpec.scala @@ -18,7 +18,7 @@ package org.alephium.ralph.lsp.access.compiler.parser.soft import org.alephium.ralph.error.CompilerError import org.alephium.ralph.lsp.access.compiler.parser.soft.TestParser._ -import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.SoftAST +import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} 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 @@ -122,7 +122,7 @@ class VariableDeclarationSpec extends AnyWordSpec with Matchers { ) // left is a tuple - val left = tupleDecl.assignment.expressionLeft.asInstanceOf[SoftAST.Tuple] + val left = tupleDecl.assignment.expressionLeft.asInstanceOf[SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type]] left.index shouldBe indexOf("let >>(a, b, c)<< = blah") left.toCode() shouldBe "(a, b, c)" From 8854b6ba98bdb0532d902c0627b4f7c4d062ff02 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 13:44:31 +1100 Subject: [PATCH 04/19] make private --- .../ralph/lsp/access/compiler/parser/soft/BooleanParser.scala | 2 +- .../ralph/lsp/access/compiler/parser/soft/CodeParser.scala | 2 +- .../ralph/lsp/access/compiler/parser/soft/GroupParser.scala | 2 +- .../lsp/access/compiler/parser/soft/IdentifierParser.scala | 2 +- .../ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala | 2 +- .../lsp/access/compiler/parser/soft/MethodCallParser.scala | 2 +- .../ralph/lsp/access/compiler/parser/soft/NumberParser.scala | 2 +- .../ralph/lsp/access/compiler/parser/soft/SpaceParser.scala | 2 +- 8 files changed, 8 insertions(+), 8 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 eaaaada4..f6d7de7e 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 @@ -3,7 +3,7 @@ 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 { +private object BooleanParser { def parseOrFail[Unknown: P]: P[SoftAST.TokenExpression[Token.PrimitiveBoolean]] = P(boolean) map (SoftAST.TokenExpression(_)) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CodeParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CodeParser.scala index 553ec445..2dfb1434 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CodeParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CodeParser.scala @@ -5,7 +5,7 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.range import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -object CodeParser { +private object CodeParser { def parseOrFail[Unknown: P, T <: Token](token: T): P[SoftAST.CodeToken[T]] = P(Index ~ token.lexeme ~ Index) map { diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala index c1a8263f..0c81f4f2 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala @@ -21,7 +21,7 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.{point, range} import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -object GroupParser { +private object GroupParser { def parse[Unknown: P, O <: Token, C <: Token]( open: O, diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParser.scala index 99def2be..53506c7e 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParser.scala @@ -5,7 +5,7 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra._ import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -object IdentifierParser { +private object IdentifierParser { def parse[Unknown: P](required: Boolean): P[SoftAST.IdentifierAST] = if (required) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala index 57fdfaaa..8ed75da7 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala @@ -5,7 +5,7 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.range import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.SoftAST -case object InfixCallParser { +private case object InfixCallParser { def parseOrFail[Unknown: P]: P[SoftAST.InfixExpression] = P { diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MethodCallParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MethodCallParser.scala index fd72082e..fe86fbb6 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MethodCallParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MethodCallParser.scala @@ -5,7 +5,7 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.range import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -case object MethodCallParser { +private case object MethodCallParser { def parseOrFail[Unknown: P]: P[SoftAST.MethodCall] = P { diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/NumberParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/NumberParser.scala index 2b9e7fb9..84bf5e99 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/NumberParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/NumberParser.scala @@ -5,7 +5,7 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra._ import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -object NumberParser { +private object NumberParser { def parseOrFail[Unknown: P]: P[SoftAST.Number] = P { diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/SpaceParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/SpaceParser.scala index 54f2a805..5108531e 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/SpaceParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/SpaceParser.scala @@ -21,7 +21,7 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.range import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -object SpaceParser { +private object SpaceParser { def parse[Unknown: P]: P[SoftAST.SpaceAST] = P(Index ~ parseOrFail.?) map { From d9a2e46276e1454e5a0ffb2c94239606906a94cd Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 13:48:38 +1100 Subject: [PATCH 05/19] `EventTemplateParser` --- .../compiler/parser/soft/BlockParser.scala | 2 +- ...Parser.scala => EventTemplateParser.scala} | 12 +++++----- .../compiler/parser/soft/ast/SoftAST.scala | 4 ++-- .../parser/soft/EventTemplateParserSpec.scala | 24 +++++++++++++++++++ .../compiler/parser/soft/TestParser.scala | 3 +++ .../parser/soft/ast/TestSoftAST.scala | 6 +++++ 6 files changed, 42 insertions(+), 9 deletions(-) rename compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{DataTemplateParser.scala => EventTemplateParser.scala} (63%) create mode 100644 compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/EventTemplateParserSpec.scala diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala index 6e2b3b3d..02efaab6 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala @@ -80,7 +80,7 @@ private object BlockParser { private def part[Unknown: P](stop: Seq[Token]): P[SoftAST.BodyPartAST] = P { TemplateParser.parseOrFail | - DataTemplateParser.parseOrFail | + EventTemplateParser.parseOrFail | FunctionParser.parseOrFail | ExpressionParser.parseOrFail | CommentParser.parseOrFail | diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/DataTemplateParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/EventTemplateParser.scala similarity index 63% rename from compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/DataTemplateParser.scala rename to compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/EventTemplateParser.scala index 98f161e5..9a07f16a 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/DataTemplateParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/EventTemplateParser.scala @@ -5,22 +5,22 @@ import fastparse.NoWhitespace.noWhitespaceImplicit import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.range import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} -private object DataTemplateParser { +private object EventTemplateParser { - def parseOrFail[Unknown: P]: P[SoftAST.DataTemplate] = + def parseOrFail[Unknown: P]: P[SoftAST.EventTemplate] = P { Index ~ - (TokenParser.parseOrFail(Token.Struct) | TokenParser.parseOrFail(Token.Enum) | TokenParser.parseOrFail(Token.Event)) ~ + TokenParser.parseOrFail(Token.Event) ~ SpaceParser.parse ~ IdentifierParser.parse ~ SpaceParser.parseOrFail.? ~ ParameterParser.parse ~ Index } map { - case (from, templateType, preIdentifierSpace, identifier, preParamSpace, params, to) => - SoftAST.DataTemplate( + case (from, eventToken, preIdentifierSpace, identifier, preParamSpace, params, to) => + SoftAST.EventTemplate( index = range(from, to), - dataType = templateType, + eventToken = eventToken, preIdentifierSpace = preIdentifierSpace, identifier = identifier, preParamSpace = preParamSpace, 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 36105262..9be64b1c 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 @@ -164,9 +164,9 @@ object SoftAST { block: BlockClause) extends BodyPartAST - case class DataTemplate( + case class EventTemplate( index: SourceIndex, - dataType: TokenDocumented[Token.DataTemplate], + eventToken: TokenDocumented[Token.Event.type], preIdentifierSpace: SpaceAST, identifier: IdentifierAST, preParamSpace: Option[Space], diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/EventTemplateParserSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/EventTemplateParserSpec.scala new file mode 100644 index 00000000..48d8e91e --- /dev/null +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/EventTemplateParserSpec.scala @@ -0,0 +1,24 @@ +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.{SoftAST, Token} +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 + +class EventTemplateParserSpec extends AnyWordSpec { + + "successfully parse an event" in { + val event = parseEventTemplate("event MyEvent(varName: TypeName") + + event.eventToken shouldBe Event(indexOf(">>event<< MyEvent(varName: TypeName")) + event.identifier shouldBe Identifier(indexOf("event >>MyEvent<<(varName: TypeName"), "MyEvent") + + // Tuples are tested in TupleSpec, test for the index and string code here. + event.params.index shouldBe indexOf("event MyEvent>>(varName: TypeName<<") + event.params.toCode() shouldBe "(varName: TypeName" + event.params.closeToken shouldBe SoftAST.TokenExpected(indexOf("event MyEvent(varName: TypeName>><<"), Token.CloseParen) + } + +} 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 1994be44..09526b39 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 @@ -82,6 +82,9 @@ object TestParser { def parseBString(code: String): SoftAST.BString = runSoftParser(BStringParser.parseOrFail(_))(code) + def parseEventTemplate(code: String): SoftAST.EventTemplate = + runSoftParser(EventTemplateParser.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 10e42c1e..5b4a0f3d 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 @@ -138,6 +138,12 @@ object TestSoftAST { token = Token.Tick ) + def Event(index: SourceIndex): SoftAST.TokenDocumented[Token.Event.type] = + TokenDocumented( + index = index, + token = Token.Event + ) + def Identifier( index: SourceIndex, text: String): SoftAST.Identifier = From b03eefdce66d4d6b3510d92fa7dfdb6e6bba1d3d Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 13:52:24 +1100 Subject: [PATCH 06/19] `StructTemplateParser` --- .../compiler/parser/soft/BlockParser.scala | 1 + .../parser/soft/StructTemplateParser.scala | 31 +++++++++++++++ .../compiler/parser/soft/ast/SoftAST.scala | 9 +++++ .../soft/StructTemplateParserSpec.scala | 38 +++++++++++++++++++ .../compiler/parser/soft/TestParser.scala | 3 ++ .../parser/soft/ast/TestSoftAST.scala | 6 +++ 6 files changed, 88 insertions(+) create mode 100644 compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/StructTemplateParser.scala create mode 100644 compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/StructTemplateParserSpec.scala diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala index 02efaab6..553932de 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala @@ -81,6 +81,7 @@ private object BlockParser { P { TemplateParser.parseOrFail | EventTemplateParser.parseOrFail | + StructTemplateParser.parseOrFail | FunctionParser.parseOrFail | ExpressionParser.parseOrFail | CommentParser.parseOrFail | diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/StructTemplateParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/StructTemplateParser.scala new file mode 100644 index 00000000..aeedc450 --- /dev/null +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/StructTemplateParser.scala @@ -0,0 +1,31 @@ +package org.alephium.ralph.lsp.access.compiler.parser.soft + +import fastparse._ +import fastparse.NoWhitespace.noWhitespaceImplicit +import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.range +import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} + +private object StructTemplateParser { + + def parseOrFail[Unknown: P]: P[SoftAST.StructTemplate] = + P { + Index ~ + TokenParser.parseOrFail(Token.Struct) ~ + SpaceParser.parse ~ + IdentifierParser.parse ~ + SpaceParser.parseOrFail.? ~ + GroupParser.parse(Token.OpenCurly, Token.CloseCurly) ~ + Index + } map { + case (from, structToken, preIdentifierSpace, identifier, preParamSpace, params, to) => + SoftAST.StructTemplate( + index = range(from, to), + structToken = structToken, + preIdentifierSpace = preIdentifierSpace, + identifier = identifier, + preParamSpace = preParamSpace, + params = params + ) + } + +} 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 9be64b1c..d78352a5 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 @@ -173,6 +173,15 @@ object SoftAST { params: Group[Token.OpenParen.type, Token.CloseParen.type]) extends BodyPartAST + case class StructTemplate( + index: SourceIndex, + structToken: TokenDocumented[Token.Struct.type], + preIdentifierSpace: SpaceAST, + identifier: IdentifierAST, + preParamSpace: Option[Space], + params: Group[Token.OpenCurly.type, Token.CloseCurly.type]) + extends BodyPartAST + /** Syntax: `implements or extends contract(arg1, arg2 ...)` */ case class TemplateInheritance( index: SourceIndex, diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/StructTemplateParserSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/StructTemplateParserSpec.scala new file mode 100644 index 00000000..0c2395b9 --- /dev/null +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/StructTemplateParserSpec.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.{SoftAST, Token} +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 + +class StructTemplateParserSpec extends AnyWordSpec { + + "closing curly is missing" in { + val struct = parseStructTemplate("struct MyStruct{varName: TypeName") + + struct.structToken shouldBe Struct(indexOf(">>struct<< MyStruct{varName: TypeName")) + struct.identifier shouldBe Identifier(indexOf("struct >>MyStruct<<{varName: TypeName"), "MyStruct") + + // Tuples are tested in TupleSpec, test for the index and string code here. + struct.params.index shouldBe indexOf("struct MyStruct>>{varName: TypeName<<") + struct.params.toCode() shouldBe "{varName: TypeName" + struct.params.closeToken shouldBe SoftAST.TokenExpected(indexOf("struct MyStruct{varName: TypeName>><<"), Token.CloseCurly) + } + + "well defined struct" in { + val struct = parseStructTemplate("struct Bar { z: U256, mut foo: Foo }") + + struct.structToken shouldBe Struct(indexOf(">>struct<< Bar { z: U256, mut foo: Foo }")) + struct.identifier shouldBe Identifier(indexOf("struct >>Bar<< { z: U256, mut foo: Foo }"), "Bar") + + // Tuples are tested in TupleSpec, test for the index and string code here. + struct.params.index shouldBe indexOf("struct Bar >>{ z: U256, mut foo: Foo }<<") + struct.params.toCode() shouldBe "{ z: U256, mut foo: Foo }" + struct.params.openToken shouldBe OpenCurly(indexOf("struct Bar >>{<< z: U256, mut foo: Foo }")) + struct.params.closeToken shouldBe CloseCurly(indexOf("struct Bar { z: U256, mut foo: Foo >>}<<")) + + } + +} 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 09526b39..236be2f3 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 @@ -85,6 +85,9 @@ object TestParser { def parseEventTemplate(code: String): SoftAST.EventTemplate = runSoftParser(EventTemplateParser.parseOrFail(_))(code) + def parseStructTemplate(code: String): SoftAST.StructTemplate = + runSoftParser(StructTemplateParser.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 5b4a0f3d..51c60fe8 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 @@ -144,6 +144,12 @@ object TestSoftAST { token = Token.Event ) + def Struct(index: SourceIndex): SoftAST.TokenDocumented[Token.Struct.type] = + TokenDocumented( + index = index, + token = Token.Struct + ) + def Identifier( index: SourceIndex, text: String): SoftAST.Identifier = From 428980a05c48f00cd4e24669584b4ad64039794b Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 13:52:42 +1100 Subject: [PATCH 07/19] add `event` and `struct` to `Demo` --- .../alephium/ralph/lsp/access/compiler/parser/soft/Demo.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/Demo.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/Demo.scala index c55a8c37..bbf105fb 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/Demo.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/Demo.scala @@ -10,6 +10,9 @@ object Demo extends App { val ast = compiler.parseSoft { """ + |event Event(a: Type) + |struct Struct { a: Type } + | |Contract HelloWorld(type: SomeType, tuple: (A, B)) extends Class implements Trait { | | // This multiline comment From b516ad122a47c4d23b6747f6c9a1e4c4b06739b5 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 13:56:34 +1100 Subject: [PATCH 08/19] narrow expression parsers executed in an `Assignment`s left `Expression` --- .../parser/soft/AssignmentParser.scala | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParser.scala index fe8d602e..22f4c828 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParser.scala @@ -10,7 +10,7 @@ private case object AssignmentParser { def parseOrFail[Unknown: P]: P[SoftAST.Assignment] = P { Index ~ - ExpressionParser.parseOrFailSelective(parseInfix = true, parseMethodCall = true, parseAssignment = false) ~ + leftExpression ~ SpaceParser.parseOrFail.? ~ TokenParser.parseOrFail(Token.Equal) ~ SpaceParser.parseOrFail.? ~ @@ -28,4 +28,20 @@ private case object AssignmentParser { ) } + private def leftExpression[Unknown: P]: P[SoftAST.ExpressionAST] = + P { + InfixCallParser.parseOrFail | + MethodCallParser.parseOrFail | + BlockParser.clause(required = false) | + VariableDeclarationParser.parseOrFail | + MutableBindingParser.parseOrFail | + ReferenceCallParser.parseOrFail | + AnnotationParser.parseOrFail | + ParameterParser.parseOrFail | + NumberParser.parseOrFail | + BooleanParser.parseOrFail | + BStringParser.parseOrFail | + IdentifierParser.parseOrFail + } + } From b3ce06832dcb9c95b7f2e26bf11310e508358d5d Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 14:00:00 +1100 Subject: [PATCH 09/19] narrow expression parsers executed in an `InfixCall`s left `Expression` --- .../compiler/parser/soft/BlockParser.scala | 3 +++ .../compiler/parser/soft/InfixCallParser.scala | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala index 553932de..adc217c3 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala @@ -23,6 +23,9 @@ import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} private object BlockParser { + def parseOrFail[Unknown: P]: P[SoftAST.BlockClause] = + BlockParser.clause(required = false) + def clause[Unknown: P](required: Boolean): P[SoftAST.BlockClause] = P { Index ~ diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala index 8ed75da7..96e052c0 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/InfixCallParser.scala @@ -10,7 +10,7 @@ private case object InfixCallParser { def parseOrFail[Unknown: P]: P[SoftAST.InfixExpression] = P { Index ~ - ExpressionParser.parseOrFailSelective(parseInfix = false, parseMethodCall = true, parseAssignment = false) ~ + leftExpression ~ SpaceParser.parseOrFail.? ~ TokenParser.InfixOperatorOrFail ~ SpaceParser.parseOrFail.? ~ @@ -28,4 +28,18 @@ private case object InfixCallParser { ) } + private def leftExpression[Unknown: P]: P[SoftAST.ExpressionAST] = + P { + MethodCallParser.parseOrFail | + BlockParser.parseOrFail | + VariableDeclarationParser.parseOrFail | + MutableBindingParser.parseOrFail | + ReferenceCallParser.parseOrFail | + ParameterParser.parseOrFail | + NumberParser.parseOrFail | + BooleanParser.parseOrFail | + BStringParser.parseOrFail | + IdentifierParser.parseOrFail + } + } From be91756757e72e955f502038a9db298968f328f5 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 14:01:32 +1100 Subject: [PATCH 10/19] replace `BlockParser.clause(required = false)` with `BlockParser.parseOrFail` for consistency --- .../lsp/access/compiler/parser/soft/AssignmentParser.scala | 2 +- .../lsp/access/compiler/parser/soft/ExpressionParser.scala | 2 +- .../ralph/lsp/access/compiler/parser/soft/FunctionParser.scala | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParser.scala index 22f4c828..290266b6 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParser.scala @@ -32,7 +32,7 @@ private case object AssignmentParser { P { InfixCallParser.parseOrFail | MethodCallParser.parseOrFail | - BlockParser.clause(required = false) | + BlockParser.parseOrFail | VariableDeclarationParser.parseOrFail | MutableBindingParser.parseOrFail | ReferenceCallParser.parseOrFail | 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 e8f1fd07..95f49e8d 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 @@ -95,7 +95,7 @@ private object ExpressionParser { VariableDeclarationParser.parseOrFail | MutableBindingParser.parseOrFail | TypeAssignmentParser.parseOrFail | - BlockParser.clause(required = false) | + BlockParser.parseOrFail | ReferenceCallParser.parseOrFail | AnnotationParser.parseOrFail | ParameterParser.parseOrFail | diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionParser.scala index d36c589e..240e4b4c 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/FunctionParser.scala @@ -39,7 +39,7 @@ private object FunctionParser { SpaceParser.parse ~ signature ~ SpaceParser.parseOrFail.? ~ - BlockParser.clause(required = false).? ~ + BlockParser.parseOrFail.? ~ Index } map { case (from, annotation, postAnnotationSpace, pub, fnDeceleration, headSpace, signature, tailSpace, block, to) => From 741d0050ba02ce235354dabd5a7fa821f6cbe2d2 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 14:04:01 +1100 Subject: [PATCH 11/19] `parse` and `parseOrFail` for `BlockParser` --- .../lsp/access/compiler/parser/soft/BlockParser.scala | 7 +++++-- .../lsp/access/compiler/parser/soft/ForLoopParser.scala | 2 +- .../lsp/access/compiler/parser/soft/TemplateParser.scala | 2 +- .../lsp/access/compiler/parser/soft/WhileLoopParser.scala | 2 +- .../ralph/lsp/access/compiler/parser/soft/TestParser.scala | 4 ++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala index adc217c3..6a6a0278 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala @@ -24,9 +24,12 @@ import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} private object BlockParser { def parseOrFail[Unknown: P]: P[SoftAST.BlockClause] = - BlockParser.clause(required = false) + parse(required = false) - def clause[Unknown: P](required: Boolean): P[SoftAST.BlockClause] = + def parse[Unknown: P]: P[SoftAST.BlockClause] = + parse(required = true) + + def parse[Unknown: P](required: Boolean): P[SoftAST.BlockClause] = P { Index ~ TokenParser.parse(required, Token.OpenCurly) ~ diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ForLoopParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ForLoopParser.scala index 2ca74a1d..19416e1a 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ForLoopParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/ForLoopParser.scala @@ -26,7 +26,7 @@ private object ForLoopParser { SpaceParser.parseOrFail.? ~ TokenParser.parse(Token.CloseParen) ~ SpaceParser.parseOrFail.? ~ - BlockParser.clause(required = true) ~ + BlockParser.parse ~ Index } map { case (from, diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TemplateParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TemplateParser.scala index 34584e6f..de0fd5de 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TemplateParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TemplateParser.scala @@ -17,7 +17,7 @@ private object TemplateParser { ParameterParser.parseOrFail.? ~ SpaceParser.parseOrFail.? ~ inheritance.rep ~ - BlockParser.clause(required = true) ~ + BlockParser.parse ~ Index } map { case (from, templateType, preIdentifierSpace, identifier, preParamSpace, params, postParamSpace, inheritance, block, to) => diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/WhileLoopParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/WhileLoopParser.scala index e000326e..b7d75c8c 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/WhileLoopParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/WhileLoopParser.scala @@ -18,7 +18,7 @@ private object WhileLoopParser { SpaceParser.parseOrFail.? ~ TokenParser.parse(Token.CloseParen) ~ SpaceParser.parseOrFail.? ~ - BlockParser.clause(required = true) ~ + BlockParser.parse ~ Index } map { case (from, whileToken, postWhileSpace, openParen, postOpenParenSpace, expression, postExpressionSpace, closeParen, postCloseParenSpace, block, to) => 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 236be2f3..05d99264 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 @@ -48,8 +48,8 @@ object TestParser { def parseTuple(code: String): SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type] = runSoftParser(ParameterParser.parse(_))(code) - def parseBlockClause(mandatory: Boolean)(code: String): SoftAST.BlockClause = - runSoftParser(BlockParser.clause(mandatory)(_))(code) + def parseBlockClause(required: Boolean)(code: String): SoftAST.BlockClause = + runSoftParser(BlockParser.parse(required)(_))(code) def parseBlockBody(code: String): SoftAST.BlockBody = runSoftParser(BlockParser.body(_))(code) From e369715060445c838d7c86c15e23386a768ebe27 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 14:04:52 +1100 Subject: [PATCH 12/19] allow `!` within identifiers --- .../lsp/access/compiler/parser/soft/IdentifierParser.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParser.scala index 53506c7e..a4840b65 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParser.scala @@ -58,7 +58,7 @@ private object IdentifierParser { private def isDevDefinedName[Unknown: P]: P[Unit] = CharsWhile { char => - char.isLetterOrDigit || Token.Underscore.lexeme.contains(char) + char.isLetterOrDigit || Token.Underscore.lexeme.contains(char) || Token.Exclamation.lexeme.contains(char) } } From 72f7bb18e1948af45cbe3339eaa8c0fa593dcaaf Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 14:15:18 +1100 Subject: [PATCH 13/19] - remove `parseSelective` from `ExpressionParser` - update `TypeAssignmentParser` - Narrow executed parsers for `MethodCall`s left expression --- .../parser/soft/ExpressionParser.scala | 64 +++---------------- .../parser/soft/MethodCallParser.scala | 14 +++- .../parser/soft/TypeAssignmentParser.scala | 27 ++++++-- .../compiler/parser/soft/ast/SoftAST.scala | 3 +- .../compiler/parser/soft/TestParser.scala | 3 + .../soft/TypeAssignmentParserSpec.scala | 48 ++++++++++++++ 6 files changed, 93 insertions(+), 66 deletions(-) create mode 100644 compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParserSpec.scala 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 95f49e8d..743330f0 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 @@ -24,30 +24,9 @@ import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.SoftAST private object ExpressionParser { def parse[Unknown: P]: P[SoftAST.ExpressionAST] = - parseSelective( - parseInfix = true, - parseMethodCall = true, - parseAssignment = true - ) - - def parseOrFail[Unknown: P]: P[SoftAST.ExpressionAST] = - parseOrFailSelective( - parseInfix = true, - parseMethodCall = true, - parseAssignment = true - ) - - def parseSelective[Unknown: P]( - parseInfix: Boolean, - parseMethodCall: Boolean, - parseAssignment: Boolean): P[SoftAST.ExpressionAST] = P { Index ~ - parseOrFailSelective( - parseInfix = parseInfix, - parseMethodCall = parseMethodCall, - parseAssignment = parseAssignment - ).? ~ + parseOrFail.? ~ Index } map { case (_, Some(expression), _) => @@ -57,45 +36,18 @@ private object ExpressionParser { SoftAST.ExpressionExpected(range(from, to)) } - def parseOrFailSelective[Unknown: P]( - parseInfix: Boolean, - parseMethodCall: Boolean, - parseAssignment: Boolean): P[SoftAST.ExpressionAST] = { - def infixOrFail() = - if (parseInfix) - InfixCallParser.parseOrFail - else - Fail(s"${InfixCallParser.productPrefix} ignored") - - def methodCallOrFail() = - if (parseMethodCall) - MethodCallParser.parseOrFail - else - Fail(s"${MethodCallParser.productPrefix} ignored") - - def assignmentOrFail() = - if (parseAssignment) - AssignmentParser.parseOrFail - else - Fail(s"${AssignmentParser.productPrefix} ignored") - - P { - assignmentOrFail() | - infixOrFail() | - methodCallOrFail() | - common - } - } - - private def common[Unknown: P]: P[SoftAST.ExpressionAST] = + def parseOrFail[Unknown: P]: P[SoftAST.ExpressionAST] = P { - ReturnStatementParser.parseOrFail | + TypeAssignmentParser.parseOrFail | + AssignmentParser.parseOrFail | + InfixCallParser.parseOrFail | + MethodCallParser.parseOrFail | + BlockParser.parseOrFail | + ReturnStatementParser.parseOrFail | ForLoopParser.parseOrFail | WhileLoopParser.parseOrFail | VariableDeclarationParser.parseOrFail | MutableBindingParser.parseOrFail | - TypeAssignmentParser.parseOrFail | - BlockParser.parseOrFail | ReferenceCallParser.parseOrFail | AnnotationParser.parseOrFail | ParameterParser.parseOrFail | diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MethodCallParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MethodCallParser.scala index fe86fbb6..27ec4613 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MethodCallParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MethodCallParser.scala @@ -10,7 +10,7 @@ private case object MethodCallParser { def parseOrFail[Unknown: P]: P[SoftAST.MethodCall] = P { Index ~ - ExpressionParser.parseOrFailSelective(parseInfix = false, parseMethodCall = false, parseAssignment = false) ~ + leftExpression ~ SpaceParser.parseOrFail.? ~ dotCall.rep(1) ~ Index @@ -41,4 +41,16 @@ private case object MethodCallParser { ) } + private def leftExpression[Unknown: P]: P[SoftAST.ExpressionAST] = + P { + VariableDeclarationParser.parseOrFail | + MutableBindingParser.parseOrFail | + ReferenceCallParser.parseOrFail | + ParameterParser.parseOrFail | + NumberParser.parseOrFail | + BooleanParser.parseOrFail | + BStringParser.parseOrFail | + IdentifierParser.parseOrFail + } + } diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParser.scala index c371d8aa..82d688ed 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParser.scala @@ -2,7 +2,7 @@ package org.alephium.ralph.lsp.access.compiler.parser.soft import fastparse._ import fastparse.NoWhitespace.noWhitespaceImplicit -import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.range +import org.alephium.ralph.lsp.access.compiler.message.SourceIndexExtra.{point, range} import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} private object TypeAssignmentParser { @@ -10,24 +10,37 @@ private object TypeAssignmentParser { def parseOrFail[Unknown: P]: P[SoftAST.TypeAssignment] = P { Index ~ - AssignmentAccessModifierParser.parseOrFail.rep ~ - IdentifierParser.parseOrFail ~ + leftExpression ~ SpaceParser.parseOrFail.? ~ TokenParser.parseOrFail(Token.Colon) ~ SpaceParser.parseOrFail.? ~ ExpressionParser.parse ~ Index } map { - case (from, access, identifier, postIdentifierSpace, equalToken, postEqualSpace, expression, to) => + case (from, left, postIdentifierSpace, equalToken, postEqualSpace, right, to) => SoftAST.TypeAssignment( index = range(from, to), - modifiers = access, - name = identifier, + name = left, preColonSpace = postIdentifierSpace, colon = equalToken, postColonSpace = postEqualSpace, - tpe = expression + tpe = right ) } + private def leftExpression[Unknown: P]: P[SoftAST.ExpressionAST] = + P(Index ~ leftExpressionOrFail.?) map { + case (_, Some(expression)) => + expression + + case (from, None) => + SoftAST.ExpressionExpected(point(from)) + } + + private def leftExpressionOrFail[Unknown: P] = + P { + MutableBindingParser.parseOrFail | + 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 d78352a5..9f1bc921 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 @@ -390,8 +390,7 @@ object SoftAST { case class TypeAssignment( index: SourceIndex, - modifiers: Seq[SoftAST.AssignmentAccessModifier], - name: IdentifierAST, + name: ExpressionAST, preColonSpace: Option[Space], colon: TokenDocumented[Token.Colon.type], postColonSpace: Option[Space], 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 05d99264..94ec44cf 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 @@ -88,6 +88,9 @@ object TestParser { def parseStructTemplate(code: String): SoftAST.StructTemplate = runSoftParser(StructTemplateParser.parseOrFail(_))(code) + def parseTypeAssignment(code: String): SoftAST.TypeAssignment = + runSoftParser(TypeAssignmentParser.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/TypeAssignmentParserSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParserSpec.scala new file mode 100644 index 00000000..0237a4e5 --- /dev/null +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/TypeAssignmentParserSpec.scala @@ -0,0 +1,48 @@ +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.SoftAST +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 + +class TypeAssignmentParserSpec extends AnyWordSpec { + + "report error" when { + "type name is not supplied" in { + val assignment = + parseTypeAssignment(": Type") + + assignment shouldBe + SoftAST.TypeAssignment( + index = indexOf(">>: Type<<"), + name = SoftAST.ExpressionExpected(indexOf(">><<: Type")), + preColonSpace = None, + colon = Colon(indexOf(">>:<< Type")), + postColonSpace = Some(SpaceOne(indexOf(":>> <>Type<<"), "Type") + ) + } + } + + "success" when { + "type assignment is fully defined" when { + "defined as identifier" in { + val assignment = + parseTypeAssignment("name : Type") + + assignment shouldBe + SoftAST.TypeAssignment( + index = indexOf(">>name : Type<<"), + name = Identifier(indexOf(">>name<< : Type"), "name"), + preColonSpace = Some(SpaceOne(indexOf("name>> <<: Type"))), + colon = Colon(indexOf("name >>:<< Type")), + postColonSpace = Some(SpaceOne(indexOf("name :>> <>Type<<"), "Type") + ) + } + } + } + +} From 31cba1ec10e19c87f454a23cc1c5efcb44af8cee Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 14:17:37 +1100 Subject: [PATCH 14/19] private `parser(required: Boolean)` --- .../lsp/access/compiler/parser/soft/BlockParser.scala | 8 ++++---- .../lsp/access/compiler/parser/soft/TestParser.scala | 3 --- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala index 6a6a0278..67b690c0 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala @@ -29,7 +29,10 @@ private object BlockParser { def parse[Unknown: P]: P[SoftAST.BlockClause] = parse(required = true) - def parse[Unknown: P](required: Boolean): P[SoftAST.BlockClause] = + def body[Unknown: P]: P[SoftAST.BlockBody] = + body() + + private def parse[Unknown: P](required: Boolean): P[SoftAST.BlockClause] = P { Index ~ TokenParser.parse(required, Token.OpenCurly) ~ @@ -50,9 +53,6 @@ private object BlockParser { ) } - def body[Unknown: P]: P[SoftAST.BlockBody] = - body() - private def body[Unknown: P](stop: Token*): P[SoftAST.BlockBody] = P { Index ~ 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 94ec44cf..066b8ca7 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 @@ -48,9 +48,6 @@ object TestParser { def parseTuple(code: String): SoftAST.Group[Token.OpenParen.type, Token.CloseParen.type] = runSoftParser(ParameterParser.parse(_))(code) - def parseBlockClause(required: Boolean)(code: String): SoftAST.BlockClause = - runSoftParser(BlockParser.parse(required)(_))(code) - def parseBlockBody(code: String): SoftAST.BlockBody = runSoftParser(BlockParser.body(_))(code) From 8746c0d411127c06a0b9804889375bd5472e76e3 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 14:29:48 +1100 Subject: [PATCH 15/19] document `SoftAST.Group` --- .../access/compiler/parser/soft/ast/SoftAST.scala | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) 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 9f1bc921..dbc5f3a2 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 @@ -233,7 +233,16 @@ object SoftAST { returned: FunctionReturnAST) extends SoftAST - /** Multiple arguments. Syntax: (arg1, (arg2, arg3)) */ + /** + * Represents a comma separated list of expressions. + * + * This list of expressions is parsed by the following syntax: + * - Struct `{ a, b: Type, mut c: C }` + * - Annotation `@using(a = b)` + * - Contract & TxScript etc `(a, b, c)` + * - fn `(a: Type, b: Type, c)` + * - `enum` etc + */ case class Group[O <: Token, C <: Token]( index: SourceIndex, openToken: TokenDocExpectedAST[O], @@ -244,7 +253,7 @@ object SoftAST { closeToken: TokenDocExpectedAST[C]) extends ExpressionAST - /** Syntax: (arg1, >>arg2, (arg3, arg4)<<) */ + /** Comma separated tail expressions of a [[Group]] */ case class GroupTail( index: SourceIndex, comma: TokenDocumented[Token.Comma.type], From 8183afea78cd662b94363d70ea1939573efb485e Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 14:32:21 +1100 Subject: [PATCH 16/19] fix test file names --- .../soft/{AnnotationSpec.scala => AnnotationParserSpec.scala} | 2 +- .../soft/{AssignmentSpec.scala => AssignmentParserSpec.scala} | 2 +- .../parser/soft/{BStringSpec.scala => BStringParserSpec.scala} | 2 +- .../parser/soft/{CommentSpec.scala => CommentParserSpec.scala} | 2 +- .../parser/soft/{GroupSpec.scala => GroupParserSpec.scala} | 2 +- .../soft/{IdentifierSpec.scala => IdentifierParserSpec.scala} | 2 +- ...{MutableBindingSpec.scala => MutableBindingParserSpec.scala} | 2 +- ...eclarationSpec.scala => VariableDeclarationParserSpec.scala} | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{AnnotationSpec.scala => AnnotationParserSpec.scala} (98%) rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{AssignmentSpec.scala => AssignmentParserSpec.scala} (98%) rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{BStringSpec.scala => BStringParserSpec.scala} (98%) rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{CommentSpec.scala => CommentParserSpec.scala} (98%) rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{GroupSpec.scala => GroupParserSpec.scala} (99%) rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{IdentifierSpec.scala => IdentifierParserSpec.scala} (93%) rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{MutableBindingSpec.scala => MutableBindingParserSpec.scala} (98%) rename compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/{VariableDeclarationSpec.scala => VariableDeclarationParserSpec.scala} (98%) diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationParserSpec.scala similarity index 98% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationParserSpec.scala index c5c8cb6e..a40a6b20 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AnnotationParserSpec.scala @@ -25,7 +25,7 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec import org.scalatest.OptionValues._ -class AnnotationSpec extends AnyWordSpec with Matchers { +class AnnotationParserSpec extends AnyWordSpec with Matchers { "error cases" should { "report missing identifier" in { diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParserSpec.scala similarity index 98% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParserSpec.scala index a8ee41fc..88a969fa 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/AssignmentParserSpec.scala @@ -23,7 +23,7 @@ import org.alephium.ralph.lsp.access.util.TestCodeUtil._ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec -class AssignmentSpec extends AnyWordSpec with Matchers { +class AssignmentParserSpec extends AnyWordSpec with Matchers { "assignments to an identifier" should { "report ExpressionExpected" when { diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BStringSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BStringParserSpec.scala similarity index 98% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BStringSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BStringParserSpec.scala index 71c8cf2a..2da2a443 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BStringSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BStringParserSpec.scala @@ -9,7 +9,7 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec import org.scalatest.OptionValues._ -class BStringSpec extends AnyWordSpec with Matchers { +class BStringParserSpec extends AnyWordSpec with Matchers { "b alone" should { "not parse as String literal" in { diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CommentSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CommentParserSpec.scala similarity index 98% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CommentSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CommentParserSpec.scala index 1f16fa9c..a8715eef 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CommentSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/CommentParserSpec.scala @@ -23,7 +23,7 @@ import org.alephium.ralph.lsp.access.util.TestCodeUtil._ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec -class CommentSpec extends AnyWordSpec with Matchers { +class CommentParserSpec extends AnyWordSpec with Matchers { "no text comment" should { "store empty comment" in { diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParserSpec.scala similarity index 99% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParserSpec.scala index 08468331..866d2322 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParserSpec.scala @@ -24,7 +24,7 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec import org.scalatest.OptionValues._ -class GroupSpec extends AnyWordSpec with Matchers { +class GroupParserSpec extends AnyWordSpec with Matchers { "missing opening paren" in { val tuple = diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParserSpec.scala similarity index 93% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParserSpec.scala index 3eebf0fa..fe0b019f 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/IdentifierParserSpec.scala @@ -6,7 +6,7 @@ import org.alephium.ralph.lsp.access.util.TestFastParse._ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec -class IdentifierSpec extends AnyWordSpec with Matchers { +class IdentifierParserSpec extends AnyWordSpec with Matchers { "disallow reserved tokens to be used as identifier" when { val reserved = diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingParserSpec.scala similarity index 98% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingParserSpec.scala index aebb53af..098809ce 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/MutableBindingParserSpec.scala @@ -24,7 +24,7 @@ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec import org.scalatest.OptionValues._ -class MutableBindingSpec extends AnyWordSpec with Matchers { +class MutableBindingParserSpec extends AnyWordSpec with Matchers { "succeed" when { "an identifier is set a mut" in { diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationParserSpec.scala similarity index 98% rename from compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationSpec.scala rename to compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationParserSpec.scala index 3b4b0f3d..fe275a00 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/VariableDeclarationParserSpec.scala @@ -27,7 +27,7 @@ import org.scalatest.TryValues.convertTryToSuccessOrFailure import scala.util.Try -class VariableDeclarationSpec extends AnyWordSpec with Matchers { +class VariableDeclarationParserSpec extends AnyWordSpec with Matchers { "succeed" when { "full valid variable declaration is defined" in { From 795814368a60b77df54060df038027f564e84cad Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 15:20:25 +1100 Subject: [PATCH 17/19] fix doc --- .../lsp/access/compiler/parser/soft/ast/SoftAST.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 dbc5f3a2..bed9fa27 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 @@ -237,11 +237,11 @@ object SoftAST { * Represents a comma separated list of expressions. * * This list of expressions is parsed by the following syntax: - * - Struct `{ a, b: Type, mut c: C }` - * - Annotation `@using(a = b)` - * - Contract & TxScript etc `(a, b, c)` - * - fn `(a: Type, b: Type, c)` - * - `enum` etc + * - Struct `{ a, b: Type, mut c: C }` + * - Annotation `@using(a = b)` + * - Contract & TxScript etc `(a, b, c)` + * - fn `(a: Type, b: Type, c)` + * - `enum` etc */ case class Group[O <: Token, C <: Token]( index: SourceIndex, From 5bf42eaa120f0c034122737bad3eef40c9da30d3 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 15:20:47 +1100 Subject: [PATCH 18/19] fix doc --- .../ralph/lsp/access/compiler/parser/soft/ast/SoftAST.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 bed9fa27..abd22ea3 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 @@ -239,7 +239,7 @@ object SoftAST { * This list of expressions is parsed by the following syntax: * - Struct `{ a, b: Type, mut c: C }` * - Annotation `@using(a = b)` - * - Contract & TxScript etc `(a, b, c)` + * - Contract | TxScript`(a, b, c)` * - fn `(a: Type, b: Type, c)` * - `enum` etc */ From d6ac479873e0f571782d798ddb46511926bc9bb2 Mon Sep 17 00:00:00 2001 From: simerplaha Date: Mon, 20 Jan 2025 15:41:01 +1100 Subject: [PATCH 19/19] test --- .../compiler/parser/soft/BlockParser.scala | 6 ++-- .../compiler/parser/soft/GroupParser.scala | 17 +++++---- .../parser/soft/GroupParserSpec.scala | 35 +++++++++++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala index 67b690c0..32a3fde0 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/BlockParser.scala @@ -23,12 +23,12 @@ import org.alephium.ralph.lsp.access.compiler.parser.soft.ast.{SoftAST, Token} private object BlockParser { - def parseOrFail[Unknown: P]: P[SoftAST.BlockClause] = - parse(required = false) - def parse[Unknown: P]: P[SoftAST.BlockClause] = parse(required = true) + def parseOrFail[Unknown: P]: P[SoftAST.BlockClause] = + parse(required = false) + def body[Unknown: P]: P[SoftAST.BlockBody] = body() diff --git a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala index 0c81f4f2..99358dc1 100644 --- a/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala +++ b/compiler-access/src/main/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParser.scala @@ -74,9 +74,9 @@ private object GroupParser { TokenParser.parse(required, open) ~ SpaceParser.parseOrFail.? ~ Index ~ - expression.? ~ + expression(open, close).? ~ SpaceParser.parseOrFail.? ~ - tail.rep ~ + tail(open, close).rep ~ TokenParser.parse(close) ~ Index } map { @@ -108,12 +108,14 @@ private object GroupParser { * * @return An instance of [[SoftAST.GroupTail]]. */ - private def tail[Unknown: P]: P[SoftAST.GroupTail] = + private def tail[Unknown: P, O <: Token, C <: Token]( + open: O, + close: C): P[SoftAST.GroupTail] = P { Index ~ TokenParser.parseOrFail(Token.Comma) ~ SpaceParser.parseOrFail.? ~ - expression ~ + expression(open, close) ~ SpaceParser.parseOrFail.? ~ Index } map { @@ -127,9 +129,12 @@ private object GroupParser { ) } - private def expression[Unknown: P]: P[SoftAST.ExpressionAST] = + private def expression[Unknown: P, O <: Token, C <: Token]( + open: O, + close: C): P[SoftAST.ExpressionAST] = P { - TypeAssignmentParser.parseOrFail | + GroupParser.parseOrFail(open, close) | + TypeAssignmentParser.parseOrFail | AssignmentParser.parseOrFail | InfixCallParser.parseOrFail | MethodCallParser.parseOrFail | diff --git a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParserSpec.scala b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParserSpec.scala index 866d2322..a5ff15ef 100644 --- a/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParserSpec.scala +++ b/compiler-access/src/test/scala/org/alephium/ralph/lsp/access/compiler/parser/soft/GroupParserSpec.scala @@ -192,4 +192,39 @@ class GroupParserSpec extends AnyWordSpec with Matchers { bbb.tpe.toCode() shouldBe "(tuple1, tuple2)" } + "nested tuples" in { + val tuple = parseTuple("(a, (b, c))") + + tuple.headExpression.value shouldBe a[SoftAST.Identifier] + + tuple.tailExpressions should have size 1 + val lastTuple = tuple.tailExpressions.head + + lastTuple shouldBe + SoftAST.GroupTail( + index = indexOf("(a>>, (b, c)<<)"), + comma = Comma(indexOf("(a>>,<< (b, c))")), + preExpressionSpace = Some(SpaceOne(indexOf("(a,>> <<(b, c))"))), + expression = SoftAST.Group( + index = indexOf("(a, >>(b, c)<<)"), + openToken = OpenParen(indexOf("(a, >>(<>b<<, c))"), "b")), + postHeadExpressionSpace = None, + tailExpressions = Seq( + SoftAST.GroupTail( + index = indexOf("(a, (b>>, c<<))"), + comma = Comma(indexOf("(a, (b>>,<< c))")), + preExpressionSpace = Some(SpaceOne(indexOf("(a, (b,>> <>c<<))"), "c"), + postExpressionSpace = None + ) + ), + closeToken = CloseParen(indexOf("(a, (b, c>>)<<)")) + ), + postExpressionSpace = None + ) + + } + }