Pegjs 保留关键字
Pegjs reserved keyword
我得到了支持这个的语法:
与、或、非、(和)、"、'
我需要能够解析的东西很少:
- a1 或 a2
- a1 a2(同上)
- a1 和 a2
- "a1" 和 'a2'
- a1 或 a2 不是 a3
- a1 a2 OR "a3" NOT(a1 AND a2 'a6')
考虑到 a1、a2 等是真实的用户输入,几乎可以包括以下任何内容:
- 123
- 特斯拉-S
- 折纸
我遇到的问题是,其中一个单词没有引号,并且以某个保留关键字开头,例如:
- 折纸
- 仙女座
在这种情况下,此解析器考虑:
- 或关键字+ igami文本
- and 关键字 + romede 文本
这就是我遇到的问题。
我已经尝试了两天各种解决方案,在 Whosebug(和官方文档)上找到:
- Pegjs: Don't allow reserved keywords as a variable name
(和许多其他)试图找到具有这些约束的解决方案:
- 不保证有space before/after关键字,例如"a1 AND(a2 OR a3)"有效("AND"和"(")之间没有space , "(a1 AND a2)OR a3" => 一个关键字也可以有 before/after 它,一个 space and/or "("/")" (但是当我尝试这个时我打破括号规则)
- 一个词只有在它是保留部分的一部分时才不是一个词:"AND"i / "OR"i / "NOT"i / "(" / ")" / " '" / '"' / " " => 任何一个都不是一个词,其他的都是,比如 ando 是一个词,而不是关键字。
这是我想出的代码:
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')
问题示例:你好折纸
给出当前语法:
{
"type": "or",
"value": {
"left": {
"type": "text",
"value": "hello"
},
"right": {
"type": "text",
"value": "igami"
}
}
}
应该给出(它认为折纸是一个完整的世界而不是 or + igami):
{
"type": "or",
"value": {
"left": {
"type": "text",
"value": "hello"
},
"right": {
"type": "text",
"value": "origami"
}
}
}
当前解析器中的 Origami 被拆分为 OR + igami,而它应该考虑整个单词 origami...
使用谓词,您可以包含匹配除关键字之外的所有词的规则,如下所示:
{
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
会匹配除"or"和"and"之外的所有单词。如果单词(那么 entire 单词)是这些关键字之一,那么 Keyword
规则将改为匹配。
因此,给定输入 and
,您将得到以下输出:
{
keyword: "and"
}
但给定输入 andromede
,您将得到以下输出:
{
word: "andromede"
}
我得到了支持这个的语法:
与、或、非、(和)、"、'
我需要能够解析的东西很少:
- a1 或 a2
- a1 a2(同上)
- a1 和 a2
- "a1" 和 'a2'
- a1 或 a2 不是 a3
- a1 a2 OR "a3" NOT(a1 AND a2 'a6')
考虑到 a1、a2 等是真实的用户输入,几乎可以包括以下任何内容:
- 123
- 特斯拉-S
- 折纸
我遇到的问题是,其中一个单词没有引号,并且以某个保留关键字开头,例如:
- 折纸
- 仙女座
在这种情况下,此解析器考虑:
- 或关键字+ igami文本
- and 关键字 + romede 文本
这就是我遇到的问题。
我已经尝试了两天各种解决方案,在 Whosebug(和官方文档)上找到:
- Pegjs: Don't allow reserved keywords as a variable name
(和许多其他)试图找到具有这些约束的解决方案:
- 不保证有space before/after关键字,例如"a1 AND(a2 OR a3)"有效("AND"和"(")之间没有space , "(a1 AND a2)OR a3" => 一个关键字也可以有 before/after 它,一个 space and/or "("/")" (但是当我尝试这个时我打破括号规则)
- 一个词只有在它是保留部分的一部分时才不是一个词:"AND"i / "OR"i / "NOT"i / "(" / ")" / " '" / '"' / " " => 任何一个都不是一个词,其他的都是,比如 ando 是一个词,而不是关键字。
这是我想出的代码:
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')
问题示例:你好折纸
给出当前语法:
{
"type": "or",
"value": {
"left": {
"type": "text",
"value": "hello"
},
"right": {
"type": "text",
"value": "igami"
}
}
}
应该给出(它认为折纸是一个完整的世界而不是 or + igami):
{
"type": "or",
"value": {
"left": {
"type": "text",
"value": "hello"
},
"right": {
"type": "text",
"value": "origami"
}
}
}
当前解析器中的 Origami 被拆分为 OR + igami,而它应该考虑整个单词 origami...
使用谓词,您可以包含匹配除关键字之外的所有词的规则,如下所示:
{
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
会匹配除"or"和"and"之外的所有单词。如果单词(那么 entire 单词)是这些关键字之一,那么 Keyword
规则将改为匹配。
因此,给定输入 and
,您将得到以下输出:
{
keyword: "and"
}
但给定输入 andromede
,您将得到以下输出:
{
word: "andromede"
}