Atleast ONE Space around Parenthesis in ANTLR4

Viewed 34

I want spaces around Parenthesis in IF condition. ATleast one space is required. But when i use Space in grammar it throws me error, when i use Else block with it. Please help me, how to accomplish it, i have seen many examples but none is related to it. i only need spaces around Parenthesis of If condition.

prog: stat_block EOF;

stat_block: OBRACE block CBRACE;

block: (stat (stat)*)?;

stat: expr ';'
 | IF  condition_block (ELSE  stat_block)?
 ;

expr
 : expr SPACE ('*' | '/') SPACE expr
 | ID
 | INT
 | STRING
 ;

 exprList: expr (',' expr)*;

 condition_block: SPACE OPAR SPACE expr SPACE CPAR SPACE stat_block;
 IF:      'IF';
 ELSE:    'ELSE';
 OPAR:    '(';
 CPAR:    ')';
 OBRACE:  '{';
 CBRACE:  '}';
 SPACE: SINGLE_SPACE+;
 SINGLE_SPACE: ' ';
 ID:      [a-zA-Z]+;
 INT:     [0-9]+;
 NEWLINE: '\r'? '\n'  -> skip;
 WS:      [ \t]+     -> skip;

Expected input to parse

IF ( 3 ) { } ELSE { }

Current Input enter image description here

2 Answers

At least one space is required.

Then you either:

  • cannot -> skip the WS rule, which will cause all spaces and tabs to become tokens and needing your parser to handle them correctly (which is likely going to become a complete mess in your parser rules!), or
  • you leave WS -> skip as-is, but include a space in your PAREN rules: OPAR : ' ( '; CPAR: ' ) '; (or with tabs as well if that is possible)

There's a reason that almost all languages ignore whitespace. If you don't ignore it, then you have to deal with its possible existence in the token stream anywhere it might, or might not, be in ALL of your parser rules.

You can try to include the spaces in the Lexer rules for tokens that you want wrapped in spaces, but may still find surprises.

Suggestion: Instead if -> skip; for your WS rule, use -> channel(HIDDEN); This keeps the tokens in the token stream so you can look for them in your code, but "hides" the whitespace tokens from the parser rules. This also allows ANTLR to get a proper interpretation of your input and build a parse tree that represents it correctly.

If you REALLY want to insist on the spaces before/after, you can write code in a listener that looks before/after the tokens in the input stream to see if you have whitespace, and generate your own error (that can be very specific about your requirement).

Related