Literals parsing

This commit is contained in:
dmitry 2021-02-25 14:26:32 +03:00
parent 103203bab0
commit 215866baf0
5 changed files with 106 additions and 59 deletions

View File

@ -3,11 +3,7 @@ package aqua.parse
import aqua.parse.Token._
import cats.data.NonEmptyList
import cats.parse.{Parser P}
// TODO could be const
sealed trait Value
case class VarLambda(name: String, lambda: Option[String]) extends Value
case class Literal(value: String, ts: List[BasicType]) extends Value
import Value.`value`
sealed trait FuncOp
sealed trait InstrOp extends FuncOp
@ -29,17 +25,9 @@ case class AbilityId(ability: String, id: Value) extends AbilityResolve
object FuncOp {
val notLambdaSymbols = Set(' ', ',', '\n', ')', ':')
val varLambda: P[VarLambda] = (`name` ~ (`.` *> P.charsWhile(c !notLambdaSymbols(c))).?).map{
case (n, l) VarLambda(n, l)
}
// TODO parse literals
val value: P[Value] = varLambda
val funcCall: P[FuncCall] =
(`name` ~ P.repSep0(value, `,`).between(`(`, `)`)).map{
(`name` ~ P.repSep0(`value`, `,`).between(`(`, `)`)).map{
case (fnName, args) FuncCall(fnName, args)
}
@ -54,14 +42,14 @@ object FuncOp {
case (v, f) Extract(v, f)
}
val abilityResolve: P[AbilityResolve] = ((`Name` <* ` `) ~ value).map{
val abilityResolve: P[AbilityResolve] = ((`Name` <* ` `) ~ `value`).map{
case (n, v) AbilityId(n, v)
}
// TODO can't be in Par, can be in On
val execOp: P[ExecOp] = P.oneOf( callOp.backtrack :: abilityResolve.backtrack :: extract :: Nil)
val startOn: P[Value] = `on` *> ` ` *> value <* ` `.? <* `:` <* ` \n*`
val startOn: P[Value] = `on` *> ` ` *> `value` <* ` `.? <* `:` <* ` \n*`
val execOn: P[On] =
(startOn ~ indented(execOp)).map{

View File

@ -9,14 +9,18 @@ case class ArrayType(data: DataType) extends DataType
case class CustomType(name: String) extends DataType
case class BasicType(name: String) extends DataType
object BasicType {
val floatS = "f32" :: "f64" :: Nil
val numberS = "s32" :: "s64" :: "i32" :: "i64" :: floatS
val boolS = "bool" :: Nil
val allS = numberS ++ boolS
private val floatS = "f32" :: "f64" :: Nil
private val signedS = "s32" :: "s64" :: floatS
private val numberS = "i32" :: "i64" :: signedS
private val boolS = "bool" :: Nil
private val stringS = "string" :: Nil
private val allS = numberS ++ boolS ++ stringS
val float = floatS.map(BasicType(_))
val signed = signedS.map(BasicType(_))
val number = numberS.map(BasicType(_))
val bool = boolS.map(BasicType(_))
val string = stringS.map(BasicType(_))
val `basictypedef`: P[BasicType] =
P.oneOf(

View File

@ -0,0 +1,37 @@
package aqua.parse
import aqua.parse.Token._
import cats.parse.{Parser P}
import cats.parse.Numbers
sealed trait Value
case class VarLambda(name: String, lambda: Option[String]) extends Value
case class Literal(value: String, ts: List[BasicType]) extends Value
object Value {
val notLambdaSymbols = Set(' ', ',', '\n', ')', ':')
val varLambda: P[VarLambda] = (`name` ~ (`.` *> P.charsWhile(c !notLambdaSymbols(c))).?).map{
case (n, l) VarLambda(n, l)
}
val bool: P[Literal] = P.oneOf( ("true" :: "false" :: Nil).map(t P.string(t).as(Literal(t, BasicType.bool)) ))
val num: P[Literal] = (P.char('-').?.with1 ~ Numbers.nonNegativeIntString).map {
case (Some(_), n) Literal(s"-$n", BasicType.signed)
case (None, n) Literal(n, BasicType.number)
}
val float: P[Literal] =
(P.char('-').?.with1 ~ (Numbers.nonNegativeIntString <* P.char('.')) ~ Numbers.nonNegativeIntString)
.string
.map(Literal(_, BasicType.float))
val string: P[Literal] =
(P.char('"') *> P.repUntil0(P.anyChar, !P.charWhere(_ != '\\') *> P.char('"'))).string.map(Literal(_, BasicType.string))
val literal: P[Literal] = P.oneOf(bool :: float.backtrack :: num :: string :: Nil)
val `value`: P[Value] = P.oneOf(literal.backtrack :: varLambda :: Nil)
}

View File

@ -6,43 +6,6 @@ import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class FuncOpSpec extends AnyFlatSpec with Matchers with EitherValues{
/**
* line variants:
func(...)
x <- func(...)
Ability.func(...)
x <- Ability.func(...)
par line
xor line
on peer:
indented lines*
Ability "const"
Ability service.id
Ability:
// we're on a local node
call smth
res.id
func {Need, x}(y: i32, z: {x}i64 -> Y, p: -> {x}) -> {x}Bool:
Ability keyword, parser
Literal, true/false
AbilityResolve: literal, lens, or arrow that resolves to a string id
try:
...
catch( errn)?:
...
if a == != b:
else:
*/
"func calls" should "parse func()" in {
FuncOp.`funcop`.parseAll("func()") should be(Right(FuncCall("func", Nil)))
@ -81,11 +44,11 @@ else:
"on" should "parse on x: y" in {
val fCall = AbilityFuncCall("Ab", FuncCall("func", Nil))
val extr = Extract("x", fCall)
val call = FuncCall("call", VarLambda("smth", None) :: Nil)
val call = FuncCall("call", Literal("true", BasicType.bool) :: Nil)
val script = """on peer.id:
| x <- Ab.func()
| call(smth)""".stripMargin
| call(true)""".stripMargin
FuncOp.`funcop`.parseAll(script).right.value should be(On(VarLambda("peer", Some("id")), NonEmptyList.of(extr, call)))
}
@ -100,4 +63,27 @@ else:
FuncOp.`funcop`.parseAll(script) should be('right)
}
/*
TODO: xor1
try:
...
catch( errn)?:
...
(next)
*/
/*
TODO: xor2
if a == != b:
...
else:
...
(next)
*/
/*
TODO: ability from lens
*/
/*
TODO: fold, fold par, streams, ...
*/
}

View File

@ -0,0 +1,32 @@
package aqua.parse
import org.scalatest.EitherValues
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
class ValueSpec extends AnyFlatSpec with Matchers with EitherValues {
"var getter" should "parse" in {
Value.`value`.parseAll("varname").right.value should be(VarLambda("varname", None))
Value.`value`.parseAll("varname.field").right.value should be(VarLambda("varname", Some("field")))
Value.`value`.parseAll("varname.field.sub").right.value should be(VarLambda("varname", Some("field.sub")))
}
"literals" should "parse" in {
Value.`value`.parseAll("true").right.value should be(Literal("true", BasicType.bool))
Value.`value`.parseAll("false").right.value should be(Literal("false", BasicType.bool))
Value.`value`.parseAll("1").right.value should be(Literal("1", BasicType.number))
Value.`value`.parseAll("1111").right.value should be(Literal("1111", BasicType.number))
Value.`value`.parseAll("-1543").right.value should be(Literal("-1543", BasicType.signed))
Value.`value`.parseAll("1.0").right.value should be(Literal("1.0", BasicType.float))
Value.`value`.parseAll("1.23").right.value should be(Literal("1.23", BasicType.float))
Value.`value`.parseAll("-1.23").right.value should be(Literal("-1.23", BasicType.float))
Value.`value`.parseAll("\"some crazy string\"").right.value should be(Literal("\"some crazy string\"", BasicType.string))
Value.`value`.parseAll("\"some crazy string with escaped \\\" quote\"").right.value should be(Literal("\"some crazy string with escaped \\\" quote\"", BasicType.string))
}
}