grammar ScriptLanguage; /*start : stmtList ; */ start : (script)* ; script : SCRIPT name=ID LPAREN signature=argList? RPAREN INDENT body=stmtList DEDENT ; argList : varDecl (COMMA varDecl)* ; varDecl : name=ID COLON type=ID ; stmtList : statement* ; statement : //scriptDecl assignment | casesStmt | scriptCommand | unconditionalBlock | conditionalBlock // | callStmt ; /*scriptDecl : SCRIPT name=ID '(' signature=argList? ')' INDENT body=stmtList DEDENT ; */ assignment : variable=ID COLON type=ID SEMICOLON | variable=ID (COLON type=ID)? ASSIGN expression SEMICOLON ; expression : expression MUL expression #exprMultiplication | expression DIV expression #exprDivision | expression op=(PLUS|MINUS) expression #exprLineOperators | expression op=(LE|GE|LEQ|GEQ) expression #exprComparison | expression op=(NEQ|EQ) expression #exprEquality | expression AND expression #exprAnd | expression OR expression #exprOr | expression IMP expression #exprIMP //| expression EQUIV expression already covered by EQ/NEQ | expression LBRACKET substExpressionList RBRACKET #exprSubst | ID LPAREN (expression (',' expression)*)? RPAREN #function | MINUS expression #exprNegate | NOT expression #exprNot | LPAREN expression RPAREN #exprParen | literals #exprLiterals | matchPattern #exprMatch ; substExpressionList : (scriptVar SUBST_TO expression (COMMA scriptVar SUBST_TO expression)* )? ; literals : ID #literalID | DIGITS #literalDigits | TERM_LITERAL #literalTerm | STRING_LITERAL #literalString | TRUE #literalTrue | FALSE #literalFalse ; /** * Example:
    match `f(x) ==>` using [x:term]

     
*/ matchPattern : MATCH ( derivable=DERIVABLE derivableExpression=expression | (pattern=expression (USING LBRACKET argList RBRACKET)?) ) ; scriptVar : QUESTION_MARK ID ; casesStmt : CASES INDENT casesList* (DEFAULT COLON? INDENT? defList=stmtList DEDENT?)? DEDENT ; casesList : (TRY | (CASE (expression | (CLOSES INDENT closesGuard=stmtList DEDENT) ) ) ) COLON INDENT? body=stmtList DEDENT? ; /*closesExpression : CLOSES INDENT closesGuard=stmtList DEDENT ;*/ unconditionalBlock : (kind+=(FOREACH|THEONLY|STRICT|RELAX|REPEAT))+ INDENT stmtList DEDENT ; conditionalBlock : kind=(IF|WHILE) LPAREN expression RPAREN INDENT stmtList DEDENT ; scriptCommand : cmd=ID parameters? SEMICOLON ; parameters: parameter+; parameter : ((pname=ID EQ)? expr=expression); /* callStmt : CALL scriptCommand SEMICOLON ; */ //LEXER Rules WS : [ \t\n\r]+ -> channel(HIDDEN) ; //comments, allowing nesting. SINGLE_LINE_COMMENT : '//' ~[\r\n]* -> channel(HIDDEN); MULTI_LINE_COMMENT : '/*' (MULTI_LINE_COMMENT|.)*? '*/' -> channel(HIDDEN); CASES: 'cases'; CASE: 'case'; TRY: 'try'; CLOSES: 'closes'; DERIVABLE : 'derivable'; DEFAULT: 'default'; ASSIGN : ':='; LBRACKET: '['; RBRACKET:']'; USING : 'using'; MATCH : 'match'; SCRIPT : 'script' ; TRUE : 'true' ; FALSE : 'false' ; CALL : 'call' ; REPEAT : 'repeat' ; /*INT : 'int' ; BOOL: 'bool' ; TERMTYPE : 'term' ;*/ FOREACH : 'foreach' ; THEONLY : 'theonly' ; STRICT : 'strict' ; RELAX : 'relax'; IF:'if'; WHILE:'while'; INDENT : '{' ; DEDENT : '}' ; SEMICOLON : ';' ; COLON : ':' ; SUBST_TO: '\\'; STRING_LITERAL : '\'' ('\'\'' | ~ ('\''))* '\'' ; TERM_LITERAL : '`' ~('`')* '`' ; PLUS : '+' ; MINUS : '-' ; MUL : '*' ; DIV : '/' ; EQ : '=' ; NEQ : '!=' ; GEQ : '>=' ; LEQ : '<=' ; GE : '>' ; LE : '<' ; AND : '&' ; OR: '|' ; IMP : '==>' ; EQUIV : '<=>' ; NOT: 'not'; COMMA: ','; LPAREN: '('; RPAREN: ')'; EXE_MARKER: '\u2316' -> channel(HIDDEN); QUESTION_MARK: '?'; DIGITS : DIGIT+ ; fragment DIGIT : [0-9] ; ID : ([a-zA-Z]|'#') ([_a-zA-Z0-9] | '.' | '\\'| '#')*;