Parser refactoring (#104)

This commit is contained in:
Dima 2021-05-05 10:47:55 +03:00 committed by GitHub
parent 450fe4e142
commit 3066e390b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 140 additions and 134 deletions

View File

@ -1,61 +1,8 @@
service Peer("peer"):
is_connected: string -> bool
service Test("123"):
doSomething: -> ()
service Op("op"):
identity: -> ()
data User:
peer_id: string
relay_id: string
name: string
service Test("test"):
getUserList: -> []User
doSomething: -> bool
check: bool -> ()
log: string -> ()
getString: string -> string
func initAfterJoin(me: User) -> []User:
allUsers <- Test.getUserList()
for user <- allUsers par:
on user.relay_id:
isOnline <- Peer.is_connected(user.peer_id)
if isOnline:
on user.peer_id via user.relay_id:
func b(me: string, a: bool, b: bool):
on me:
if a:
if b:
Test.doSomething()
else:
on user.peer_id via user.relay_id:
Op.identity()
par Test.doSomething()
<- allUsers
func handleArr(arr: []bool):
for b <- arr:
Test.check(b)
func checkStreams(ch: []string) -> []bool:
stream: *bool
stream <- Peer.is_connected("write once")
stream <- Peer.is_connected("write twice")
for b <- ch:
on b:
stream <- Peer.is_connected(b)
handleArr(stream)
<- stream
func test(user: string, relay_id: string) -> string:
on relay_id:
Peer.is_connected("on relay_id")
on user:
Peer.is_connected("on user")
par Peer.is_connected("par on init peer")
<- ""
-- should fail, as using str2 in parallel
func topologyTest(friend: string, friendRelay: string) -> string:
on friend via friendRelay:
str2 <- Test.getString("friends string via")
par Test.log(str2)
<- "finish"

View File

@ -1,13 +1,15 @@
package aqua
import aqua.parser.Ast
import cats.data.ValidatedNec
import aqua.parser.lift.{FileSpan, LiftParser, Span}
import cats.data.ValidatedNec
object Aqua {
def parseString(input: String): ValidatedNec[AquaError, Ast[Span.F]] =
Ast.fromString[Span.F](input).leftMap(_.map(pe => SyntaxError(pe.failedAtOffset, pe.expected)))
Ast
.fromString[Span.F](input)
.leftMap(_.map(pe => SyntaxError(pe.failedAtOffset, pe.expected)))
def parseFileString(name: String, input: String): ValidatedNec[AquaError, Ast[FileSpan.F]] = {
implicit val fileLift: LiftParser[FileSpan.F] = FileSpan.fileSpanLiftParser(name, input)

View File

@ -24,32 +24,37 @@ object Expr {
override def ast[F[_]: LiftParser: Comonad](ps: Indent): P[Tree[F]] = companion.ast[F](ps)
}
abstract class And(thenInline: List[Expr.Companion], orIndented: List[Expr.Companion])
extends Companion {
override def ast[F[_]: LiftParser: Comonad](ps: Indent): P[Ast.Tree[F]] =
(p[F] ~ ((` `.backtrack *> P
.oneOf(thenInline.map(_.ast[F](ps).backtrack))
.map(Chain.one)) | (` : \n+` *> indented(
s => {
val psI = ps.copy(indent = s)
P.oneOf(orIndented.map(_.ast[F](psI).backtrack))
},
ps.indent
)).map(_.toList).map(Chain.fromSeq))).map { case (expr, internal) =>
Cofree[Chain, Expr[F]](expr, Eval.now(internal))
}
}
abstract class Leaf extends Companion {
override def ast[F[_]: LiftParser: Comonad](ps: Indent): P[Ast.Tree[F]] =
p[F].map(Cofree[Chain, Expr[F]](_, Eval.now(Chain.empty)))
}
abstract class AndThen(headExpr: Companion, oneOfExprs: Companion*)
extends And(thenInline = headExpr :: oneOfExprs.toList, orIndented = Nil)
trait And extends Companion {
def validChildren: List[Companion]
}
abstract class AndIndented(headExpr: Companion, oneOfExprs: Companion*)
extends And(thenInline = Nil, orIndented = headExpr :: oneOfExprs.toList)
abstract class AndThen extends And {
override def ast[F[_]: LiftParser: Comonad](ps: Indent): P[Ast.Tree[F]] =
(p[F] ~ (` *` *> P
.oneOf(validChildren.map(_.ast[F](ps)))
.map(Chain.one))).map { case (expr, internal) =>
Cofree[Chain, Expr[F]](expr, Eval.now(internal))
}
}
abstract class AndIndented extends And {
override def ast[F[_]: LiftParser: Comonad](ps: Indent): P[Ast.Tree[F]] =
(p[F] ~ (` : \n+` *> indented(
s => {
val psI = ps.copy(indent = s)
P.oneOf(validChildren.map(_.ast[F](psI).backtrack))
},
ps.indent
)).map(_.toList).map(Chain.fromSeq)).map { case (expr, internal) =>
Cofree[Chain, Expr[F]](expr, Eval.now(internal))
}
}
}

View File

@ -9,7 +9,9 @@ import cats.parse.Parser
case class DataStructExpr[F[_]](name: CustomTypeToken[F]) extends Expr[F]
object DataStructExpr extends Expr.AndIndented(FieldTypeExpr) {
object DataStructExpr extends Expr.AndIndented {
override def validChildren: List[Expr.Companion] = List(FieldTypeExpr)
override def p[F[_]: LiftParser: Comonad]: Parser[DataStructExpr[F]] =
`data` *> ` ` *> CustomTypeToken.ct[F].map(DataStructExpr(_))

View File

@ -1,15 +1,26 @@
package aqua.parser.expr
import aqua.parser.Expr
import aqua.parser.lexer.Token._
import aqua.parser.lift.LiftParser
import aqua.parser.lift.LiftParser._
import cats.Comonad
import cats.parse.Parser
import aqua.parser.lexer.Token._
case class ElseOtherwiseExpr[F[_]](point: F[Unit]) extends Expr[F]
object ElseOtherwiseExpr extends Expr.AndIndented(Expr.defer(OnExpr), ParExpr, CallArrowExpr, AbilityIdExpr, ForExpr) {
object ElseOtherwiseExpr extends Expr.AndIndented {
override def validChildren: List[Expr.Companion] =
List(
Expr.defer(OnExpr),
ParExpr,
CallArrowExpr,
AbilityIdExpr,
Expr.defer(ForExpr),
Expr.defer(IfExpr),
Expr.defer(ElseOtherwiseExpr)
)
override def p[F[_]: LiftParser: Comonad]: Parser[ElseOtherwiseExpr[F]] =
(`else` | `otherwise`).lift.map(ElseOtherwiseExpr(_))

View File

@ -1,24 +1,26 @@
package aqua.parser.expr
import aqua.parser.Expr
import aqua.parser.lexer.Token._
import aqua.parser.lexer.{Name, Value}
import aqua.parser.lift.LiftParser
import aqua.parser.lift.LiftParser._
import cats.Comonad
import cats.parse.{Parser => P}
import aqua.parser.lexer.Token._
import LiftParser._
case class ForExpr[F[_]](item: Name[F], iterable: Value[F], par: Option[F[Unit]]) extends Expr[F]
object ForExpr
extends Expr.AndIndented(
Expr.defer(OnExpr),
ParExpr,
CallArrowExpr,
AbilityIdExpr,
Expr.defer(IfExpr),
Expr defer ElseOtherwiseExpr
) {
object ForExpr extends Expr.AndIndented {
override def validChildren: List[Expr.Companion] = List(
Expr.defer(OnExpr),
ParExpr,
Expr.defer(ForExpr),
CallArrowExpr,
AbilityIdExpr,
Expr.defer(IfExpr),
Expr.defer(ElseOtherwiseExpr)
)
override def p[F[_]: LiftParser: Comonad]: P[ForExpr[F]] =
((`for` *> ` ` *> Name.p[F] <* ` <- `) ~ Value.`value`[F] ~ (` ` *> `par`.lift).?).map {

View File

@ -1,13 +1,13 @@
package aqua.parser.expr
import aqua.parser.Ast.Tree
import aqua.parser.{Expr, Indent}
import aqua.parser.lexer.Token._
import aqua.parser.lexer.{Arg, DataTypeToken, Name, Value}
import aqua.parser.lift.LiftParser
import aqua.parser.{Expr, Indent}
import cats.Comonad
import cats.free.Cofree
import cats.parse.Parser
import cats.Comonad
case class FuncExpr[F[_]](
name: Name[F],
@ -16,18 +16,19 @@ case class FuncExpr[F[_]](
retValue: Option[Value[F]]
) extends Expr[F]
object FuncExpr
extends Expr.AndIndented(
OnExpr,
AbilityIdExpr,
ReturnExpr,
CallArrowExpr,
ParExpr,
ForExpr,
IfExpr,
ElseOtherwiseExpr,
DeclareStreamExpr
) {
object FuncExpr extends Expr.AndIndented {
override def validChildren: List[Expr.Companion] = List(
OnExpr,
AbilityIdExpr,
ReturnExpr,
CallArrowExpr,
ParExpr,
ForExpr,
IfExpr,
ElseOtherwiseExpr,
DeclareStreamExpr
)
override def p[F[_]: LiftParser: Comonad]: Parser[FuncExpr[F]] =
((`func` *> ` ` *> Name.p[F]) ~ comma0(Arg.p)

View File

@ -1,17 +1,27 @@
package aqua.parser.expr
import aqua.parser.Expr
import aqua.parser.lexer.{EqOp, Literal, Value}
import cats.parse.{Parser => P}
import aqua.parser.lexer.Token._
import aqua.parser.lexer.{EqOp, Literal, Value}
import aqua.parser.lift.LiftParser
import aqua.types.LiteralType
import cats.Comonad
import cats.parse.{Parser => P}
case class IfExpr[F[_]](left: Value[F], eqOp: EqOp[F], right: Value[F]) extends Expr[F]
object IfExpr
extends Expr.AndIndented(Expr.defer(OnExpr), ParExpr, CallArrowExpr, AbilityIdExpr, ForExpr) {
object IfExpr extends Expr.AndIndented {
override def validChildren: List[Expr.Companion] =
List(
Expr.defer(OnExpr),
ParExpr,
CallArrowExpr,
AbilityIdExpr,
Expr.defer(ForExpr),
Expr.defer(IfExpr),
Expr.defer(ElseOtherwiseExpr)
)
override def p[F[_]: LiftParser: Comonad]: P[IfExpr[F]] =
(`if` *> ` ` *> Value.`value`[F] ~ (` ` *> EqOp.p[F] ~ (` ` *> Value.`value`[F])).?).map {

View File

@ -9,10 +9,22 @@ import cats.parse.{Parser => P}
case class OnExpr[F[_]](peerId: Value[F], via: List[Value[F]]) extends Expr[F]
object OnExpr extends Expr.AndIndented(CallArrowExpr, AbilityIdExpr, IfExpr, ElseOtherwiseExpr) {
object OnExpr extends Expr.AndIndented {
override def validChildren: List[Expr.Companion] =
List(
Expr.defer(OnExpr),
ParExpr,
CallArrowExpr,
AbilityIdExpr,
Expr.defer(ForExpr),
Expr.defer(IfExpr),
Expr.defer(ElseOtherwiseExpr)
)
override def p[F[_]: LiftParser: Comonad]: P[OnExpr[F]] =
(`on` *> ` ` *> Value.`value`[F] ~ (` ` *> `via` *> ` ` *> Value.`value`[F]).rep0).map { case (peerId, via) =>
OnExpr(peerId, via)
(`on` *> ` ` *> Value.`value`[F] ~ (` ` *> `via` *> ` ` *> Value.`value`[F]).rep0).map {
case (peerId, via) =>
OnExpr(peerId, via)
}
}

View File

@ -9,7 +9,10 @@ import cats.parse.Parser
case class ParExpr[F[_]](point: F[Unit]) extends Expr[F]
object ParExpr extends Expr.AndThen(Expr.defer(OnExpr), CallArrowExpr, Expr.defer(ForExpr)) {
object ParExpr extends Expr.AndThen {
override def validChildren: List[Expr.Companion] =
List(Expr.defer(OnExpr), CallArrowExpr, Expr.defer(ForExpr))
override def p[F[_]: LiftParser: Comonad]: Parser[ParExpr[F]] =
`par`.lift.map(ParExpr(_))

View File

@ -9,10 +9,13 @@ import cats.parse.Parser
case class ServiceExpr[F[_]](name: Ability[F], id: Option[Value[F]]) extends Expr[F]
object ServiceExpr extends Expr.AndIndented(ArrowTypeExpr) {
object ServiceExpr extends Expr.AndIndented {
override def validChildren: List[Expr.Companion] = List(ArrowTypeExpr)
override def p[F[_]: LiftParser: Comonad]: Parser[ServiceExpr[F]] =
(`service` *> ` ` *> Ability.ab[F] ~ Value.`value`[F].between(`(`, `)`).backtrack.?).map { case (name, id) =>
ServiceExpr(name, id)
(`service` *> ` ` *> Ability.ab[F] ~ Value.`value`[F].between(`(`, `)`).backtrack.?).map {
case (name, id) =>
ServiceExpr(name, id)
}
}

View File

@ -1,13 +1,13 @@
package aqua.parser.lexer
import Token._
import aqua.parser.lexer.Token._
import aqua.parser.lift.LiftParser
import aqua.parser.lift.LiftParser._
import cats.{Comonad, Functor}
import cats.data.NonEmptyList
import cats.parse.{Parser => P}
import cats.syntax.functor._
import cats.syntax.comonad._
import cats.syntax.functor._
import cats.{Comonad, Functor}
sealed trait LambdaOp[F[_]] extends Token[F]
@ -22,9 +22,13 @@ case class IntoArray[F[_]: Functor](override val unit: F[Unit]) extends LambdaOp
}
object LambdaOp {
private def parseField[F[_]: LiftParser: Comonad]: P[LambdaOp[F]] = (`.` *> `name`).lift.map(IntoField(_))
private def parseField[F[_]: LiftParser: Comonad]: P[LambdaOp[F]] =
(`.` *> `name`).lift.map(IntoField(_))
private def parseArr[F[_]: LiftParser: Comonad]: P[LambdaOp[F]] = `*`.lift.map(IntoArray(_))
private def parseOp[F[_]: LiftParser: Comonad]: P[LambdaOp[F]] = P.oneOf(parseField.backtrack :: parseArr :: Nil)
private def parseOp[F[_]: LiftParser: Comonad]: P[LambdaOp[F]] =
P.oneOf(parseField.backtrack :: parseArr :: Nil)
def ops[F[_]: LiftParser: Comonad]: P[NonEmptyList[LambdaOp[F]]] =
parseOp.rep

View File

@ -19,6 +19,7 @@ object Token {
private val anum_ = anum ++ f_
private val nl = Set('\n', '\r')
val ` *` : P0[String] = P.charsWhile0(fSpaces)
val ` ` : P[String] = P.charsWhile(fSpaces)
val `const`: P[Unit] = P.string("const")
val `data`: P[Unit] = P.string("data")
@ -58,13 +59,13 @@ object Token {
val `"` : P[Unit] = P.char('"')
val `*` : P[Unit] = P.char('*')
val `[]` : P[Unit] = P.string("[]")
val `(` : P[Unit] = ` `.?.with1 *> P.char('(') <* ` `.?
val `)` : P[Unit] = ` `.?.with1 *> P.char(')') <* ` `.?
val `(` : P[Unit] = P.char('(').surroundedBy(` `.?)
val `)` : P[Unit] = P.char(')').surroundedBy(` `.?)
val `()` : P[Unit] = P.string("()")
val ` -> ` : P[Unit] = ` `.?.with1 *> P.string("->") <* ` `.?
val ` <- ` : P[Unit] = (` `.?.with1 *> P.string("<-") <* ` `.?).backtrack
val ` -> ` : P[Unit] = P.string("->").surroundedBy(` `.?)
val ` <- ` : P[Unit] = P.string("<-").surroundedBy(` `.?)
val `=` : P[Unit] = P.string("=")
val ` = ` : P[Unit] = (` `.?.with1 *> P.string("=") <* ` `.?).backtrack
val ` = ` : P[Unit] = P.string("=").surroundedBy(` `.?)
val `?` : P[Unit] = P.string("?")
val `<-` : P[Unit] = P.string("<-").backtrack

View File

@ -1,7 +1,7 @@
package aqua.parser.lift
import cats.{Comonad, Eval}
import cats.parse.{LocationMap, Parser => P}
import cats.{Comonad, Eval}
import scala.language.implicitConversions
@ -48,7 +48,9 @@ object Span {
onLeft + s + (" " * (lastNSize - s.length)) + onRight + " "
}
def toConsoleStr(msg: String, onLeft: String, onRight: String = Console.RESET): String =
def toConsoleStr(msg: String, onLeft: String, onRight: String = Console.RESET): String = {
val line3Length = line._3.length
val line3Mult = if (line3Length == 0) 1 else line3Length
pre.map(formatLine(_, onLeft, onRight)).mkString("\n") +
"\n" +
formatLN(line._1, onLeft, onRight) +
@ -60,7 +62,7 @@ object Span {
"\n" +
(" " * (line._2.length + lastNSize + 1)) +
onLeft +
("^" * line._3.length) +
("^" * line3Mult) +
("=" * line._4.length) +
onRight +
"\n" +
@ -70,6 +72,7 @@ object Span {
onRight +
"\n" +
post.map(formatLine(_, onLeft, onRight)).mkString("\n")
}
}
type F[T] = (Span, T)