mirror of
https://github.com/fluencelabs/aqua.git
synced 2025-05-27 22:41:19 +00:00
Literals parsing
This commit is contained in:
parent
103203bab0
commit
215866baf0
@ -3,11 +3,7 @@ package aqua.parse
|
|||||||
import aqua.parse.Token._
|
import aqua.parse.Token._
|
||||||
import cats.data.NonEmptyList
|
import cats.data.NonEmptyList
|
||||||
import cats.parse.{Parser ⇒ P}
|
import cats.parse.{Parser ⇒ P}
|
||||||
|
import Value.`value`
|
||||||
// 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
|
|
||||||
|
|
||||||
sealed trait FuncOp
|
sealed trait FuncOp
|
||||||
sealed trait InstrOp extends FuncOp
|
sealed trait InstrOp extends FuncOp
|
||||||
@ -29,17 +25,9 @@ case class AbilityId(ability: String, id: Value) extends AbilityResolve
|
|||||||
|
|
||||||
object FuncOp {
|
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] =
|
val funcCall: P[FuncCall] =
|
||||||
(`name` ~ P.repSep0(value, `,`).between(`(`, `)`)).map{
|
(`name` ~ P.repSep0(`value`, `,`).between(`(`, `)`)).map{
|
||||||
case (fnName, args) ⇒ FuncCall(fnName, args)
|
case (fnName, args) ⇒ FuncCall(fnName, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,14 +42,14 @@ object FuncOp {
|
|||||||
case (v, f) ⇒ Extract(v, f)
|
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)
|
case (n, v) ⇒ AbilityId(n, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO can't be in Par, can be in On
|
// TODO can't be in Par, can be in On
|
||||||
val execOp: P[ExecOp] = P.oneOf( callOp.backtrack :: abilityResolve.backtrack :: extract :: Nil)
|
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] =
|
val execOn: P[On] =
|
||||||
(startOn ~ indented(execOp)).map{
|
(startOn ~ indented(execOp)).map{
|
||||||
|
@ -9,14 +9,18 @@ case class ArrayType(data: DataType) extends DataType
|
|||||||
case class CustomType(name: String) extends DataType
|
case class CustomType(name: String) extends DataType
|
||||||
case class BasicType(name: String) extends DataType
|
case class BasicType(name: String) extends DataType
|
||||||
object BasicType {
|
object BasicType {
|
||||||
val floatS = "f32" :: "f64" :: Nil
|
private val floatS = "f32" :: "f64" :: Nil
|
||||||
val numberS = "s32" :: "s64" :: "i32" :: "i64" :: floatS
|
private val signedS = "s32" :: "s64" :: floatS
|
||||||
val boolS = "bool" :: Nil
|
private val numberS = "i32" :: "i64" :: signedS
|
||||||
val allS = numberS ++ boolS
|
private val boolS = "bool" :: Nil
|
||||||
|
private val stringS = "string" :: Nil
|
||||||
|
private val allS = numberS ++ boolS ++ stringS
|
||||||
|
|
||||||
val float = floatS.map(BasicType(_))
|
val float = floatS.map(BasicType(_))
|
||||||
|
val signed = signedS.map(BasicType(_))
|
||||||
val number = numberS.map(BasicType(_))
|
val number = numberS.map(BasicType(_))
|
||||||
val bool = boolS.map(BasicType(_))
|
val bool = boolS.map(BasicType(_))
|
||||||
|
val string = stringS.map(BasicType(_))
|
||||||
|
|
||||||
val `basictypedef`: P[BasicType] =
|
val `basictypedef`: P[BasicType] =
|
||||||
P.oneOf(
|
P.oneOf(
|
||||||
|
37
src/main/scala/aqua/parse/Value.scala
Normal file
37
src/main/scala/aqua/parse/Value.scala
Normal 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)
|
||||||
|
|
||||||
|
}
|
@ -6,43 +6,6 @@ import org.scalatest.flatspec.AnyFlatSpec
|
|||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
|
|
||||||
class FuncOpSpec extends AnyFlatSpec with Matchers with EitherValues{
|
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 {
|
"func calls" should "parse func()" in {
|
||||||
FuncOp.`funcop`.parseAll("func()") should be(Right(FuncCall("func", Nil)))
|
FuncOp.`funcop`.parseAll("func()") should be(Right(FuncCall("func", Nil)))
|
||||||
@ -81,11 +44,11 @@ else:
|
|||||||
"on" should "parse on x: y" in {
|
"on" should "parse on x: y" in {
|
||||||
val fCall = AbilityFuncCall("Ab", FuncCall("func", Nil))
|
val fCall = AbilityFuncCall("Ab", FuncCall("func", Nil))
|
||||||
val extr = Extract("x", fCall)
|
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:
|
val script = """on peer.id:
|
||||||
| x <- Ab.func()
|
| 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)))
|
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)
|
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, ...
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
32
src/test/scala/aqua/parse/ValueSpec.scala
Normal file
32
src/test/scala/aqua/parse/ValueSpec.scala
Normal 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))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user