また、lexer のどこかで最初の行の前にある ident アイテムの数を追跡し、それをパーサーに渡すこともできます。最も興味深い部分は、それをパーサーに正しく渡そうとすることです:)パーサーが先読みを使用している場合(ここでは、パーサーが実際に1つでも一致する前に可変数のトークンを照会する可能性があることを意味します)、1つのグローバル変数を介してそれを渡そうとするようです非常に悪い考えです(パーサーがまだ前の行を解析しようとしている間に、レクサーが次の行でスリップしてインデントカウンターの値を変更する可能性があるため)。また、他の多くの場合、グローバルは悪です;) インデントカウンターを使用して、最初の行の「実際の」トークンをマークする方が合理的です。正確な例を示すことはできません (もしあれば、どのパーサーとレクサージェネレーターを使用するのかさえわかりません... )しかし、最初の行のトークンにデータを保存するようなもの(パーサーからそのようなトークンを簡単に取得できない場合は快適ではない可能性があります)またはカスタムデータを保存する(トークンをインデントにリンクするマップ、ソースコードのすべての行がインデックスとして配置される配列要素値としてのインデント値) で十分なようです。このアプローチの欠点の 1 つは、ident 値を区別し、それに基づいて動作を変更する必要があるパーサーがさらに複雑になることです。JavaCC の LOOKAHEAD({ yourConditionInJava }) のようなものがここで機能する可能性がありますが、このアプローチの欠点の 1 つは、ident 値を区別し、それに基づいて動作を変更する必要があるパーサーがさらに複雑になることです。JavaCC の LOOKAHEAD({ yourConditionInJava }) のようなものがここで機能する可能性がありますが、このアプローチの欠点の 1 つは、ident 値を区別し、それに基づいて動作を変更する必要があるパーサーがさらに複雑になることです。JavaCC の LOOKAHEAD({ yourConditionInJava }) のようなものがここで機能する可能性がありますが、あまり良い考えではありません。あなたのアプローチに多くの追加のトークンを使用することは、それほど悪いことではないようです:)
別の方法として、この 2 つのアプローチを組み合わせることをお勧めします。インデントカウンターが次の行で値を変更した場合にのみ、追加のトークンを生成できます。人工的な BEGIN および END トークンのようなものです。このようにして、レクサーからパーサーに供給されるストリーム内の「人工」トークンの数を減らすことができます。追加のトークンを理解するには、パーサーの文法だけを調整する必要があります...
私はこれを試しませんでした (そのような言語の解析に関する実際の経験はありません)。可能な解決策について私の考えを共有しただけです。この種の言語用に既に構築されたパーサーをチェックすることは、あなたにとって大きな価値があります。オープンソースはあなたの友達です ;)