Skip to content

Commit

Permalink
Fix compilation rule for NonterminalLiteral (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
h2oche committed Feb 22, 2022
1 parent 0e888f5 commit 616d4aa
Show file tree
Hide file tree
Showing 11 changed files with 48 additions and 30 deletions.
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/interp/Interp.scala
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ class Interp(
val r = interp(rule).escaped
??? // TODO parse `code` with `rule`
}
case EParseRule(name, params) => ???
case ESourceText(expr) => ???
case EGrammar(name, params) => Grammar(name, params)
case ESourceText(expr) => ???
case EYet(msg) =>
throw NotSupported(msg)
case EContains(list, elem) =>
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/esmeta/interp/State.scala
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ case class Cont(
/** abstract syntax tree (AST) values */
case class AstValue(ast: Ast) extends PureValue

/** grammars */
case class Grammar(name: String, params: List[Boolean]) extends PureValue

// -----------------------------------------------------------------------------
// Literal Values
// -----------------------------------------------------------------------------
Expand Down
9 changes: 9 additions & 0 deletions src/main/scala/esmeta/interp/util/Stringifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class Stringifier(detail: Boolean, location: Boolean) {
case clo: Clo => cloRule(app, clo)
case cont: Cont => contRule(app, cont)
case AstValue(ast) => app >> ast
case gr: Grammar => grammarRule(app, gr)
case lit: LiteralValue => litRule(app, lit)

// addresses
Expand All @@ -136,6 +137,14 @@ class Stringifier(detail: Boolean, location: Boolean) {
if (!captured.isEmpty) app >> ", " >> captured.toList
app >> ">"

// grammar
given grammarRule: Rule[Grammar] = (app, gr) =>
given Rule[Boolean] = (app, bool) => app >> (if (bool) "T" else "F")
given Rule[List[Boolean]] = iterableRule()
app >> "grammar<" >> gr.name
if (!gr.params.isEmpty) app >> "[" >> gr.params >> "]"
app >> ">"

// literal values
given litRule: Rule[LiteralValue] = (app, lit) =>
lit match
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/esmeta/ir/Expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ case class EIsCompletion(expr: Expr) extends Expr
case class EReturnIfAbrupt(expr: Expr, check: Boolean) extends Expr
case class EPop(list: Expr, front: Boolean) extends Expr
case class EParse(code: Expr, rule: Expr) extends Expr
case class EParseRule(name: String, params: List[Boolean]) extends Expr
case class EGrammar(name: String, params: List[Boolean]) extends Expr
case class ESourceText(expr: Expr) extends Expr
case class EYet(msg: String) extends Expr
case class EContains(list: Expr, elem: Expr) extends Expr
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/ir/util/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ trait Parsers extends BasicParsers {
case f ~ e => EPop(e, f)
} | "(" ~ "parse" ~> expr ~ expr <~ ")" ^^ {
case c ~ r => EParse(c, r)
} | "(" ~ "rule" ~> ("|" ~> word <~ "|") ~ parseParams <~ ")" ^^ {
case x ~ ps => EParseRule(x, ps)
} | "(" ~ "grammar" ~> ("|" ~> word <~ "|") ~ parseParams <~ ")" ^^ {
case x ~ ps => EGrammar(x, ps)
} | "(" ~ "source-text" ~> expr <~ ")" ^^ {
ESourceText(_)
} | "(" ~ "yet" ~> string <~ ")" ^^ {
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/esmeta/ir/util/Stringifier.scala
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ class Stringifier(detail: Boolean, location: Boolean) {
app >> "(pop " >> (if (front) "<" else ">") >> " " >> list >> ")"
case EParse(code, rule) =>
app >> "(parse " >> code >> " " >> rule >> ")"
case EParseRule(name, params) =>
app >> "(rule |" >> name >> "|"
case EGrammar(name, params) =>
app >> "(grammar |" >> name >> "|"
given Rule[Boolean] = (app, bool) => app >> (if (bool) "T" else "F")
given Rule[List[Boolean]] = iterableRule("[", "", "]")
app >> params >> ")"
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/esmeta/ir/util/UnitWalker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ trait UnitWalker extends BasicUnitWalker {
walk(list); walk(front)
case EParse(code, rule) =>
walk(code); walk(rule)
case EParseRule(name, params) =>
case EGrammar(name, params) =>
walk(name); walkList(params, walk)
case ESourceText(exor) =>
walk(expr)
Expand Down
21 changes: 18 additions & 3 deletions src/main/scala/esmeta/spec/util/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ class Compiler(val spec: Spec) {
val newFb = FuncBuilder(Func.Kind.Clo, cloName, ps, body, fb.algo)
newFb.result
EClo(cloName, captured.map(compile))
case lit: Literal => compile(lit)
case lit: Literal => compile(fb, lit)
}

// compile binary operators
Expand All @@ -419,13 +419,28 @@ class Compiler(val spec: Spec) {
case UnaryExpression.Op.Neg => UOp.Neg

// compile literals
private def compile(lit: Literal): Expr = lit match {
private def compile(fb: FB, lit: Literal): Expr = lit match {
case ThisLiteral() => ENAME_THIS
case NewTargetLiteral() => ENAME_NEW_TARGET
case HexLiteral(hex, name) => EMathVal(hex)
case CodeLiteral(code) => EStr(code)
case NonterminalLiteral(ordinal, name) =>
toERef(NAME_THIS, EStr(name + ordinal.fold("")(_.toString)))
fb.algo.head match
case SyntaxDirectedOperationHead(Some(target), method, _, _) =>
val rhsNames = target.rhsParams.map(_.name)
// check if it is used as reference
// TODO ClassTail[0,3].Contains
if (rhsNames contains name) {
var (idx, ord) = (0, 0)
val targetOrd = ordinal.getOrElse(1)
rhsNames.foreach {
case nt =>
if (nt == name && ord < targetOrd) ord += 1
if (ord < targetOrd) idx += 1
}
toERef(NAME_THIS, EMathVal(idx))
} else EGrammar(name, Nil) // TODO grammar params
case _ => EGrammar(name, Nil) // TODO grammar params
case ConstLiteral(name) => EConst(name)
case StringLiteral(s) => EStr(s)
case FieldLiteral(field) => EStr(field)
Expand Down
17 changes: 3 additions & 14 deletions src/main/scala/esmeta/spec/util/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,9 @@ extension (rhs: Rhs) {
def getNts: List[Nonterminal] = rhs.symbols.flatMap(_.getNt)

/** get parameters from RHSs */
def getRhsParams: List[Param] = {
import Param.Kind.*
val names = rhs.getNts.map(_.name)
val duplicated = names.filter(p => names.count(_ == p) > 1).toSet
var counter = Map[String, Int]()
val paramNames = names.map(name => {
if (duplicated contains name) {
val k = counter.getOrElse(name, 0)
counter += name -> (k + 1)
s"$name$k"
} else name
})
paramNames.map(Param(_, Normal, "unknown"))
}
// TODO give more precise type
def getRhsParams: List[Param] =
rhs.getNts.map(nt => Param(nt.name, Param.Kind.Normal, "Unknown"))
}

/** extensions for symbols */
Expand Down
2 changes: 2 additions & 0 deletions src/test/scala/esmeta/interp/StringifyTinyTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class StringifyTinyTest extends InterpTest {
lazy val ast = AstValue(Syntactic("Identifier", Nil, 1, Nil))
lazy val astArgs =
AstValue(Syntactic("Identifier", List(true, false), 1, Nil))
lazy val grammar = Grammar("A", List(true, false))
lazy val lex = AstValue(Lexical("Identifier", "x"))
checkStringify("Value")(
comp -> "comp[~throw~/to](42)",
Expand All @@ -132,6 +133,7 @@ class StringifyTinyTest extends InterpTest {
ast -> "|Identifier|<1>",
astArgs -> "|Identifier|[TF]<1>",
lex -> "|Identifier|(x)",
grammar -> "grammar<A[TF]>",
Math(3.2) -> "3.2",
Number(3.2) -> "3.2f",
BigInt(324) -> "324n",
Expand Down
10 changes: 5 additions & 5 deletions src/test/scala/esmeta/ir/StringifyTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import esmeta.util.SystemUtils._
import scala.collection.mutable.ListBuffer

class StringifyTinyTest extends IRTest {
val name: String = "cfgStringifyTest"
val name: String = "irStringifyTest"

// registration
def init: Unit = {
Expand Down Expand Up @@ -135,8 +135,8 @@ class StringifyTinyTest extends IRTest {
lazy val riaNoCheck = EReturnIfAbrupt(xExpr, false)
lazy val popFront = EPop(xExpr, true)
lazy val popBack = EPop(xExpr, false)
lazy val parse = EParse(xExpr, rule)
lazy val rule = EParseRule("A", List(true, false))
lazy val parse = EParse(xExpr, egrammar)
lazy val egrammar = EGrammar("A", List(true, false))
lazy val yet = EYet("NOT YET")
lazy val contains = EContains(xExpr, xExpr)
lazy val xExpr = ERef(x)
Expand Down Expand Up @@ -186,8 +186,8 @@ class StringifyTinyTest extends IRTest {
riaNoCheck -> "[! x]",
popFront -> "(pop < x)",
popBack -> "(pop > x)",
parse -> "(parse x (rule |A|[TF]))",
rule -> "(rule |A|[TF])",
parse -> "(parse x (grammar |A|[TF]))",
egrammar -> "(grammar |A|[TF])",
yet -> "(yet \"NOT YET\")",
contains -> "(contains x x)",
xExpr -> "x",
Expand Down

0 comments on commit 616d4aa

Please sign in to comment.