Scala 组合器解析器 - 区分数字字符串和变量字符串

Posted

技术标签:

【中文标题】Scala 组合器解析器 - 区分数字字符串和变量字符串【英文标题】:Scala combinator parsers - distinguish between number strings and variable strings 【发布时间】:2010-09-20 09:05:47 【问题描述】:

我正在做 Cay Horstmann 的组合器解析器练习,我想知道在匹配语句中区分表示数字的字符串和表示变量的字符串的最佳方法:

def factor: Parser[ExprTree] = (wholeNumber | "(" ~ expr ~ ")" | ident) ^^ 
    case a: wholeNumber  => Number(a.toInt)
    case a: String => Variable(a)

那里的第二行,“case a: wholeNumber”是不合法的。我想过一个正则表达式,但还没有找到一种方法让它与“case”一起工作。

【问题讨论】:

【参考方案1】:

我会稍微拆分一下,然后将案例分析推送到|。这是组合子和真正的 LL(*) 解析的优点之一:

def factor: Parser[ExprTree] = ( wholeNumber ^^  Number(_.toInt) 
                               | "(" ~> expr <~ ")" 
                               | ident ^^  Variable(_)  )

如果您不熟悉下划线语法,我深表歉意。基本上它只是意味着“将第 n 个参数替换为封闭函数值”。因此 Variable(_) 等价于 x =&gt; Variable(x)

这里的另一个语法魔术是~&gt;&lt;~ 运算符代替~。这些运算符意味着该术语的解析应包括两个括号的语法,但结果应仅由expr 的结果确定。因此,"(" ~&gt; expr &lt;~ ")""(" ~ expr ~ ")" 完全匹配,但它不需要额外的案例分析来从expr 检索内部结果值。

【讨论】:

太棒了!必须将 Number(_.toInt) 更改为 x:String => Number(x) ,因为我收到“错误:缺少扩展函数的参数类型”,然后它就像一个魅力。仍然很好奇是否有解决它的案例类方法。 好吧,实际上 case 只是定义了一个偏函数。它允许您对输入进行模式匹配,这就是它有用的真正原因。我可以很容易地使用部分函数(案例)来写我的答案,但这并不是必需的。 :-)(除了 ~> 和 如果您的意思是在整个术语上匹配,那么我认为答案是“不,没有办法做到这一点”。除非 wholeNumber 方法返回的 Parser 的组件类型与 String 不同,否则实际上无法将其与 ident 甚至 "(" ~> expr 刚刚意识到我不是特别清楚......部分函数(使用大小写定义)与普通函数完全相同,它们只允许在输入上进行模式匹配。因此: x => x.toInt 与 case x => x.toInt 相同。 感谢丹尼尔,我已经解决了最初的问题,但我仍然对使用正则表达式进行模式匹配感到好奇,从阅读这本书和谷歌搜索来看,似乎没有办法做到这一点。

以上是关于Scala 组合器解析器 - 区分数字字符串和变量字符串的主要内容,如果未能解决你的问题,请参考以下文章

Swift函数式编程十一(解析器组合算子)

Swift函数式编程十一(解析器组合算子)

Spark基础-scala学习

scala的插值器

C ++业务规则表达式解析器/评估[关闭]

在 Scala 元组上使用功能组合器?