Im cố gắng để phù hợp với cú pháp sau:Scala Parser Combinators thủ thuật cho đệ quy bnf?
pgm ::= exprs
exprs ::= expr [; exprs]
expr ::= ID | expr . [0-9]+
My scala sưu tập điện phân tích cú pháp combinator trông như thế này:
import scala.util.parsing.combinator.PackratParsers
import scala.util.parsing.combinator.syntactical._
object Dotter extends StandardTokenParsers with PackratParsers {
lexical.delimiters ++= List(".",";")
def pgm = repsep(expr,";")
def expr :Parser[Any]= ident | expr~"."~num
def num = numericLit
def parse(input: String) =
phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match {
case Success(result, _) => println("Success!"); Some(result)
case n @ _ => println(n);println("bla"); None
}
def main(args: Array[String]) {
val prg = "x.1.2.3;" +
"y.4.1.1;" +
"z;" +
"n.1.10.30"
parse(prg);
}
}
Nhưng công việc doesnt này. Hoặc là nó "phù hợp với tham lam" và nói với tôi:
[1.2] failure: end of input expected
x.1.2.3;y.4.1.1;z;n.1.10.30
hoặc nếu tôi thay đổi |
đến một |||
tôi nhận được một stackoverflow:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.Character.isLetter(Unknown Source)
at java.lang.Character.isLetter(Unknown Source)
at scala.util.parsing.combinator.lexical.Lexical$$anonfun$letter$1.apply(Lexical.scala:32)
at scala.util.parsing.combinator.lexical.Lexical$$anonfun$letter$1.apply(Lexical.scala:32)
...
tôi kindoff hiểu tại sao tôi nhận được lỗi; Tôi có thể làm gì để phân tích một cú pháp như trên? Nó không có vẻ rằng bí truyền với tôi
EDIT: Dựa trên giấy được tham chiếu trong http://scala-programming-language.1934581.n4.nabble.com/Packrat-parser-guidance-td1956908.html tôi phát hiện ra rằng chương trình didnt tôi thực sự sử dụng phân tích cú pháp sưu tập điện mới.
Tức là. thay đổi Parser[Any]
-PackratParser[Any]
và sử dụng lazy val
thay vì def
Tôi viết lại trên thế này:
import scala.util.parsing.combinator.PackratParsers
import scala.util.parsing.combinator.syntactical._
object Dotter extends StandardTokenParsers with PackratParsers {
lexical.delimiters ++= List(".",";")
lazy val pgm : PackratParser[Any] = repsep(expr,";")
lazy val expr :PackratParser[Any]= expr~"."~num | ident
lazy val num = numericLit
def parse(input: String) =
phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match {
case Success(result, _) => println("Success!"); Some(result)
case n @ _ => println(n);println("bla"); None
}
def main(args: Array[String]) {
val prg = "x.1.2.3 ;" +
"y.4.1.1;" +
"z;" +
"n.1.10.30"
parse(prg);
}
}
Chính xác! Tôi đã đọc lại tài liệu và tìm ra điều này. Điều cuối cùng cần thiết là một lỗi đánh máy trong phương thức phân tích cú pháp: 'cụm từ (expr)' phải là 'cụm từ (pgm) '. Chúc mừng! – svrist