我正在寻找一种使用Scala解析器组合器的方法来与正则表达式匹配,然后再对其进行解析。
示例:
import scala.util.parsing.combinator.RegexParsers
object MetaCommandParser extends RegexParsers with App {
def parseSub: Parser[Object] = (parseElement <~ "=>") ~ parseExpression.*
def parseElement: Parser[Object] = """\w+""".r
def parseOr: Parser[Object] = listElements
def listElements: Parser[Object] = parseExpression ~ opt("|" ~ listElements)
def parseExpression: Parser[Object] = parseElement | parseOr
def parseMetaCommand(s: String) = {
MetaCommandParser.parseAll(parseSub, s) match {
case Success(result, _) => result
case Failure(msg, _) => throw new Exception("FAILURE: " + msg)
case Error(msg, _) => throw new Exception("ERROR: " + msg)
}
}
println(parseMetaCommand("operation => test"));
}
类型:
sealed trait Command;
case class Sub(tag: Word, sub: List[Expression]) extends Command;
case class ReplaceBy(tag: Word, sub: List[Expression]) extends Command;
sealed trait Expression;
case class Or(elements: Set[Expression]) extends Expression;
case class Reference(tag: String) extends Expression;
case class Option(element: Expression) extends Expression;
case class Word(tag: String) extends Expression;
case object Empty extends Expression;
如果我使用以下表达式在parseSub上执行解析器: “操作=>测试”
我有一个StackOverflow。我的解析器很好地解析了Sub(Word(operation),Word(test)),但之后出现了错误。我认为解析器试图在parseExpression上计算一个空字符串以结束“ parseExpression。*”,但是在listElements中循环。如果我可以确保在调用parseExpression之前输入的内容有效,那么我认为它可以解决我的问题(parseValidString函数)!
因此,我试图验证我的条目与该正则表达式匹配,以避免无限循环,但我不知道如何做到这一点:/
谢谢!
答案 0 :(得分:2)
您的parseExpression
和listElements
规则是相互左递归的(通过parseOr
)。在我的评论中,我建议这可能不会在这里引起堆栈溢出,因为parseElement
在listElements
之前被尝试过,这意味着listElements
将永远无法到达(这是另一个问题。和本身)。
但是,由于您在parseExpression
循环中使用*
,因此它将重复应用,直到失败为止,这意味着最后将尝试使用其所有替代方法。因此将达到listElements
,并且左递归确实会导致堆栈溢出。您还可以从以下事实中看到这一点:如果您将| parseOr
中的parseExpression
注释掉,堆栈溢出就会消失。