私は 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]
上記の文法は、私が示した 2 つの例を処理しますが、2 つの問題に気付き、次の 3 つの質問に至りました。
1.文法は、この一見単純な入力で失敗します (重要なのは、ネストされた OR が親 OR の直後に来て、「文字列」が最後にあるということです):
OR(
OR (
"string1"
)
"string2"
)
何がこれを引き起こしているのか、またはそれを修正する方法がわかりません。
2.文法には現在、operand
ルールに対して次のばかげた行があります。
operand =
string
/ ws or_predicate:or_predicate { return or_predicate; }
.の前の 3 行目の先頭の空白 (ws) に注意してくださいor_predicate
。その空白がないと、「最大コールスタックサイズを超えました」というエラーが表示されます。左再帰に関係していると思いますが、それについては肯定的ではありません。理想的には、必要な「ws」がないようにしたいので、次のようなスペースのないクエリが機能します。
OR("string1"OR("string2")"string3")
現時点では、次のような余分な空白を人為的に追加する必要があります。
OR("string1" OR("string2") "string3")
3. この文法へのアプローチは完全に間違っていますか? これは私が試みた 2 番目のものであり、1 番目は pegjs 算術の例に基づいていたので、これについて完全に間違っている可能性があり、それがこれらの問題に遭遇している可能性があることに気付きました。
あなたの助けと時間をありがとう!
よろしくお願いします、
エド