ルール内または括弧で囲まれたサブルール内の非終端記号の1つから値を返す必要があるのは非常に一般的です。 例えば:
varDecl = type:type id:ID init:( EQ e:expr {return e} )?
{ return scopedAST('VARDECL', {type, id, init}) }
この場合、言語のオプションのフレーズのinit
括弧レベル内にe
というラベルの付いたexpr
必要でした。 戻り値の一部として「ノイズワード」 EQ
は必要ありませんでした。
PEGjs言語に、上記のexpr
ような端末をマークするために使用される記号があり、それらだけが文法規則またはサブ規則から返される値になる場合、この場合はより簡単になります。
上記の私の例を書き直すには:
varDecl = type:type id:ID init:( EQ ^expr )?
{ return scopedAST('VARDECL', {type, id, init}) }
^
を使用してinit
括弧で囲まれたオプションのフレーズサブルール内のexpr
値をマークし、 init
バインドされるものを指定することに注意してください。 これにより、この例に示されている括弧で囲まれたサブルールがある場合とない場合の両方で、多くの状況が単純化されます。
このような素晴らしくシンプルでエレガント、そして強力なツールを作ってくれてありがとう。 私はPEGjsが大好きです! :笑顔:
そのアイデアが大好き! ^
も非常に直感的です。
これは、ネストされていないルールでも機能する可能性があります。
WhiteSpacedIdentifier = WhiteSpace? identifier:Identifier WhiteSpace {return identifier;}
// becomes
WhiteSpacedIdentifier = WhiteSpace? ^Identifier WhiteSpace?
とても読みやすい! おそらく、次のように、複数の^
することもできます。
a = ^b c ^d e
[b, d]
返しますか? 理にかなっているようです。
同様に、名前付きキャプチャと混合した場合、 ^
ルールが無視されることは理にかなっているようです。
x = a ^b foo:c { return foo; }
cのみを返します。
ああ、その倍数のアイデアは素晴らしいです。 名前付きキャプチャとのミキシングは
エラー。
火、2016年7月5日には、午前1時07分グラハムウェイクフィールド[email protected]
書きました:
とても読みやすい! おそらく、複数の^の使用も機能し、次のようになります。
a = ^ bc ^ de
[b、d]を返しますか? 理にかなっているようです。
同様に、名前付きキャプチャと混合した場合、^
ルールは無視されます:x = a ^ b foo:c {return foo; }
—
スレッドを作成したため、これを受け取っています。このメールに直接返信し、GitHubで表示してください
https://github.com/pegjs/pegjs/issues/427#issuecomment -230413015、またはミュート
スレッド
https://github.com/notifications/unsubscribe/ABC26k8v0DIzuWUlkoDZGm2ep10Y5bcMks5qShDAgaJpZM4IkuA9
。
説明されているパターンが非常に一般的であることに完全に同意します。 アクションなしでそれを表現する方法を持つことは理にかなっています。
提案された解決策( ^
演算子)について私がよくわからないこと。 意味がすぐにはわからない特殊文字を使用することは常に問題があり、学習曲線に追加されます。 キャラクターが他の目的に使用される可能性もあります。 最後になりましたが、構文解析に直接影響を与えないものを式に入れるというアイデアは好きではありません。 これにはすでに1つのインスタンス( $
演算子)があると主張できますが、私は同意します。 しかし、 $
追加が(小さな)間違いではなかったかどうかはわかりません。 もしそうなら、私はそれを再び作ることを避けたいと思います。
これについては、1.0.0以降でさらに深く考えます。
もう少し考えてみてください。 ^
とラベル付きの式は衝突するので( ^
無視することを提案します)、結果をマークする代わりに、たとえば_ignored_式をマークすることができます。 (構文の提案!)空のラベルを提供することによって:
WhiteSpacedIdentifier = WhiteSpace? identifier:Identifier WhiteSpace {return identifier;}
// becomes
WhiteSpacedIdentifier = :WhiteSpace? Identifier :WhiteSpace?
そこには、新しい構文はなく(すでに:
があります)、セマンティクスが少し拡張されているだけです。
その場合、より一貫性のあるものは、結果として返される必要がある式を空の「ラベル」でマークします。 ちなみに、既存のセマンティクスを壊さないでください。ラベルは存在しますが、名前はありません。 結果にアクセスするためにラベルが導入されているため、名前のないラベルが自動的に結果になるのは非常に論理的です。 自動ラベルと具体ラベルの同時存在は禁止されます。 自動ラベルが1つしかない場合は、単一の結果を返す必要がありますが、そのような動作はより要求されるため、1つの要素を持つ配列を返す必要はありません。
@Mingun
ラベルを返してみませんか?
start = "{" :expr "}" // return expr
start = "{" label:expr "}" // return label
何かに「ラベルを付ける」場合は、それを使って何かをしたい(たとえば、返品する)のは理にかなっていると思います。
一方、 start = ex:expr :expr
ようなルールでエラーが発生するのはなぜですか?
多分それはjavascriptの関数の引数変数に似た何かをするべきですか? たとえば、 start = ex:expr :expr
は[ex, expr]
を返す必要があります。 アクションがある場合は、& arguments
変数( start = ex:expr :expr { return [ex, arguments[0], ex] }
)というラベルを付ける必要があります
@alanmimms私はこのアイデアが好きです。 単純な値を返すためだけに名前(変数/ラベル)を作成する必要はありません。
名前のないラベル( :expr
)は^expr
よりも優れていると思います
ラベルを返してみませんか?
@nedzadarekは、式に名前を付けると、重要な式でそれを使用しない可能性が高くなるためです。 少なくとも、名前はあなたにとって重要です、さもなければあなたはそれを与えないでしょう、本当に? また、名前の付いたラベルと名前のないラベルを混在させることは、意識的な行動よりも間違いである可能性が高いため、禁止されている方が安全です。 ある名前を付けたら、別の名前を付けてみませんか?
残念ながら、その自動ラベルは@opatutによって提供されるものに
start = a :b;// `a` - it is rule reference or label?
a = .;
b = .;
したがって、この目的のために別のキャラクターを選択する必要があります。 現時点では、 ~
、 (backslash)
、 @
、 #
、 %
、 ^
、 -
、 |
、 \
および,
。
別の解決策-いくつかの疑似アクションを導入します-戻り値の単純な関数を作成するためのショートカット。たとえば、 {=>[]}
は、_ "シーケンスからラベル付けされた結果を収集し、それらを配列に返す" _を意味します。 、および{=>{}}
-同じですが、オブジェクトを返します。キーはラベルの名前と同じです。 ただし、この動作の実装には文法の拡張は必要なく、プラグインによって完全に実現できます。 プラグインでこのような実装を行う方が望ましいとさえ言えます。
start1 = a:'a' b c d:. {=>[]};// returns ['a', <d value>]
start2 = a:'a' b c d:. {=>{}};// returns { a: 'a', d: <d value> }
@Mingun
式に名前を付けると、重要な式でそれを使用しない可能性が高くなるためです。 少なくとも、名前はあなたにとって重要です、さもなければあなたはそれを与えないでしょう、本当に?
はい、名前は重要です=>使いたい=>返品したいです。
自明でない表現の問題は何ですか?
残念ながら、その自動ラベルは@opatutによって提供されるものに
はい。
::expression
も混乱していると思いますか? @dmajda
#235の複製としてクローズ
編集:この問題を参照する#235に関するOPのコメントにメモを追加しました