@matの提案をフォローアップし、トークンストリーム用の構文を使用すると、ここに簡単な例があります。
はあなたの言語を定義し、次のBNFがあるとします。
<program> ::= program begin <statement_list> end .
<statement_list> ::= <statement> | <statement> ; <statement_list>
<statement> ::= ...
あなたはあなたのパースツリーを表現する方法を決定する必要があります。私は組み込みリストとしてn-ary構文木を表現するのにぎこちない方法のように思っていましたが(私はそれに多くのことを考えませんでした)、うまくいけば、それがどのように動作するのかを知ることができます。あなたのDCGは直接BNFを反映することになる、との引数は、解析ツリーのようになります。
program([key(program), key(begin), AST_statement_list, key(end), sep(.)]) -->
[key(program), key(begin)],
statement_list(AST_statement),
[key(end), sep(.)].
statement_list([AST]) --> statement(AST).
statement_list([AST_statement | AST_statement_list]) -->
statement(AST_statement),
statement_list(AST_statement_list).
statement(AST) --> ...
あなたはトークンストリームであなたのDCGを呼び出すことによって解析します:
phrase(program(ParseTree), TokenStream).
プログラム解析ツリーは次のようになります:
[key(program), key(begin), [Statement1_List, Statement2_List, ...], key(end), sep(.)]
は各StatementN_List
は、それ自体が文のサブツリーのためのn分木になります。
[タグ:dcg]を参照してください。純粋なプロローグの関係は、*すべての方向*で使用できます。つまり、リストとその解析木の間の関係を記述すると、リストとツリーの両方を解析する**と**を生成することができます。抽象構文ツリーとトークンのリストの間の関係を記述する 'program(AST) - > ...'のようなDCGルールから始めましょう。 – mat