【问题标题】:EBNF to Scala parser combinatorEBNF 到 Scala 解析器组合器
【发布时间】:2010-10-06 06:34:30
【问题描述】:

我有以下要解析的 EBNF:

PostfixExp      -> PrimaryExp ( "[" Exp "]" 
                                | . id "(" ExpList ")" 
                                | . length )*

这就是我得到的:

def postfixExp: Parser[Expression] = (
    primaryExp ~ rep(
        "[" ~ expression ~ "]"
        | "." ~ ident ~"(" ~ repsep(expression, "," ) ~ ")" 
        | "." ~ "length") ^^ {
        case primary ~ list =>  list.foldLeft(primary)((prim,post) =>
                post match {
                    case "[" ~ length ~ "]" => ElementExpression(prim, length.asInstanceOf[Expression])
                    case "." ~ function ~"(" ~ arguments ~ ")" =>  CallMethodExpression(prim, function.asInstanceOf[String], arguments.asInstanceOf[List[Expression]])
                    case _ => LengthExpression(prim)
                }
            )
    })

但我想知道是否有更好的方法,最好不必求助于强制转换 (asInstanceOf)。

【问题讨论】:

    标签: parsing scala parser-combinators


    【解决方案1】:

    我会这样做:

    type E = Expression
    
    def postfixExp = primaryExp ~ rep(
        "[" ~> expr <~ "]" ^^ { e => ElementExpression(_:E, e) }
      | "." ~ "length" ^^^ LengthExpression
      | "." ~> ident ~ ("(" ~> repsep(expr, ",") <~ ")") ^^ flatten2 { (f, args) =>
          CallMethodExpression(_:E, f, args)
        }
    ) ^^ flatten2 { (e, ls) => collapse(ls)(e) }
    
    def expr: Parser[E] = ...
    
    def collapse(ls: List[E=>E])(e: E) = {
      ls.foldLeft(e) { (e, f) => f(e) }
    }
    

    为简洁起见将expressions 缩短为expr,并添加了类型别名E 出于同样的原因。

    我在这里用来避免丑陋的案例分析的技巧是从内部生产中返回一个函数值。此函数采用Expression(将是primary),然后基于第一个返回一个新的Expression。这统一了点调度和括号表达式的两种情况。最后,collapse 方法用于将函数值的线性List 合并为适当的 AST,从指定的主表达式开始。

    请注意,LengthExpression 只是作为值(使用^^^)从其各自的生产中返回。这是因为案例类的伴随对象(假设LengthExpression 确实是一个案例类)扩展了委托给它们的构造函数的相应函数值。因此,LengthExpression 表示的函数接受一个 Expression 并返回一个新的 LengthExpression 实例,正好满足了我们对高阶树构造的需求。

    【讨论】:

      猜你喜欢
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-20
      • 1970-01-01
      • 2014-05-24
      • 2012-10-04
      • 2011-07-01
      相关资源
      最近更新 更多