2017-04-05 8 views
0

ANTLRWorks 2.1을 사용하여 ANTLR4에서 결합 된 문법을 연구하고 있습니다. 정의 된 렉서 규칙으로 인식되지 않고 정의 된 마지막 파서 룰에서만 인식되는 렉서 규칙 IdentifierBlock이 있습니다. 이러한 규칙 이후에 리터럴을 추가하면 이러한 오류가 제거되거나 숨겨집니다. (이탤릭체 토큰 오류를 던지고있다) 마지막에 오류가있는ANTL 4 결합 된 문법에서 Lexer 규칙을 인식하지 못함

내 문법 :

grammar GCombined; 

options { language = Cpp; } 

@lexer::namespace{AntlrTest01} 
@parser::namespace{AntlrTest01} 

    /* First Lexer Stage */ 

Bit: '0' | '1'; 
Digit : '0'..'9'; 
ODigit: '0'..'7'; 
XDigit: '0'..'f'; 
Letter: ('a'..'z') | ('A'..'Z'); 
Symbol: '|' 
     | '-' 
     | '!' 
     | '#' 
     | '$' 
     | '%' 
     | '&' 
     | '(' 
     | ')' 
     | '*' 
     | '+' 
     | ',' 
     | '-' 
     | '.' 
     | '/' 
     | ':' 
     | ';' 
     | '<' 
     | '=' 
     | '>' 
     | '?' 
     | '@' 
     | '[' 
     | ']' 
     | '^' 
     | '_' 
     | '`' 
     | '{' 
     | '|' 
     | '}' 
     | '~'; 
WSpace: (' ' 
     | '\t' 
     | '\r' 
     | '\n' 
     | '\c' 
     | '\0' 
     | '\u000C' 
     )+ -> skip; 

DNumber: Digit+; 
ONumber: '0o' Digit+; 
XNumber: '0x' Digit; 
Integer: DNumber 
     | ONumber 
     | XNumber; 
Float: DNumber '.' DNumber; 

Character: Letter 
     | Digit 
     | Symbol 
     | WSpace; 
String: Character+; 
Literal: '"' String '"'; 

Boolean: 'true' | 'false'; 

    /* Second Lexer Stage */ 

Number: Integer | Float; 
Identifier: Letter (Letter | Digit | '_')+; 
Keyword: Letter+; 
Operator: '+' 
     | '-' 
     | '*' 
     | '/' 
     | '%' 
     | '==' 
     | '!=' 
     | '>' 
     | '<' 
     | '>=' 
     | '<=' 
     | '&&' 
     | '||' 
     | '^' 
     | '&' 
     | '|' 
     | '<<' 
     | '>>' 
     | '~' ; 

Expression: (Operator | Identifier) 
     '(' (Identifier | Number)+ ')'; 
Parameter: Identifier 
     | Expression 
     | Number; 
Statement: Keyword '(' Parameter+ ')'; 
Block: '{' Statement+ '}'; 

    /* Third Lexer Stage */ 

Add: '+'; 
Sub: '-'; 
Mlt: '*'; 
Div: '/'; 
Mod: '%'; 
Mathop: Add | Sub | Mlt | Div | Mod; 

Deq: '=='; 
Neq: '!='; 
Gtr: '>'; 
Lss: '<'; 
Geq: '>='; 
Leq: '<='; 
Condop: Deq | Neq | Gtr | Lss | Geq | Leq; 

And: '&&'; 
Or: '||'; 
Xor: '^'; 
Bnd: '&'; 
Bor: '|'; 
Logop: And | Or | Xor | Bnd | Bor; 

Neg: '!'; 
Boc: '~'; 
Negop: Neg | Boc; 

Asl: '<<'; 
Asr: '>>'; 
Shftop: Asl | Asr; 

Eql: '='; 

Inc: '++'; 
Dec: '--'; 
Incop: Inc | Dec; 

Peq: '+='; 
Meq: '-='; 
Teq: '*='; 
Seq: '/='; 
Req: '%='; 
Casop: Peq | Meq | Teq | Seq | Req; 

Lparen: '('; 
Rparen: ')'; 
Lbrack: '['; 
Rbrack: ']'; 
Lbrace: '{'; 
Rbrace: '}'; 
Point : '.'; 
Colon : ':'; 

Numvar: Number 
     | Identifier 
     | Mathop '(' Parameter+ ')'; 
Boolvar: Boolean 
     | Identifier 
     | Condop '(' Parameter+ ')' 
     | Logop '(' Parameter+ ')'; 
Metaxpr: (Identifier | Operator) '(' Parameter+ ')'; 

    /* First Parser Stage */ 

    //expressions 

add: '+' '(' Numvar+ ')'; 
sub: '-' '(' Numvar+ ')'; 
mlt: '*' '(' Numvar+ ')'; 
div: '/' '(' Numvar+ ')'; 
mod: '%' '(' Integer+ ')'; 
mathexpr: add 
     | sub 
     | mlt 
     | div 
     | mod; 

eql: '==' '(' Parameter+ ')'; 
neq: '!=' '(' Parameter+ ')'; 
gtr: '>' '(' Parameter+ ')'; 
les: '<' '(' Parameter+ ')'; 
geq: '>=' '(' Parameter+ ')'; 
leq: '<=' '(' Parameter+ ')'; 
condexpr: eql 
     | neq 
     | gtr 
     | les 
     | geq 
     | leq; 

and: '&&' '(' Parameter+ ')'; 
or : '||' '(' Parameter+ ')'; 
xor: '^' '(' Parameter+ ')'; 
bnd: '&' '(' Parameter+ ')'; 
bor: '|' '(' Parameter+ ')'; 
logexpr: and 
     | or 
     | xor 
     | bnd 
     | bor; 

asl: '<<' '(' Parameter Numvar ')'; 
asr: '>>' '(' Parameter Numvar ')'; 
shiftexpr: asl | asr; 

neg: '!' '(' Parameter ')'; 
boc: '~' '(' Parameter ')'; 
negexpr: neg 
     | boc; 

arrexpr: Identifier '[' Numvar ']'; 

    //instruction forms 

vardec: 'def' '(' Identifier+ ')' ': ' Identifier ; 
lindec: Identifier '(' Identifier ')'; 
assign: '=' '(' (Identifier | lindec) Parameter ')'; 

incstmt: (Inc | Dec) '(' Identifier ')' 
     | Casop '(' Identifier Identifier ')'; 

cond: 'if' '(' Boolvar ')' Block 
    ('else if' '(' Boolvar ')' Block)? 
    ('else' Block)?; 

loop: (
     ('while' '(' (condexpr | negexpr) ')') 
    | ('for' '(' assign ',' (condexpr | negexpr) ',' incstmt')') 
    ) Block; 

fundef: 'func' '(' Identifier Parameter+ ')' ': ' Identifier Block; 
prodef: 'proc' '(' Identifier Parameter* ')' Block; 
call: Identifier '(' Parameter+ ')'; 

excHandler: 'try' Block 
      'catch' '(' Identifier ')' Block 
      ('finally' Block)?; 

classdef: 'class' '(' Identifier ')' (': ' _Identifier_)? _Block_; 
+1

오류를 나타내는 완전한 문법을 ​​제공해야합니다. – GRosenberg

답변

0

ANTLR은 명확한 문법 규칙이 필요합니다. 제공된 문법에서 Symbol 규칙은 Operator 규칙 및 다른 규칙과 충돌합니다. IdentifierLetter 규칙이 충돌합니다. 동일한 입력 (내용 : & 길이)을 일치시킬 수있는 경우 규칙이 충돌합니다.

또한 예를 들어, Symbol 규칙은 대체로 '{'을 포함합니다. 암시 적 토큰 유형이 Symbol 토큰 유형과 같지 않으므로 alts에서 임의의 문자에 '{' (암시 적 토큰 유형 임) 리터럴을 사용하는 후속 규칙이 일치하지 않습니다. 가장 좋은 방법은 리터럴의 중복 사용을 피하는 것입니다. 규칙에서 리터럴을 정의한 다음 해당 규칙을 참조하면됩니다.

Antlr4를 배우려면 TDAR 사본을 구입하는 것이 가장 좋습니다.

+0

저는 실제로 자습서와 코딩을 읽었습니다. 보라, 보라. 렉서 단계의 순서를 바꾸면 문제가 해결됩니다! –

+0

재정렬하면 다른 충돌 규칙이 예상대로 작동하지 않습니다! Antlr은 모호성을 처리하지 않습니다. 즉, (항상) 충돌 규칙의 첫 번째 (위에서 아래로)를 사용하고 나머지는 기능적으로 섀도 ​​잉하는 결과를 둡니다. – GRosenberg