0

I'm currently building a grammar for unit tests regarding a proprietary language my company uses.

This language resembles Regex in some way, for example F=bing* indicates the possible repetition of bing. A single * however represents one any block, and ** means any number of arbitrary blocks.

My only solution to this is using semantic predicates, checking if the preceding token was a space. If anyone has suggestions circumventing this problem in a different way, please share!

Otherwise, my grammar looks like this right now, but the predicates don't seem to work as expected.

grammar Pattern;

element:
    ID
    | macro;

macro:
    MACRONAME macroarg? REPEAT?;

macroarg: '['( (element | MACROFREE ) ';')* (element | MACROFREE) ']';


and_con : 
    element '&' element
    | and_con '&' element
    |'(' and_con ')';

head_con :
    'H[' block '=>' block ']';

block :
    element
    | and_con
    | or_con
    | head_con
    | '(' block ')';

blocksequence :
    (block ' '+)* block;

or_con :
     ((element | and_con) '|')+ (element | and_con)
    | or_con '|' (element | and_con)
    | '(' blocksequence (')|(' blocksequence)+ ')' REPEAT?;

patternlist :
    (blocksequence ' '* ',' ' '*)* blocksequence;

sentenceord :
    'S=(' patternlist ')';

sentenceunord :
    'S={' patternlist '}';

pattern :
    sentenceord
    | sentenceunord
    |  blocksequence;   

multisentence :
    MS pattern;

clause :
    'CLS' ' '+ pattern;

complexpattern :
    pattern
    | multisentence
    | clause
    | SECTIONS ' ' complexpattern;

dictentry:
    NUM ';' complexpattern
    | NUM ';' NAME ';' complexpattern
    | COMMENT;

dictionary:
    (dictentry ('\n'|'\r\n'))* (dictentry)? EOF;


ID : ( '^'? '!'? ('F'|'C'|'L'|'P'|'CA'|'N'|'PE'|'G'|'CD'|'T'|'M'|'D')'=' NAME REPEAT? '$'? )
    | SINGLESTAR REPEAT?;

fragment SINGLESTAR: {_input.LA(-1)==' '}? '*';
fragment REPEATSTAR: {_input.LA(-1)!=' '}? '*';

fragment NAME: CHAR+ | ',' | '.' | '*';

fragment CHAR: [a-zA-Z0-9_äöüßÄÖÜ\-];

REPEAT: (REPEATSTAR|'+'|'?'|FROMTIL);

fragment FROMTIL: '{'NUM'-'NUM'}';

MS : 'MS' [0-9];

SECTIONS: 'SEC' '=' ([0-9]+','?)+;

NUM: [0-9]+;

MACRONAME: '#'[a-zA-Z_][a-zA-Z_0-9]*;

MACROFREE: [a-zA-Z!]+;

COMMENT: '//' ~('\r'|'\n')*;
Max Uppenkamp
  • 974
  • 4
  • 16
  • By rummaging through the generated code, i found that the semantic predicate has to be written as `self._input` instead of just `_input`. It still won't work though. – Max Uppenkamp Dec 04 '15 at 12:18

1 Answers1

1

When targeting Python, the syntax of lookahead predicates needs to be like this:

SINGLESTAR: {self._input.LA(-1)==ord(' ')}? '*';

Note that it is necessary to add the "self." reference to the call and wrap the character with the ord() function which returns a unicode value for comparison. Antlr documentation for Python target is seriously lacking!

Max Uppenkamp
  • 974
  • 4
  • 16