%header% GRAMMARTYPE = "LL" DESCRIPTION = "A grammar for SunScript." AUTHOR = "arookas" VERSION = "1.1" DATE = "2015/11/29" LICENSE = "No license." COPYRIGHT = "Copyright (c) 2015 arookas" %tokens% // whitespace WHITESPACE = <<[ \t\r\n]+>> %ignore% // comments SINGLE_LINE_COMMENT = <> %ignore% MULTI_LINE_COMMENT = <> %ignore% // keywords IMPORT = "import" BUILTIN = "builtin" FUNCTION = "function" VAR = "var" CONST = "const" IF = "if" ELSE = "else" DO = "do" WHILE = "while" FOR = "for" RETURN = "return" BREAK = "break" CONTINUE = "continue" YIELD = "yield" EXIT = "exit" DUMP = "dump" LOCK = "lock" UNLOCK = "unlock" INT = "int" FLOAT = "float" TYPEOF = "typeof" PRINT = "print" TRUE = "true" FALSE = "false" // punctuation L_BRACE = "{" R_BRACE = "}" L_PAREN = "(" R_PAREN = ")" L_BRACKET = "[" R_BRACKET = "]" COLON = ":" SEMICOLON = ";" COMMA = "," DOT = "." ELLIPSIS = "..." QMARK = "?" // operators ADD = "+" SUB = "-" // doubles as the negation operator MUL = "*" DIV = "/" MOD = "%" BIT_AND = "&" BIT_OR = "|" BIT_LSH = "<<" BIT_RSH = ">>" LOG_NOT = "!" LOG_AND = "&&" LOG_OR = "||" EQ = "==" NEQ = "!=" LT = "<" LTEQ = "<=" GT = ">" GTEQ = ">=" ASSIGN = "=" ASSIGN_ADD = "+=" ASSIGN_SUB = "-=" ASSIGN_MUL = "*=" ASSIGN_DIV = "/=" ASSIGN_MOD = "%=" ASSIGN_BIT_AND = "&=" ASSIGN_BIT_OR = "|=" ASSIGN_BIT_LSH = "<<=" ASSIGN_BIT_RSH = ">>=" // literals IDENTIFIER = <<[_A-Za-z][_A-Za-z0-9]*>> DEC_NUMBER = <<-?[0-9]+\.[0-9]+>> HEX_NUMBER = <<-?0x[0-9A-Fa-f]+>> INT_NUMBER = <<-?[0-9]+>> STRING = <<"(\\.|[^"])*">> %productions% script = root_statement+; // statements root_statement = import_statement SEMICOLON | function_definition | builtin_declaration SEMICOLON | statement; statement = compound_statement SEMICOLON | if_statement | while_statement | do_statement SEMICOLON | for_statement | return_statement SEMICOLON | break_statement SEMICOLON | continue_statement SEMICOLON | yield_statement SEMICOLON | exit_statement SEMICOLON | dump_statement SEMICOLON | lock_statement SEMICOLON | unlock_statement SEMICOLON | statement_block; compound_statement = compound_statement_item {COMMA compound_statement_item}; compound_statement_item = const_definition | variable_definition | variable_declaration | variable_assignment | print_statement | function_call; statement_block = L_BRACE {statement} R_BRACE; import_statement = IMPORT STRING; yield_statement = YIELD; exit_statement = EXIT; dump_statement = DUMP; lock_statement = LOCK; unlock_statement = UNLOCK; print_statement = PRINT argument_list; name_label = IDENTIFIER COLON; // operators assignment_operator = ASSIGN | ASSIGN_ADD | ASSIGN_SUB | ASSIGN_MUL | ASSIGN_DIV | ASSIGN_MOD | ASSIGN_BIT_AND | ASSIGN_BIT_OR | ASSIGN_BIT_LSH | ASSIGN_BIT_RSH; ternary_operator = expression QMARK expression COLON expression; binary_operator = ADD | SUB | MUL | DIV | MOD | // arithmetic BIT_AND | BIT_OR | BIT_LSH | BIT_RSH | // bitwise EQ | NEQ | LT | LTEQ | GT | GTEQ | // comparison LOG_AND | LOG_OR; // logical unary_operator = LOG_NOT | SUB; // expressions expression = operand {binary_operator operand}; operand = [unary_operator_list] term; term = int_cast | float_cast | typeof_cast | function_call | variable_reference | STRING | DEC_NUMBER | HEX_NUMBER | INT_NUMBER | TRUE | FALSE | L_PAREN expression R_PAREN | L_BRACKET ternary_operator R_BRACKET; // HACK: the brackets remove ambiguity unary_operator_list = unary_operator+; int_cast = INT L_PAREN expression R_PAREN; float_cast = FLOAT L_PAREN expression R_PAREN; typeof_cast = TYPEOF L_PAREN expression R_PAREN; // constants const_definition = CONST IDENTIFIER ASSIGN expression; // variables variable_reference = IDENTIFIER; // used in expressions variable_declaration = VAR IDENTIFIER; variable_definition = VAR IDENTIFIER assignment_operator expression; variable_assignment = IDENTIFIER assignment_operator expression; // functions function_definition = FUNCTION IDENTIFIER parameter_list statement_block; function_call = IDENTIFIER argument_list; parameter_list = L_PAREN [parameter {COMMA parameter}] R_PAREN; // e.g. (a, b, ...) parameter = IDENTIFIER | ELLIPSIS; argument_list = L_PAREN [argument {COMMA argument}] R_PAREN; argument = expression; // builtins builtin_declaration = BUILTIN IDENTIFIER parameter_list; // flow control if_statement = [name_label] IF expression statement [ELSE statement]; while_statement = [name_label] WHILE expression statement; do_statement = [name_label] DO statement WHILE expression; for_statement = [name_label] FOR L_PAREN [for_declaration] SEMICOLON [for_condition] SEMICOLON [for_iteration] R_PAREN statement; for_declaration = compound_statement; for_condition = expression; for_iteration = compound_statement; return_statement = RETURN [expression]; break_statement = BREAK [IDENTIFIER]; continue_statement = CONTINUE [IDENTIFIER];