如何解决与正则表达式创建解析器相关的错误?

时间:2015-06-17 20:56:42

标签: regex scala parsing lexical-analysis

我正在使用Scala中的StandardTokenParsers编写解析器。需要创建一个正则表达式解析器来解析路径。我测试了正则表达式工作正常,但发送到一个函数来解析它,程序给出一个错误,我无法弄明白!与此解析器相关的代码的一部分如下:

 class InfixToPostfix extends StandardTokenParsers {
 import scala.util.matching.Regex
 import lexical.StringLit
//parsing the path
 def regexStringLit(r: Regex): Parser[String] =
 acceptMatch( "string literal matching regex " + r,{ case  StringLit(s) if r.unapplySeq(s).isDefined => s })
// Regex for path
 val pathIdent ="""/hdfs://[\d.]+:\d+/[\w/]+/\w+([.+]\w+)+""".r   
 def pathIdente: Parser[String] =regexStringLit(pathIdent)

 lexical.delimiters ++= List("+","-","*","/", "^","(",")",",")
 def value :Parser[Expr] = numericLit ^^ { s => Number(s) }
 def variable:Parser[Expr] =  pathIdente ^^ { s => Variable(s) }
 def parens:Parser[Expr] = "(" ~> expr <~ ")"

 def argument:Parser[Expr] = expr <~ (","?)
 def func:Parser[Expr] = ( pathIdente ~ "(" ~ (argument+) ~ ")" ^^ { case f ~ _ ~ e ~ _ => Function(f, e) })
//and the rest of the code ....

此解析器将解析算术运算。我使用args(0)将我的输入发送到以下程序: &#34; / HDFS://111.33.55.2:8888 /文件夹1 / p.a3d + 1&#34;

我收到以下错误:

[1.1] failure: string literal matching regex /hdfs://([\d\.]+):(\d+)/([\w/]+/(\w+\.\w+)) expected

 /hdfs://111.33.55.2:8888/folder1/p.a3d
 ^

无法弄清楚如何解决它!

仅供参考:&#34; + 1&#34;将由代码中的解析器处理,因此部分&#34; pathIdent&#34;仅用于路径,这是造成麻烦的部分。这也很好:

  """/hdfs://\d+(\.\d+){3}:\d+(/(\w+([.+]\w+)*))+""".r 

它在代码检查之外正常工作:regexpal.com 但在程序中使用它仍然是同样的错误。

我想知道StringLit是不是包含某些字符并导致错误的字符串。除了StringLit之外还有什么我可以在这里使用吗?

1 个答案:

答案 0 :(得分:1)

匹配失败将是因为匹配器贪婪。这是几种语言中正则表达式匹配(因此也就是词法分析)的常见问题。

贪婪的匹配会在表达式的末尾捕捉到你。

您有([\w/]+/(\w+\.\w+)),但这将无法匹配,因为与输入文本p所代表的\w匹配的 folder1/p是被作品([\w/]+吞噬了。它在.期间停止。因此,在点之前没有任何字词允许(\w+\.\w+)匹配。

您必须重新考虑正则表达式,并使每个路径片段终止于固相/,而不是使其成为集合的一部分。

你知道吗?

要完成这项工作,您需要通过以下方式表达:

"""/hdfs://[\d.]+:\d+/(\w/)+\w+([.+]\w+)+""".r 

我将[\w/]+/替换为(\w/)+。现在,这指定了单词和斜杠的顺序,并为下一个模式留下了不匹配的单词,以便成功。