From 4c3c32b7c400e87f962dc9827892a9224765e2a4 Mon Sep 17 00:00:00 2001 From: InversionSpaces Date: Tue, 25 Jul 2023 12:09:51 +0200 Subject: [PATCH] fix(compiler): Fix `if` with brackets parsing (#812) --- .../aqua/parser/expr/func/ArrowExpr.scala | 4 ++- .../test/scala/aqua/parser/FuncExprSpec.scala | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/parser/src/main/scala/aqua/parser/expr/func/ArrowExpr.scala b/parser/src/main/scala/aqua/parser/expr/func/ArrowExpr.scala index 64ffb14f4..01800d07f 100644 --- a/parser/src/main/scala/aqua/parser/expr/func/ArrowExpr.scala +++ b/parser/src/main/scala/aqua/parser/expr/func/ArrowExpr.scala @@ -24,8 +24,10 @@ object ArrowExpr extends Expr.AndIndented { PushToStreamExpr :: ForExpr :: Expr.defer(OnExpr) :: - CallArrowExpr :: + // It is important for IfExpr to be before CallArrowExpr + // because `if (1 + 1) == 2` is parsed as if `if(1 + 1)` is an arrow call IfExpr :: + CallArrowExpr :: TryExpr :: ElseOtherwiseExpr :: CatchExpr :: diff --git a/parser/src/test/scala/aqua/parser/FuncExprSpec.scala b/parser/src/test/scala/aqua/parser/FuncExprSpec.scala index aefdaaa18..1153ee9b1 100644 --- a/parser/src/test/scala/aqua/parser/FuncExprSpec.scala +++ b/parser/src/test/scala/aqua/parser/FuncExprSpec.scala @@ -16,6 +16,7 @@ import aqua.parser.lift.LiftParser.Implicits.idLiftParser import aqua.types.ScalarType.* import cats.Id import cats.data.{Chain, NonEmptyList} +import cats.data.Chain.* import cats.free.Cofree import cats.syntax.foldable.* import cats.data.Validated.{Invalid, Valid} @@ -23,6 +24,7 @@ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.{Inside, Inspectors} import org.scalatest.matchers.should.Matchers import cats.~> +import cats.Eval import scala.collection.mutable import scala.language.implicitConversions @@ -286,4 +288,27 @@ class FuncExprSpec extends AnyFlatSpec with Matchers with Inside with Inspectors parser.parseAll(script).value.toEither.isRight shouldBe true } + + "function with if" should "be parsed correctly" in { + val script = + """func ifTest(): + | if (1 + 1) == 2: + | Test.test("one") + | + | if 2 < 3 != (1 > 2): + | Test.test("two") + |""".stripMargin + + inside(parser.parseAll(script).value) { case Valid(ast) => + ast + .cata[Int]((expr, results) => + // Count `if`s inside the tree + Eval.later(results.sumAll + (expr match { + case IfExpr(_, _, _) => 1 + case _ => 0 + })) + ) + .value shouldBe 2 + } + } }