[英]Scala's parser combinator compare before parse
我正在尋找一種使用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上執行解析器:“ operation => test”
我有一個StackOverflow。 我的解析器很好地解析了Sub(Word(operation),Word(test)),但之后出現了錯誤。 我認為解析器試圖在parseExpression上計算一個空字符串以結束“ parseExpression。*”,但是在listElements中循環。 如果可以在調用parseExpression之前確保我的條目有效,那么我認為它可以解決我的問題(parseValidString函數)!
因此,我試圖驗證我的條目與該正則表達式匹配,以避免無限循環,但我不知道如何做到這一點:/
謝謝!
您的parseExpression
和listElements
規則是相互左遞歸的(通過parseOr
)。 在我的評論中,我建議這可能不會導致堆棧溢出,因為parseElement
在listElements
之前進行了listElements
,這意味着listElements
將永遠無法到達(這本身就是另一個問題)。
但是,由於在*
循環中使用parseExpression
,因此它將重復應用,直到失敗為止,這意味着最終將嘗試使用其所有替代方法。 因此,將達到listElements
,而左遞歸確實會導致堆棧溢出。 您也可以從以下事實中看到這一點:如果注釋掉| parseOr
,則堆棧溢出會消失| parseOr
| parseOr
在parseExpression
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.