grammar LabelTest;


manyLabels
    : SYMBOL_FACT SYMBOL_LB num1=number num2=number SYMBOL_ADD number SYMBOL_ADD num4=number num5=number SYMBOL_FACT
    ;

withLabels
    : functionCall                              #branch_call
    | operatorNeg a=withLabels                  #branch_pref
    | withLabels operatorFact                   #branch_suff
    | SYMBOL_LB withLabels SYMBOL_RB            #branch_bracket
    | a=withLabels operatorAnd b=withLabels     #branch_1
    | b=withLabels operatorMul a=withLabels     #branch_2
    | x=withLabels operatorAdd y=withLabels     #branch_3
    | number                                    #branch_number
    | SYMBOL_ASK p=number q=number r=number     #branch_ask
    ;

withoutLabels
    : functionCall
    | operatorNeg a=withLabels
    | withLabels operatorFact
    | SYMBOL_LB withLabels SYMBOL_RB
    | a=withLabels operatorAnd b=withLabels
    | b=withLabels operatorMul a=withLabels
    | x=withLabels operatorAdd y=withLabels
    | number
    | SYMBOL_ASK p=number q=number r=number
    ;

withoutLabelsRecursive
    : functionCall
    | operatorNeg a=withoutLabelsRecursive
    | withoutLabelsRecursive operatorFact
    | SYMBOL_LB withoutLabelsRecursive SYMBOL_RB
    | a=withoutLabelsRecursive operatorAnd b=withoutLabelsRecursive
    | b=withoutLabelsRecursive operatorMul a=withoutLabelsRecursive
    | x=withoutLabelsRecursive operatorAdd y=withoutLabelsRecursive
    | number
    | SYMBOL_ASK p=number q=number r=number
    ;

functionCall
    : NAME SYMBOL_LB args=functionArguments SYMBOL_RB
    ;

functionArguments
    : functionArgument (SYMBOL_COM functionArgument)*
    ;

functionArgument
    : withLabels
    ;

withToken
    : SYMBOL_LB SYMBOL_LB value=NUMBER_INT SYMBOL_RB SYMBOL_RB
    ;

operatorAnd     : SYMBOL_AND;
operatorMul     : SYMBOL_MUL;
operatorAdd     : SYMBOL_ADD;
operatorNeg     : SYMBOL_NEG;
operatorFact    : SYMBOL_FACT;

number : NUMBER_INT;

NUMBER_INT : [0-9]+ ;

NAME : [a-z]+ ;

SYMBOL_LB : '(' ;
SYMBOL_RB : ')' ;
SYMBOL_COM : ',' ;

SYMBOL_FACT: '!' ;
SYMBOL_AND : '&' ;
SYMBOL_MUL : '*' ;
SYMBOL_ADD : '+' ;
SYMBOL_NEG : '-' ;

SYMBOL_ASK : '?' ;

WS :  [ \t\r\n]+ -> skip ;