2017-06-02 86 views
2

我正在使用Scala的Parser Combinator框架,扩展了RegexParsers类。我有一个identifier令牌,它以字母开头,可以包含字母,破折号,下划线和数字,只要它不是保留字中的一个。我尝试使用解析器的not()来停止使用保留字,但它也匹配带有保留字前缀的标识符。如何过滤解析器组合器中的保留字?

def reserved = "and" | "or" 

def identifier: Parser[String] = not(reserved) ~> """[a-zA-Z][\.a-zA-Z0-9_-]*""".r 

然而,当我试图解析的标识符像and-today我得到一个错误说Expected Failure

如何过滤保留字如果它们是令牌的完全匹配而不仅仅是前缀?

在使用not()时,还有一种方法可以改善错误报告吗?在其他情况下,我得到解析器期望的正则表达式,但在这种情况下,它只是说Failure,没有任何细节。

+1

难道是绝对必要的,您使用正则表达式?您可以使用组合模式匹配和比较参数(如'.equalsIgnoreCase')来获得所需的结果。 –

+0

不确定你的意思是结合模式匹配。是的,令牌必须与正则表达式匹配,除了一些保留字(我想避开正则表达式)。这是一个非常实用的解析器,在各种其他地方使用正则表达式。 Maxim的解决方案非常完美。 – jbx

回答

3

您可以使用filterWithError既能过滤掉保留字和自定义这样的错误消息:

val reservedWords = HashSet("and", "or") 

    val idRegex= """[a-zA-Z][\.a-zA-Z0-9_-]*""".r 

    val identifier = Parser(input => 
     idRegex(input).filterWithError(
     !reservedWords.contains(_), 
     reservedWord => s"YOUR ERROR MESSAGE FOR $reservedWord", 
     input 
    ) 
    ) 
+0

谢谢工作完美。 – jbx