あなたが何を求めているのかははっきりしていません。私が理解していることから、ソースの解析またはコードの生成に問題があります。
解析部分については、手動で記述したい場合は、再帰降下法を簡単に使用できます。基本的に、式、ブロック、if、while、for などのステートメントなど、各構文クラスを解析する関数を作成します。再帰的にお互いを呼び出すようにします。通常、パーサー関数は AST ノードを返し、呼び出し元はそれらをより大きなノードで構成します。
あなたの例では、論理式、ifステートメント、式/ステートメントのブロック、およびifステートメントを解析するための関数があります。トークン ストリームにが表示if
されたら、if ステートメントが続くことがわかるので、適切な解析関数を呼び出しますparse_if
。文法のおかげで、parse_if
andif
ステートメントは次のように見える必要がありますif (<logical expression>) <block> [else <block>]
--角括弧はオプションのブロックを表し、角括弧は必須です。したがって、最初に論理式を解析する関数を再帰的に呼び出しますparse_logical_exp
。これにより、後で最終的な AST にプラグインできる if ステートメントの論理式の AST ノードが返されます。then ブロックについても同様です。then ブロックを使用した後で、else
トークン ストリームで、ブロック解析関数を再度呼び出します。どのサブ関数もエラーを通知しなかった場合は問題ないので、最終的に if ステートメントの AST を構築し、それを呼び出し元に返すことができます。(Python) 擬似コード:
def parse_if(tokens):
# Skip over the if token or signal an error if the current token is not an "if"
tokens.expect("if")
logical_condition = parse_logical_exp(tokens)
if logical_condition is Error:
raise ParseError(logical_condition.message)
then_block = parse_block(tokens)
if then_block is Error:
raise ParseError(then_block.message)
else_block = None
if tokens.current() == "else":
# Skip over the else token or signal an error
tokens.expect("else")
else_block = parse_block(tokens)
if else_block is Error:
raise ParseError(else_block.message)
return IfNode(logical_condition, then_block, else_block)
これは単なる疑似コードであり、別の方法でエラー チェック/レポートを実行したい場合があることに注意してください。
あなたが言及しているかもしれない問題は、「dangling else problem」と呼ばれます。基本的に、else がどちらに属しているかはわかりません。ウィキペディアの記事から引用するには:
ぶら下がっているelseを扱うときの慣例は、elseを近くのifステートメントに付けることであり、特に、明確な文脈自由文法を可能にします。Pascal や C などのプログラミング言語はこの規則に従っているため、言語のセマンティクスにあいまいさはありません。
コード生成部分については、次の質問への回答に興味があるかもしれません:バイトコード コンパイラでジャンプ アドレスを計算するためのインテリジェントなソリューションは? .