Scala Parser Combinator:如何调整andExpr解析逻辑区分单值与多值
调整andExpr解析逻辑:让单个输入识别为literal而非orExpr
我明白你的问题了——你希望andExpr的规则是:只有当输入被"and"分隔时,才把各个部分解析成orExpr;如果是单个元素(没有"and"),就直接解析成literal,而不是走orExpr的逻辑。
问题出在哪?
你当前的代码用了rep1sep(orExpr, "and") | literal,但rep1sep的特性是匹配1个或多个由分隔符连接的目标解析器,所以单个orExpr(比如输入"bye")会被第一个分支直接捕获,literal分支永远不会被触发,这就导致了不符合预期的结果。
解决方案
我们需要修改第一个分支,让它只匹配至少两个由"and"连接的orExpr,这样单个元素就会自然落到literal分支里。可以用orExpr ~ rep("and" ~> orExpr)来实现这个逻辑:
def andExpr: Parser[Expr] = // 匹配至少两个orExpr用"and"连接的情况 (orExpr ~ rep("and" ~> orExpr)) ^^{ // 把多个orExpr组合成AndExpr(这里根据你的实际Expr结构调整) case firstOrExpr ~ remainingOrExprs => remainingOrExprs.foldLeft(firstOrExpr)(AndExpr(_, _)) } | // 单个元素直接解析为literal literal
逻辑说明
- 第一个分支:
orExpr ~ rep("and" ~> orExpr)要求必须有一个初始的orExpr,后面跟着至少一个由"and"引导的orExpr——也就是说,只有像"hello and hi"这样的输入才会触发这个分支,此时"hello"和"hi"都会被解析成orExpr。 - 第二个分支:当输入是单个元素(比如"bye")时,第一个分支无法匹配,解析器就会尝试
literal分支,完全符合你的需求。
这样就能严格区分两种场景,达到你想要的解析效果啦。
内容的提问来源于stack exchange,提问作者Priyansh Goel
相关产品推荐
相关产品推荐

