如何解决与从正则表达式创建解析器相关的错误?
How to solve an error related to creating parser from regex?
我正在使用 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) 将我的输入发送到程序:
"/hdfs://111.33.55.2:8888/folder1/p.a3d+1"
我收到以下错误:
[1.1] failure: string literal matching regex /hdfs://([\d\.]+):(\d+)/([\w/]+/(\w+\.\w+)) expected
/hdfs://111.33.55.2:8888/folder1/p.a3d
^
想不出怎么解决!
仅供参考:“+1”部分将由代码中的解析器处理,因此 "pathIdent" 部分仅用于路径,这就是导致问题的部分。这也不错:
"""/hdfs://\d+(\.\d+){3}:\d+(/(\w+([.+]\w+)*))+""".r
它在检查它的代码之外工作正常:regexpal.com
但在程序中使用它仍然是同样的错误。
我想知道 StringLit 是否是不包含某些字符并导致错误的那个。我可以在这里使用除 StringLit 以外的其他任何东西吗?
匹配失败将是因为匹配器贪心。这是多种语言中正则表达式匹配(以及词法分析)的常见问题。
贪婪匹配在表达式的末尾捕获你。
你有 ([\w/]+/(\w+\.\w+))
但这将无法匹配,因为 word p
与输入文本 \w
匹配 folder1/p
被([\w/]+
这块吞没了。它在 .
期间停止。因此,点之前没有单词允许 (\w+\.\w+)
永远匹配。
您将不得不重新考虑您的正则表达式并使每个路径片段终止于斜线 /
而不是将其作为集合的一部分。
看到了吗?
要完成这项工作,您需要用以下方式表达:
"""/hdfs://[\d.]+:\d+/(\w/)+\w+([.+]\w+)+""".r
我将 [\w/]+/
替换为 (\w/)+
。这现在指定了单词和斜杠的顺序,并留下一个不匹配的单词,以便后续模式成功。
我正在使用 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) 将我的输入发送到程序: "/hdfs://111.33.55.2:8888/folder1/p.a3d+1"
我收到以下错误:
[1.1] failure: string literal matching regex /hdfs://([\d\.]+):(\d+)/([\w/]+/(\w+\.\w+)) expected
/hdfs://111.33.55.2:8888/folder1/p.a3d
^
想不出怎么解决!
仅供参考:“+1”部分将由代码中的解析器处理,因此 "pathIdent" 部分仅用于路径,这就是导致问题的部分。这也不错:
"""/hdfs://\d+(\.\d+){3}:\d+(/(\w+([.+]\w+)*))+""".r
它在检查它的代码之外工作正常:regexpal.com 但在程序中使用它仍然是同样的错误。
我想知道 StringLit 是否是不包含某些字符并导致错误的那个。我可以在这里使用除 StringLit 以外的其他任何东西吗?
匹配失败将是因为匹配器贪心。这是多种语言中正则表达式匹配(以及词法分析)的常见问题。
贪婪匹配在表达式的末尾捕获你。
你有 ([\w/]+/(\w+\.\w+))
但这将无法匹配,因为 word p
与输入文本 \w
匹配 folder1/p
被([\w/]+
这块吞没了。它在 .
期间停止。因此,点之前没有单词允许 (\w+\.\w+)
永远匹配。
您将不得不重新考虑您的正则表达式并使每个路径片段终止于斜线 /
而不是将其作为集合的一部分。
看到了吗?
要完成这项工作,您需要用以下方式表达:
"""/hdfs://[\d.]+:\d+/(\w/)+\w+([.+]\w+)+""".r
我将 [\w/]+/
替换为 (\w/)+
。这现在指定了单词和斜杠的顺序,并留下一个不匹配的单词,以便后续模式成功。