あなたは間違いなくこのようなことを行うことができますが、明らかにソースコードの直感性を破壊します。これを実際に実装する限り、レクサーはまったく変更する必要はありません。レクサーがソースの "if"と一致する場合は、IF
タイプのトークンを返します。
IF, LARROW, INTLITERAL, SEMICOLON
私は可能性があります:私たちはif
は変数名であり、それはパーサに供給するためのレクサーのトークンストリームは1です。
if <- 1;
値が割り当てなってき以下の代入文を、持っていると仮定、
assignStmt::= id:i LARROW intExpr:e SEMICOLON {: RESULT = new AssignmentStatement(i, e) :}
intExpr::= INTLITERAL:i {: RESULT = i.intVal; :}
id::= ID:i {: RESULT = i.strVal; :}
LARROW
、ID
:(W整数rvals \)代入文を記述するために、次の作品を持っていますIF
,INTLITERAL
およびSEMICOLON
は、レクサーによって返されるトークンであり、assignStmt
,id
およびintExpr
は非終端記号である端末である。 ID
は、識別子(例えば、クラス/変数/メソッド名)を表す。
if文の生成に失敗した後、最終的に代入文の最初のプロダクションを入力します。私たちはid
非ターミナルを展開します。唯一の生産はID
ですが、一致させたいトークンはIF
なので、assignStmt
の生産は完全に失敗します。
assignStmt::= id:i LARROW intExpr:e SEMICOLON {: RESULT = new AssignmentStatement(i, e) :}
intExpr::= INTLITERAL:i {: RESULT = i.intVal; :}
id::= ID:i {: RESULT = i.strVal; :}
|IF {: RESULT = "if"; :}
注|
は、非ターミナルの代替生産を定義していること:私がしなければならないすべてが「あれば」変数は名前を付けることができるように、私の言語については
。現在、非ターミナルのid
の2番目の生産があり、現在のトークンと一致し、最終的に代入文と一致します。
AssignmentStatement
は、次のように定義されたASTノードです:
class AssignmentStatement {
String varName;
int intVal;
AssignmentStatement(String s, int i){varName = s; intVal = i; }
}
パーサは、ソースが構文的に正しいことを決定すると、他に何も影響を与えてはなりません。変数の名前は、コンパイルの後半には影響しないはずです。つまり、コンパイルの実行を許可する条件を作成しない場合です。
このように、能力は、コンパイラを「混乱させる」だけでなく、その言語でコードを読む人々にも役立ちます。結局これを許可するのはなぜですか? – kirilloid