【问题标题】:PEGJS: Generating an AST for a predicate first syntaxPEGJS:为谓词优先语法生成 AST
【发布时间】:2015-05-12 15:50:38
【问题描述】:

我又开始探索 pegjs 了,显然还没有掌握核心概念。我正在尝试解析以谓词开头的“查询语言”,然后是操作数列表(可能包括另一个谓词)。所以一个简单的例子是:

OR(
   "string1"
   "string2"
)

我希望将以上内容转换为:

{
   predicate: "OR",
   operands: [
        {
           type: "STRING",
           value: "string1"
        },
        {
           type: "STRING",
           value: "string2"
        }
   ]
}

这个查询:

OR(
    "string1"
    "string2"
    AND (
        "string4"
        "string5"
    )
    "string3"
)

会变成这个 AST:

{
    predicate: "OR",
    operands: [
        {
            type: "STRING",
            value: "string1"
        },
        {
            type: "STRING",
            value: "string2"
        },
        {
            predicate: "AND"
            operands: [
                {
                    type: "STRING",
                    value: "string4"
                },
                {
                    type: "STRING",
                    value: "string5"
                }
            ]
        },
        {
            type: "STRING",
            value: "string3"
        }
    ] 
}

我的语法很接近,但有几个问题。这是当前的 PEGJS 语法。可以直接粘贴到在线pegjs解析器(http://pegjs.majda.cz/online)中。

start =
    or_predicate

or_predicate
  = ws* "OR" ws* "(" ws* operands:or_predicate ws* ")" ws* 
  { if(Array.isArray(operands)) {
      return {predicate: "OR", operands: operands} 
     } else {
      return {predicate: "OR", operands: [operands] }
     }
  }
  / and_predicate

and_predicate
  = ws* "AND" ws* "(" operands:and_predicate ")"
  { if(Array.isArray(operands)) {
      return {predicate: "AND", operands: operands} 
     } else {
      return {predicate: "AND", operands: [operands] }
     }
  }
  / operands  

operands
  = ws* values:operand+ { return values; }  

operand =
    string
    / ws or_predicate:or_predicate { return or_predicate; }

string =
   ws* "\"" value:valid_variable_characters "\"" 
   { return { type: "STRING", value: value.join("")}}

// List of valid characters for string variables
valid_variable_characters =
    [a-zA-Z0-9 _]+

ws =
   [ \t\n]

上面的语法处理了我给出的两个例子,但我注意到了两个问题,这导致我提出以下三个问题。

1.语法在这个看似简单的输入上失败(关键是嵌套的 OR 紧跟在父 OR 之后,“字符串”在末尾):

OR(
   OR (
      "string1"
   )
   "string2"
)

我不确定是什么原因造成的,也不知道如何解决。

2.语法目前对于operand 规则有这条愚蠢的行:

operand =
    string
    / ws or_predicate:or_predicate { return or_predicate; }

注意第三行 or_predicate 之前的前导空格 (ws)。如果没有那个空格,我会收到错误“超出最大调用堆栈大小”。我认为这与左递归有关,但对此并不积极。理想情况下,我希望那里没有必需的“ws”,因此没有空格的查询可以工作:

OR("string1"OR("string2")"string3")

现在你必须人为地添加一些额外的空格,如下所示:

OR("string1" OR("string2") "string3")

3.我是不是完全错误地处理了这个语法?这只是我尝试的第二个,第一个是基于 pegjs 算术示例的,所以我意识到我可能完全错误,这可能就是我遇到这些问题的原因。

感谢您的协助和时间!

最好的问候,

埃德

【问题讨论】:

    标签: javascript parsing grammar abstract-syntax-tree pegjs


    【解决方案1】:

    我对 PEG 也很陌生,但您主要看 examples 而不是阅读文档后就会掌握它。

    尝试将您的版本与此版本进行比较:

    start
      = ws* predicate:predicate ws* { return predicate; }
    
    predicate
      = "OR" ws* "(" operands:operand+ ")"  { return { predicate: 'OR', operands: operands }; }
      / "AND" ws* "(" operands:operand+ ")" { return { predicate: 'AND', operands: operands }; }
    
    operand
      = ws* predicate:predicate ws* { return predicate; }
      / ws* string:string ws* { return string; }
    
    string
      = "\"" chars:valid_variable_characters+ "\"" { return { type: "STRING", value: chars.join("")}}
    
    valid_variable_characters = [a-zA-Z0-9 _]
    ws = [ \t\n]
    

    空格是可选的。

    OR("str1"OR("str2""str3"AND("str4""str5"))"str6")
    

    给予:

    {
       "predicate": "OR",
       "operands": [
          {
             "type": "STRING",
             "value": "str1"
          },
          {
             "predicate": "OR",
             "operands": [
                {
                   "type": "STRING",
                   "value": "str2"
                },
                {
                   "type": "STRING",
                   "value": "str3"
                },
                {
                   "predicate": "AND",
                   "operands": [
                      {
                         "type": "STRING",
                         "value": "str4"
                      },
                      {
                         "type": "STRING",
                         "value": "str5"
                      }
                   ]
                }
             ]
          },
          {
             "type": "STRING",
             "value": "str6"
          }
       ]
    }
    

    【讨论】:

    • 哇,非常感谢。我能够以您的示例为基础并从那里建立起来。这太棒了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    相关资源
    最近更新 更多