如何使用scala组合器为表达式赋予任意值

时间:2015-12-14 23:34:01

标签: scala parsing

假设我想在scala中解析一个字符串,并且每次有括号嵌套在一起时,我会将一些数字与它自身相乘。防爆 数字= 3的(())+()+((()))为3 * 3 + 3 + 3 * 3 * 3。我如何使用scala组合器完成此操作。

class SimpleParser extends JavaTokenParsers {

  def Base:Parser[Int] = """(""" ~remainder ~ """)"""  
  def Plus = atom ~ '+' ~ remainder 
  def Parens = Base
  def remainder:Parser[Int] =(Next|Start) }

我如何制作它以便每次解析一个原子时,数字会自动相乘,然后原子内部的内容也会被解析? 我会在原子def之后放一个方法

def Base:Parser[Int] = """(""" ~remainder ~ """)""" ^^(2*paser(remainder))

?我不明白如何做到这一点,因为它的递归性质,就像我找到括号,我必须乘以这些括号中的任何三倍。

2 个答案:

答案 0 :(得分:1)

如果您从内到外建立数字,这是最简单的。对于括号组,我们从基本情况开始(这将简单地导致数字本身),然后为每个嵌套再次添加数字。总而言之,我们从单个括号组开始,然后可选地添加加数,直到我们用完为止:

scala> ParserWith3.parseAll(ParserWith3.expr, "(())+()+((()))")
res0: ParserWith3.ParseResult[Int] = [1.15] parsed: 18

然后:

map

我使用的是map,因为我无法支持解析库的小型运营商聚会,但您可以用{{1}替换所有^^ s }或^^^如果你真的想要。

答案 1 :(得分:0)

如果您使用scala解析器组合器构建正确的递归规则这一事实(例如,mult出现在其自己定义的右侧):

import scala.util.parsing.combinator.RegexParsers

trait  ExprsParsers extends RegexParsers {
   val value = 3
   lazy val mult: Parser[Int] = 
     "(" ~> mult <~ ")" ^^ { _ * value }  |||
     "()" ^^ { _ => value }

   lazy val plus: Parser[Int] = 
     (mult <~ "+") ~ plus ^^ { case m ~ p => m + p } ||| 
     mult
}

要使用该代码,您只需创建一个继承ExprsParsers的结构,例如: :

object MainObj extends ExprsParsers {
    def main(args: Array[String]): Unit = {
        println(parseAll(plus, "() + ()"))  //[1.8] parsed: 6
        println(parseAll(plus, "() + (())")) //[1.10] parsed: 12
        println(parseAll(plus, "((())) + ()"))  //[1.12] parsed: 30
    }
}

检查scala source file for parser是否有任何您不理解的操作员。