использование antlrworks для решения леворекурсивных - PullRequest
0 голосов
/ 03 декабря 2010

Привет, я хочу написать грамматику (используя ANTLRWORKS), которая позже примет (в режиме отладки) этот код

repeat_until
    :'repeat' seq_statement 'until' exp
    ;

read    :

          'read' ID ';'  
    ;

    fragment    
Operation_stat
    :   (NUMBER|ID) OP (NUMBER|ID) 
    ;

OP  :   ('+'|'-'|'*'|'/')
    ;

NUMBER  :
'0'..'9'+   
    ;

LOG_OP  :
('<' | '>' | '=' | '<=' | '>=' )
    ;


ID  :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;



FLOAT
    :   ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    |   '.' ('0'..'9')+ EXPONENT?
    |   ('0'..'9')+ EXPONENT
    ;

COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

STRING
    :  '\'' ( ESC_SEQ | ~('\\'|'\'') )* '\''
    ;




fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;

Спасибо за вашу помощь

1 Ответ

1 голос
/ 03 декабря 2010

Я считаю, что в ANLRWorks есть функция, помогающая удалить левую рекурсию из грамматики, хотя, насколько мне известно, она работает только с очень простыми грамматиками. Прошло много времени с тех пор, как я в последний раз высказывался с этим, так что вы должны исследовать себя в этом направлении.

Чтобы вручную удалить левую рекурсию, см .: http://www.antlr.org/wiki/display/ANTLR3/Left-Recursion+Removal (обязательно пройдите все 3 раздела)

EDIT

Я не уверен, что смогу вам помочь: вы, похоже, полностью упускаете из виду тот факт, что ANTLR не может справиться с леворекурсивными грамматиками. Ваши следующие правила парсера:

seq_statement 
  :  seq_statement ';' statement 
  |  seq_statement
  ;

simple_exp
  :  simple_exp OP term 
  |  term    
  ;

term    
  :  term OP factor factor 
  |  factor  
  ;

все настолько явно рекурсивны, что я не уверен, как объяснить это как-нибудь яснее. Я имею в виду, разве ты не видишь, что не так с таким правилом, как:

a
  : a b
  ;

? Что в основном совпадает с вашим правилом seq_statement.

У меня сложилось впечатление, что вы пытаетесь преобразовать существующую грамматику в грамматику ANTLR. Это тот случай? И вы действительно знаете, что на самом деле означает левая рекурсия?

РЕДАКТИРОВАТЬ II

Что-то вроде:

parse
  :  block EOF 
  ;

block
  :  statement (';' statement)* ';'? 
  ;

statement
  :  'read' expression  
  |  'write' expression 
  |  ifStatement
  |  repeatStatement
  |  assignment
  ;

ifStatement
  :  'if' expression 'then' block? ('else' block?)? 'end' 
  ;

repeatStatement
  :  'repeat' block? 'until' expression 
  ;

assignment
  :  Identifier ':=' expression 
  ;

expression
  :  equalityExp
  ;

equalityExp
  :  relationalExp (('=' | '!=') relationalExp)*
  ;

relationalExp
  :  additiveExp (('>=' | '<=' | '>' | '<') additiveExp)*
  ;

additiveExp
  :  multiplicativeExp (('+' | '-') multiplicativeExp)*
  ;

multiplicativeExp
  :  atom (('*' | '/' | '%') atom)*
  ;

atom
  :  Identifier
  |  Int
  |  '(' expression ')' 
  ;

Int
  :  '0'..'9'+
  ;

Identifier
  :  'a'..'z'+
  ;

Space
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

должен сделать трюк.

...