首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PEGJS:为谓词第一语法生成AST

PEGJS:为谓词第一语法生成AST
EN

Stack Overflow用户
提问于 2015-03-11 00:54:33
回答 1查看 1.2K关注 0票数 3

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

代码语言:javascript
复制
OR(
   "string1"
   "string2"
)

我希望将上述内容转化为:

代码语言:javascript
复制
{
   predicate: "OR",
   operands: [
        {
           type: "STRING",
           value: "string1"
        },
        {
           type: "STRING",
           value: "string2"
        }
   ]
}

此查询:

代码语言:javascript
复制
OR(
    "string1"
    "string2"
    AND (
        "string4"
        "string5"
    )
    "string3"
)

会变成这样的AST:

代码语言:javascript
复制
{
    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)中。

代码语言:javascript
复制
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之后,"string“在末尾):

代码语言:javascript
复制
OR(
   OR (
      "string1"
   )
   "string2"
)

我不知道是什么导致了这件事,也不知道如何解决。

2.语法中目前有一条用于operand规则的愚蠢行:

代码语言:javascript
复制
operand =
    string
    / ws or_predicate:or_predicate { return or_predicate; }

注意or_predicate前第三行的前导空格(ws)。如果没有这个空格,我就会得到错误“超过最大调用堆栈大小”。我认为这与左递归有关,但并不是肯定的。理想情况下,我希望能够在那里没有必需的'ws‘,这样一个没有空格的查询就能工作:

代码语言:javascript
复制
OR("string1"OR("string2")"string3")

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

代码语言:javascript
复制
OR("string1" OR("string2") "string3")

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

感谢您的帮助和时间!

诚挚的问候,

边缘

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-12 11:53:43

我对聚乙二醇也很陌生,但是在主要看示例而不是阅读文档之后,您就掌握了它的诀窍。

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

代码语言:javascript
复制
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]

空白是可选的。

代码语言:javascript
复制
OR("str1"OR("str2""str3"AND("str4""str5"))"str6")

给予:

代码语言:javascript
复制
{
   "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"
      }
   ]
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28976751

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档