首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Pegjs保留关键字

Pegjs保留关键字
EN

Stack Overflow用户
提问于 2019-07-16 17:07:03
回答 1查看 139关注 0票数 2

我有个语法支持这个:

和,或,不,(和),",‘

我需要分析的东西很少有样例:

  • a1或a2
  • a1 a2 (与上文相同)
  • a1和a2
  • "a1“和”a2“
  • a1或a2而非a3
  • a1 a2或"a3“NOT(a1和a2 'a6')

考虑到a1、a2等是真正的用户输入,几乎可以包括以下内容:

  • 123
  • 特斯拉-S
  • 折纸

我遇到的问题是,当其中一个单词没有引号,并且以保留关键字开头时,例如:

  • 折纸
  • 仙女座

在本例中,此解析器考虑:

  • 或关键字+ igami文本
  • 和关键字+ romede文本

这就是我遇到的问题。

我尝试了两天不同的解决方案,在堆栈溢出(和官方文档)上找到:

(和许多其他的)试图找到一个有这些约束的解决方案:

  • 不能保证在关键字之前/之后有空格,例如"a1和(a2或a3)“是有效的(在”和“和"(")之间没有空格,"(a1和a2)和a3”(a1和a2)或“=> a关键字”之前/之后可能有空格和/或“(”//“)”(但当我尝试这样做时,我打破了括号规则)
  • 只有在保留部分:“和”i/“或”i/“”不是“i/ "(”/“)/”‘’/‘’/“=>的时候,单词才不是一个词

下面是我想出的代码:

代码语言:javascript
复制
content = andOperator

andOperator
    = head:orOperator tail:(_ "AND"i _ orOperator)* {
        return tail.reduce(function(result, element) {
            return {
                type: "and",
                value: {
                    left: result,
                    right: element[3]
                }
            };
        }, head);
    }

orOperator
    = head:notOperator tail:(_ ("OR"i / _) _ notOperator)* {
        return tail.reduce(function(result, element) {
            return {
                type: "or",
                value: {
                    left: result,
                    right: element[3]
                }
            };
        }, head);
    }

notOperator
    = head:parenthesis tail:(_ ("AND"i / "OR" / _) _ "NOT"i _ parenthesis)* {
        return tail.reduce(function(result, element) {
            var type = (element[1] && element[1].toLowerCase() === "or") ? "or" : "and";
            return {
                type: type,
                value: {
                    left: result,
                    right: {
                        type: "not",
                        value: element[5]
                    }
                }
            };
        }, head);
    }

parenthesis "Parenthesis"
    = _ "(" _ inside:content+ _ ")" _ {
        return {
            type: "parenthesis",
            value: (Array.isArray(inside) && inside.length === 1) ? inside[0] : inside
        };
    } / text

/*
-----------------------------
  TEXT
-----------------------------
*/

text "Text"
    = _ inside:(singleQuoteText / doubleQuoteText / noQuoteText)+ _ {
        return (Array.isArray(inside) && inside.length === 1) ? inside[0] : inside;
    }

singleQuoteText "Single Quote Text"
    = "'" text:$([^\']+) "'" {
        return {
            type: "text",
            value: text ? text.trim(): text
        };
    }

doubleQuoteText "Double Quote Text"
    = '"' text:$([^\"]+) '"' {
        return {
            type: "text",
            value: text ? text.trim(): text
        };
    }

noQuoteText "No Quote Text"
    = text:$(!reserved .)+ {
        return {
            type: "text",
            value: text ? text.trim(): text
        };
    }

reserved "List of keyword this grammar allow"
    = ("AND"i / "OR"i / "NOT"i / "(" / ")" / "'" / '"' / " ")

/*
-----------------------------
  WHITESPACE PARSING
-----------------------------
*/
__ "Mandatory Whitespace"
    = $(whitespace+)

_ "Optional Whitespace"
    = __?

whitespace
    = [\u0009\u000B\u000C\u0020\u00A0\uFEFF\u1680\u180E\u2000-\u200A\u202F\u205F\u3000] / $('\r\n' / '\n')

问题的例子: hello折纸

给出当前语法:

代码语言:javascript
复制
{
   "type": "or",
   "value": {
      "left": {
         "type": "text",
         "value": "hello"
      },
      "right": {
         "type": "text",
         "value": "igami"
      }
   }
}

应该给予(它认为折纸是一个完整的世界,而不是或+ igami):

代码语言:javascript
复制
{
   "type": "or",
   "value": {
      "left": {
         "type": "text",
         "value": "hello"
      },
      "right": {
         "type": "text",
         "value": "origami"
      }
   }
}

在当前解析器中折纸被拆分为OR + igami,而它应该考虑整个单词折纸。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-23 14:38:49

使用谓词,您可以包含一个与所有单词匹配的规则,但关键字除外,如下所示:

代码语言:javascript
复制
{

   var keywords = ["and", "or"];

}

Expression =
    word:$(Word) { return { word: word } } /
    keyword:$(Keyword) { return { keyword: keyword } }

// Word will match everything except "and" and "or",
// including words like "origami" and "andromede"
Word = word:$([a-zA-Z]+) &{ return !keywords.includes(word) }

Keyword = [a-zA-Z]+

在上述语法中,Word将匹配除“或”和“和”以外的所有单词。如果单词(然后是整个单词)是这些关键字之一,那么Keyword规则将与之匹配。

因此,给定输入and,您将得到以下输出:

代码语言:javascript
复制
{
    keyword: "and"
}

但是,给定输入andromede,您将得到以下输出:

代码语言:javascript
复制
{
    word: "andromede"
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57062299

复制
相关文章

相似问题

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