grammar Jyro;

// -----------------------
// Parser rules
// -----------------------

program
    : statement* EOF
    ;

// ---- Statements ----
statement
    : variableDecl
    | ifStmt
    | switchStmt
    | whileStmt
    | forEachStmt
    | returnStmt
    | breakStmt
    | continueStmt
    | incDecStmt
    | exprStmt
    ;

variableDecl
    : VAR Identifier (COLON typeName)? (ASSIGN expression)?
    ;

typeName
    : NUMBER_T
    | STRING_T
    | BOOLEAN_T
    | OBJECT_T
    | ARRAY_T
    ;

exprStmt
    : expression
    ;

incDecStmt
    : assignmentTarget (INCR | DECR)
    ;

// ---- Control Flow ----
ifStmt
    : IF expression THEN statement*
      (ELSE IF expression THEN statement*)*
      (ELSE statement*)?
      END
    ;

switchStmt
    : SWITCH expression DO
        (CASE expression THEN statement*)*
        (DEFAULT THEN statement*)?
      END
    ;

whileStmt
    : WHILE expression DO statement* END
    ;

forEachStmt
    : FOREACH Identifier IN expression DO statement* END
    ;

returnStmt
    : RETURN
    ;

breakStmt
    : BREAK
    ;

continueStmt
    : CONTINUE
    ;

// ---- Expressions (C#-style precedence) ----
// Lowest to highest:
// assignment (right-assoc) < conditional ?: (right-assoc) < or < and < equality < relational < additive < multiplicative < unary < postfix/primary

expression
    : assignmentExpr
    ;

assignmentExpr
    : conditionalExpr                                     #AssignPass
    | assignmentTarget ASSIGN assignmentExpr              #AssignMake
    ;

// Assignment targets: identifiers or Data.* chains
assignmentTarget
    : Identifier (memberOrIndex)*
    | DATA (memberOrIndex)+
    ;

conditionalExpr
    : logicalOrExpr (QMARK conditionalExpr COLON conditionalExpr)?
    ;

logicalOrExpr
    : logicalAndExpr (OR logicalAndExpr)*
    ;

logicalAndExpr
    : equalityExpr (AND equalityExpr)*
    ;

equalityExpr
    : relationalExpr ((EQ | NEQ) relationalExpr)*
    ;

relationalExpr
    : additiveExpr ((LT | LE | GT | GE | IS) additiveExpr)*
    ;

additiveExpr
    : multiplicativeExpr ((ADD | SUB) multiplicativeExpr)*
    ;

multiplicativeExpr
    : unaryExpr ((MUL | DIV | MOD) unaryExpr)*
    ;

unaryExpr
    : (NOT | SUB) unaryExpr
    | postfixExpr
    ;

postfixExpr
    : primaryExpr (postfixSuffix)*
    ;

postfixSuffix
    : LPAREN argList? RPAREN
    | memberOrIndex
    ;

memberOrIndex
    : DOT Identifier
    | LBRACK expression RBRACK
    ;

// ---- Primaries & literals ----
primaryExpr
    : literal
    | Identifier
    | DATA (memberOrIndex)+
    | LPAREN expression RPAREN
    | objectLiteral
    | arrayLiteral
    ;

literal
    : numberLiteral
    | stringLiteral
    | TRUE
    | FALSE
    | NULL
    ;

numberLiteral
    : Number
    ;

stringLiteral
    : String
    ;

objectLiteral
    : LBRACE (objectEntry (COMMA objectEntry)*)? RBRACE
    ;

objectEntry
    : (String | LBRACK expression RBRACK) COLON expression
    ;

arrayLiteral
    : LBRACK (expression (COMMA expression)*)? RBRACK
    ;

argList
    : expression (COMMA expression)*
    ;

// -----------------------
// Lexer rules
// -----------------------

// Keywords / operators (case-sensitive)
VAR        : 'var';
IF         : 'if';
THEN       : 'then';
ELSE       : 'else';
END        : 'end';
SWITCH     : 'switch';
DO         : 'do';
CASE       : 'case';
DEFAULT    : 'default';
WHILE      : 'while';
FOREACH    : 'foreach';
IN         : 'in';
RETURN     : 'return';
BREAK      : 'break';
CONTINUE   : 'continue';

TRUE       : 'true';
FALSE      : 'false';
NULL       : 'null';

AND        : 'and';
OR         : 'or';
NOT        : 'not';
IS         : 'is';

// Types
NUMBER_T   : 'number';
STRING_T   : 'string';
BOOLEAN_T  : 'boolean';
OBJECT_T   : 'object';
ARRAY_T    : 'array';

// Reserved root
DATA       : 'Data';

// Punctuation / operators
INCR       : '++';
DECR       : '--';
EQ         : '==';
NEQ        : '!=';
LE         : '<=';
GE         : '>=';
LT         : '<';
GT         : '>';
ADD        : '+';
SUB        : '-';
MUL        : '*';
DIV        : '/';
MOD        : '%';

ASSIGN     : '=';
QMARK      : '?';
COLON      : ':';
COMMA      : ',';
DOT        : '.';
LPAREN     : '(';
RPAREN     : ')';
LBRACE     : '{';
RBRACE     : '}';
LBRACK     : '[';
RBRACK     : ']';

// Identifiers
Identifier : (Letter | '_') (Letter | Digit | '_')* ;

// Numbers: integers and decimals
Number     : Digit+ ('.' Digit+)? ;

// Strings: double-quoted with escapes
String
    : '"' ( EscapeSeq | ~["\\\r\n] )* '"'
    ;

fragment EscapeSeq
    : '\\' [btnfr"\\/]          // \b \t \n \f \r \" \\ \/
    | '\\' 'u' Hex Hex Hex Hex  // \uXXXX
    ;

fragment Letter : [A-Za-z] ;
fragment Digit  : [0-9] ;
fragment Hex    : [0-9A-Fa-f] ;

// Whitespace & comments
WS       : [ \t\r\n]+ -> skip ;
COMMENT  : '#' ~[\r\n]* -> skip ;

Back to top

Copyright © Mesch Systems. All rights reserved.