我正在尝试为编程语言Icon编写一个解释器.这个过程中的一个步骤是为Icon编写一个解析器,我用以下方式完成了:
import java.io.FileReader
import scala.util.parsing.combinator.syntactical._
import scala.util.parsing.combinator.RegexParsers
import scala.util.parsing.combinator.PackratParsers
import scala.util.parsing.combinator.JavaTokenParsers
abstract class expr
case class CstInt(val value : Int) extends expr
case class FromTo(val from : expr, val to : expr) extends expr
case class Write(val value : expr) extends expr
case class And(val e1 : expr, val e2 : expr) extends expr
case class Or(val e1 : expr, val e2 : expr) extends expr
object ExprParser extends JavaTokenParsers with PackratParsers{
lazy val exp : PackratParser[expr] = andexp | exp2
lazy val exp2 : PackratParser[expr] = fromTo | exp3
lazy val exp3 :PackratParser[expr] = orexp | exp4
lazy val exp4 : PackratParser[expr] = integer | exp5
lazy val exp5 : PackratParser[expr] = write
lazy val integer : PackratParser[expr] = wholeNumber ^^ { s => CstInt(s.toInt)}
lazy val write : PackratParser[Write] = "write" ~> "(" ~> exp <~ ")" ^^ { e => Write(e)}
lazy val fromTo : PackratParser[FromTo] = ("(" ~> integer) ~ ("to" ~> integer <~ ")") ^^ { case from ~ to => FromTo(from, to)}
lazy val andexp : PackratParser[And] = exp ~ ("&" ~> exp) ^^ { case e1 ~ e2 => And(e1, e2)}
lazy val orexp : PackratParser[Or] = exp ~ ("|" ~> exp) ^^ { case e1 ~ e2 => Or(e1, e2)}
def parseInput(input: String) : expr =
parseAll (exp, input) match {
case Success(tree, _) => tree
case e: NoSuccess => throw new IllegalArgumentException(e.toString())
}
}
object Interpret {
def main(args : Array[String]) : Unit = {
println(ExprParser.parseInput(args(0)))
}
}
但是,当我尝试解析以下表达式时,我遇到了一些问题:
write((1 to 4) | 4)
我收到此错误:
java.lang.IllegalArgumentException: [9.17] failure: `)' expected but ` ' found
而解析
write((1 to 4) & 4)
工作得很好.如果我将orexp解析器移动到fromto解析器上方的exp组,则第一个表达式可以正常工作.但是,这不符合Icon给出的规则,并不能解决潜在的问题.
有没有人对解决方案有任何想法?根据Scala文档,混合packrat解析器和常规解析器应该没问题.
最佳答案 好吧,我已经阅读了Scala中的包装解析器上的
paper,我担心这个语法不能正常工作.问题是,从内部写入exp,然后写入本身失败(并且没有其他选择,外部exp失败).它永远不会回头说“好吧,让我们看看是否有另一个exp也是有效的”.
但是,看看this text,我没有看到括号作为其语法的一部分.如果只是重写它以从该级别中删除那些括号,它将起作用:
object ExprParser extends JavaTokenParsers with PackratParsers{
lazy val exp : PackratParser[expr] = andexp | exp2
lazy val exp2 : PackratParser[expr] = fromTo | exp3
lazy val exp3 :PackratParser[expr] = orexp | exp4
lazy val exp4 : PackratParser[expr] = integer | exp5
lazy val exp5 : PackratParser[expr] = write | exp6
lazy val exp6 : PackratParser[expr] = "(" ~> exp <~ ")"
lazy val integer : PackratParser[expr] = wholeNumber ^^ { s => CstInt(s.toInt)}
lazy val write : PackratParser[Write] = "write" ~> "(" ~> exp <~ ")" ^^ { e => Write(e)}
lazy val fromTo : PackratParser[FromTo] = integer ~ ("to" ~> integer) ^^ { case from ~ to => FromTo(from, to)}
lazy val andexp : PackratParser[And] = exp ~ ("&" ~> exp) ^^ { case e1 ~ e2 => And(e1, e2)}
lazy val orexp : PackratParser[Or] = exp3 ~ ("|" ~> exp) ^^ { case e1 ~ e2 => Or(e1, e2)}
}