2021年の更新
これは、 Peggy.jsのオンラインプレイグラウンドで実行される実際の例です。Peggy.jsは、活発に開発されているPEG.jsのフォークです。PEG.jsは、DavidMaidaによって廃止されました。
この例はINDENT
、、、SAMEDENT
およびDEDENT
ルールがどのように解析されるか、および解析場所を使用する方法を示しています。コンソールログを確認してください。
これらの構文を使用しますが、他のパーサジェネレータからは知られていない可能性があります。
(ファイルの先頭)
{{...}}
(グローバル初期化子)–...
パーサー生成で実行します。
{...}
(解析ごとの初期化子)–...
パーサーのインスタンス化で実行します。
(ファイル内)
X = Y {...}
(アクション)–成功し...
たときに実行します。Y
初期化子からの変数が利用可能です。何かを返す場合...
、それは返すものを置き換えY
ます。
$X
X
–結果ではなく、で解析されたテキストを返します。
... @X ...
(pluck演算子)–... X ...
の結果を。の結果に置き換えX
ます。
&{...}
(述語)–「そして...
また真実である必要がある」。
X = &(...)
–...
成功した場合、X
成功します。...
入力を消費しません。
詳細については、ドキュメントを参照してください。
{{
console.clear()
console.log('Parser generated')
}}
{
let indentstack = []
let indent = ''
function found (what) {
let loc = location()
console.log(`[${loc.start.line}:${loc.start.column} - ${loc.end.line}:${loc.end.column}] found ${what}`)
}
console.log('Parser instantiated')
}
DOCUMENT = NEWLINES? @THINGS NEWLINES? _
THINGS = ( SAMEDENT @( OBJECT / LINE ) )*
OBJECT = key:KEY childs:(BLOCK / INLINE) {
found(`object "${key}"`)
let o = {}
o[key] = childs
return o
}
KEY = @$( [^ \t\r\n:]+ ) _ ':' _
BLOCK = NEWLINES INDENT @THINGS DEDENT
INLINE = line:LINE { return [line] }
LINE = text:$( (!EOL .)+ ) NEWLINES? {
found(`line "${text}"`)
return text
}
INDENT = &(
spaces:$( [ \t]+ ) &{
return spaces.length > indent.length
} {
indentstack.push(indent)
indent = spaces
}
) {
found('indent')
}
SAMEDENT = spaces:$( [ \t]* ) &{
return spaces === indent
} {
found('samedent')
}
/* Because of this rule, results cache must be disabled */
DEDENT = &{
indent = indentstack.pop()
return true
} {
found('dedent')
}
_ = [ \t]*
EOL = '\r\n' / '\n' / '\r'
NEWLINES = (_ EOL)+
/* Test with this input
H:
a
b
c
G:
d
e
f
*/
古い答え
これは、PEG.jsv0.10.0で機能する@JakubKulhanの文法の修正です。= &{ indent = indentStack.pop(); return true;}
PEG.jsでは{...}
文法内のスタンドアロンアクション()が許可されなくなったため、最後の行をに変更する必要があります。&{...}
この行は、常に成功する述語( )になりました( return true;
)。
pos = offset;
エラーが発生するため、も削除しましたoffset is not defined
。おそらく、Jakubは古いバージョンのPEG.jsで利用可能なグローバル変数を参照していました。PEG.jsは、location()
オフセットやその他の情報を含むオブジェクトを返す関数を提供するようになりました。
// do not use result cache, nor line and column tracking
{ var indentStack = [], indent = ""; }
start
= INDENT? l:line
{ return l; }
line
= SAMEDENT line:(!EOL c:. { return c; })+ EOL?
children:( INDENT c:line* DEDENT { return c; })?
{ var o = {}; o[line] = children; return children ? o : line.join(""); }
EOL
= "\r\n" / "\n" / "\r"
SAMEDENT
= i:[ \t]* &{ return i.join("") === indent; }
INDENT
= &(i:[ \t]+ &{ return i.length > indent.length; }
{ indentStack.push(indent); indent = i.join(""); })
DEDENT
= &{ indent = indentStack.pop(); return true;}
v 0.11.0以降、PEG.jsはValue Plucking演算子もサポートします。これ@
により、この文法をさらに簡単に記述できますが、現在オンラインパーサーにはないため、この例に追加することは控えます。