用于由方法调用组成的简单DSL的Lexer/Parser

本文关键字:简单 DSL Parser Lexer 方法 调用 用于 | 更新日期: 2023-09-27 18:05:21

我希望为我们与内部工具一起使用的简单DSL创建一个词法分析器和解析器。将有几个内置符号(这是正确的术语吗?),它们将接受1到10个参数之间的任何地方。例如:

foo(bar1;bar2)

在运行时添加的符号也将始终具有零参数。例子:

testy1()

这些将串在一起并从CSV文件中读取。装配线应该像这样:

foo(bar1:bar2)testy1()

我很难在网上找到能轻易解释词法分析和解析函数调用的资源。有人能给我指个好方向吗,或者给我点建议吗?

用于由方法调用组成的简单DSL的Lexer/Parser

我用PegJS编写了一个小解析器,它能够解析函数调用中的简单表达式。peg避免了歧义,它们可以很好地解决这个问题。

Start
  = Expr
/* Expressions */
Expr
  = FuncCall
  / Literal
RestExpr
  = _ ( "," / ":" ) _ e:Expr {
    return e;
  }
/* Function call */
FuncCall
  = func:Ident _ "(" _ x:Expr? xs:RestExpr* _ ")" {
    return {
      type: "FuncCall",
      func: func.value,
      params: x ? [x].concat(xs) : []
    };
  }
/* Literals */
Literal
  = Number
  / Ident
Number
  = val:[0-9]+ {
    return {
      type: "Number",
      value: parseInt(val.join(""))
    };
  }
/* Identifier */
Ident
  = x:IdentStart xs:IdentRest* {
  return {
    type: "Ident",
    value: [x].concat(xs).join("")
  };
}
IdentStart
  = [a-z_]i
IdentRest
  = [a-z0-9_]i
_
  = [ 's't'r'n]*

您可以在这里测试解析器:http://pegjs.org/online

输入示例为foo(1, bar(2), baz(3)),输出为:

{
   "type": "FuncCall",
   "func": "foo",
   "params": [
      {
         "type": "Number",
         "value": 1
      },
      {
         "type": "FuncCall",
         "func": "bar",
         "params": [
            {
               "type": "Number",
               "value": 2
            }
         ]
      },
      {
         "type": "FuncCall",
         "func": "baz",
         "params": [
            {
               "type": "Number",
               "value": 3
            }
         ]
      }
   ]
}

这显然不是最好的方法,但我相信peg-sharp可以用c#做得很好:https://code.google.com/p/peg-sharp/.