1

ANTLR と Java を使用してコンパイラを作成しようとしています。ルールがあり、その一部だけを使用できないという問題があります。0: HALT 0,0,0 などのコマンドがあり、その後はすべて無視したいと考えています。

eg0: HALT 0,0,0 何とか何とか何とか、何とか無視したい

私のルールは次のとおりです。

    rule returns [String value]
    :
    INTEGER':' ro=rocommand i1=INTEGER',' i2=INTEGER ',' i3=INTEGER rest {$value = $ro.text+" "+$i1.text+","+$i2.text+","+$i3.text;   }
    | INTEGER':' rm=rmcommand j1=INTEGER ',' j2=INTEGER '('j3=INTEGER')' rest {$value = $rm.text+" "+$j1.text+","+$j2.text+"("+$j3.text+")"; }
;

私が持っているコードは次のとおりです。

CharStream charStream = new ANTLRStringStream(strLine);
simulatorLexer lexer = new simulatorLexer(charStream);
TokenStream tokenStream = new CommonTokenStream(lexer);
simulatorParser parser = new simulatorParser(tokenStream);
System.out.println(parser.rule());

私が得るものは次のとおりです。

0: rule:IN 0,0,0
1: rule:LDC 1,1,0
line 1:15 no viable alternative at character 'r'
line 1:18 no viable alternative at character '='
line 1:15 no viable alternative at character 'i'

テキストの場合:

0: rule:IN 0,0,0
1: rule:LDC 1,1,0 r1=0

したがって、最初の行を正しく解析し、2 行目を 0 まで解析する必要があります。その後、r1=0 を無視する必要があります。今までは正常に動作していましたが、いくつかのエラーが表示され、それらを取り除きたいと考えています。私を助けてください!

編集

あなたが私をより良く助けることができるように、私は文法全体を投稿しています. ルール部分を認識したいだけです。

program:
    rule+
;


rocommand:
    'HALT'|'IN'|'OUT'|'ADD'|'SUB'|'MUL'|'DIV'|'LDC'
;

rmcommand:
    'LD'|'LDA'|'LDC'|'ST'|'JLT'|'JLE'|'JGE'|'JGT'|'JEQ'|'JNE' 
;

rest:
  ~('\n'|'\r')* '\r'? ('\n'|EOF)
;

rule returns [String value]
    :
    INTEGER':' ro=rocommand i1=INTEGER',' i2=INTEGER ',' i3=INTEGER rest {$value = $ro.text+" "+$i1.text+","+$i2.text+","+$i3.text;   }
    | INTEGER':' rm=rmcommand j1=INTEGER ',' j2=INTEGER '('j3=INTEGER')' rest {$value = $rm.text+" "+$j1.text+","+$j2.text+"("+$j3.text+")"; }
;

WS  : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};
INTEGER : '0'..'9'+;
IGNORELINE : '*' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;};
4

1 に答える 1

4

このルールには、次の 2 つの問題があります。

rest:
  ~('\n'|'\r')* '\r'? ('\n'|EOF)
;

パーサー ルール内では~、レクサーが生成するトークンのセット全体を否定します。そのため、または以外の単一の文字には一致~('\n'|'\r')しませ。またはに一致したトークン以外の任意のトークンに一致します。'\n''\r'\r\n

また、lexer は隠しチャネルに'\n'and'\r'を置くため、これらのトークンはパーサーで使用できません。これは'\n'restルール内の が決して一致しないことを意味します。

要するに、これらの文字はWSルールによって破棄されるため、パーサーに行の終わりを「伝える」ことはできません。restこれは、そのようなパーサー ルールを適切に記述する方法がないことを意味します。

あなたの入力のために:

0: IN 0,0,0
1: LDC 1,1,0 r1=0

(私が削除したことに注意してください'rule:'

次のトークンがレクサーによって生成されます。

token[type=INTEGER text='0']
token[type=':'     text=':']
token[type='IN'    text='IN']
token[type=INTEGER text='0']
token[type=','     text=',']
token[type=INTEGER text='0']
token[type=','     text=',']
token[type=INTEGER text='0']
token[type=INTEGER text='1']
token[type=':'     text=':']
token[type='LDC'   text='LDC']
token[type=INTEGER text='1']
token[type=','     text=',']
token[type=INTEGER text='1']
token[type=','     text=',']
token[type=INTEGER text='0']
token[type=INTEGER text='1']
token[type=INTEGER text='0']

したがって、これらはパーサー ルールで使用できるトークンです。

エラーを見てわかるように、次の 2 つの文字:'='とはレクサーによって照合できないことに注意してください。'r'

line 2:13 no viable alternative at character 'r'
line 2:15 no viable alternative at character '='

考えられる解決策は、整数とコロンに一致するレクサー ルールを作成することです。

START : INTEGER ':';

ruleそして、このトークンから始めましょう:

rule
 : START ro=rocommand i1=INTEGER ',' i2=INTEGER ',' i3=INTEGER rest ...
 | ...
 ;

そうすれば、restそのトークン以外の 0 個以上のトークンに一致させることができSTARTます。

rest
 : ~START*
 ;

'='および'r'文字をキャプチャするには、ANYルールを作成し、このルールをレクサー ルールの最後に配置します。

ANY : . ; // match any char

そうすれば、パーサーは次の解析ツリーを作成します。

ここに画像の説明を入力

別の解決策は、LINE_BREAKトークンを作成することです。

LINE_BREAK : '\r'? '\n' | '\r';

(もちろん、からと を削除\rしてください!)\nWS

そして、次のようにします。

rule
 : INTEGER ':' ro=rocommand i1=INTEGER ',' i2=INTEGER ',' i3=INTEGER rest LINE_BREAK ...
 | ...
 ;

rest
 : ~LINE_BREAK*
 ;
于 2012-08-26T08:49:22.737 に答える