LK SF
LK SF

Reputation: 1

ANTLR Grammar and generated code problems

I'm trying to create an expression parser using ANTLR The expression will go inside an if statement so its root is a condition.

I have the following grammar, which "compiles" to parser/lexer files with no problems, however the generated code itself has some errors, essentially two "empty" if statements i.e. if (())

Not sure what I'm doing wrong, any help will be greatly appreciated.

Thanks.

Grammar .g file below: grammar Expression;

options {
  language=CSharp3;
  output=AST;
}

tokens {
  ROOT;
  UNARY_MIN;
}

@parser::namespace { Antlr3 }
@lexer::namespace { Antlr3 }
public parse
  :  orcond EOF -> ^(ROOT orcond)
  ;

orcond
  :  andcond ('||' andcond)*
  ;

andcond
  :  condition ('&&' condition)*
  ;

condition
  :  exp (('<' | '>' | '==' | '!=' | '<=' | '>=')^ exp)?
  ;

exp
  :  addExp
  ;

addExp
  :  mulExp (('+' | '-')^ mulExp)*
  ;

mulExp
  :  unaryExp (('*' | '/')^ unaryExp)*
  ;

unaryExp
  :  '-' atom -> ^(UNARY_MIN atom)
  |  atom
  ;

atom
  :  Number
  |  '(' parenthesisvalid ')' -> parenthesisvalid
  ;

parenthesisvalid
  :  fullobjectref
  |  orcond
  ;

fullobjectref
  :  objectref ('.' objectref)?
  ;

objectref
  :  objectname ('()' | '(' params ')' | '[' params ']')?
  ;

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

params
  :  paramitem (',' paramitem)?
  ;

paramitem
  :  unaryExp
  ;

Number
  :  ('0'..'9')+ ('.' ('0'..'9')+)?
  ;

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

Upvotes: 0

Views: 207

Answers (2)

Andremoniy
Andremoniy

Reputation: 34900

Additionally it will be more neatly to use fragment blocks. In this case your code will be something like this:

Objectname  :  LETTER (LETTER  | DIGIT | '_')*;    
Number: DIGIT+ ('.' DIGIT+)?;
fragment DIGIT : '0'..'9' ;
fragment LETTER : ('a'..'z' | 'A'..'Z'); 

Upvotes: 0

Bart Kiers
Bart Kiers

Reputation: 170148

Don't use the range operator, .., inside parser rules.

Remove the parser rule objectname and create the lexer rule:

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

Upvotes: 2

Related Questions