grammar fspow; prog: stat+ ; // labelling alternatives creates extra visitor methods // the labels might clash with rule names, so I make them unique stat: assignment # statAssignment | fcList # statFcList | fcApplySelector # statFcApplySelector | message # statMessage ; assignment : ID '=' expression; // when alternatives are introduced, try using labels to distinguish expression : ID # exprID | selCreation # exprSelCreation | fcCreation # exprFcCreation ; // ------- // filecollection statements // ------- fcCreation: fcCreationName '(' rootSpecifier ')' ; fcCreationName: 'FileCollection' ; rootSpecifier: STRING ; // ------- // selector statements // ------- selCreation : selCreationName '(' testexpression ')' ; selCreationName: 'Selector' ; testexpression : testunit (testoperator testunit)* ; testoperator: 'intersect' #testoperatorIntersect ; testunit: 'name' '(' STRING ')' #testunitname | 'size' '(' STRING ')' #testunitsize | 'type' '(' STRING ')' #testunittype | 'date' '(' STRING ')' #testunitdate | '(' testexpression ')' #testunittestexpression | 'not' '(' testexpression ')' #testunitnottestexpression ; // ------- // apply statement // ------- fcApplySelector: ID '.' applyName '(' expression ')' ; applyName: 'apply' ; // ------- // print statement // ------- fcList: ID '.' printName ; // fc.print() printName: 'print()' ; // ------- // message statement // ------- message: 'message' STRING ; ID: [a-zA-Z][a-zA-Z0-9]* ; STRING: '"'.*?'"' {self.text = self.text[1:-1]} ; WS : [ \t\r\n]+ -> skip ; COMMENT : '//' ~[\r\n]* -> channel(HIDDEN) ;