// Overrides -------------------------------------------------------------------------------------------------------------------------- COMMENT = _{ ("--" ~ "[" ~ "[" ~ (ANY)* ~ "--" ~ "]" ~ "]") | ("--" ~ (!(NEWLINE) ~ ANY)* ~ (NEWLINE | EOI)) } WHITESPACE = _{ (" " | "\t" | NEWLINE | COMMENT) } // Numbers --------------------------------------------------------------------------------------------------------------------------- int = _{ ASCII_DIGIT+ } float = _{ int ~ "." ~ int } exponent = _{ (int | float) ~ ("e" | "E") ~ ("-")? ~ int } hex = _{ "0x" ~ ASCII_HEX_DIGIT+ } number = { int | float | exponent | hex } // Strings ---------------------------------------------------------------------------------------------------------------------------- normal_string = @{ "\"" ~ (escape_sequence | (!("\\" | "\"" | NEWLINE) ~ ANY))* ~ "\"" } char_string = @{ "'" ~ (escape_sequence | (!("'" | "\\" | NEWLINE) ~ ANY))* ~ "'" } long_string = @{ "[" ~ ("=")* ~ "[" ~ (escape_sequence | (!("\\" | "]") ~ ANY))* ~ "]" ~ ("=")* ~ "]" } escape_sequence = _{ "\\" ~ ("b" | "t" | "n" | "f" | "r" | "\"" | "'" | "\\") | unicode_escape | octal_escape } octal_escape = _{ "\\" ~ ('0'..'3') ~ ('0'..'7') ~ ('0'..'7') | "\\" ~ ('0'..'7') ~ ('0'..'7') | "\\" ~ ('0'..'7') } unicode_escape = _{ "\\" ~ "u" ~ ASCII_HEX_DIGIT ~ ASCII_HEX_DIGIT ~ ASCII_HEX_DIGIT ~ ASCII_HEX_DIGIT } template_string_expression = _{ "{" ~ expression ~ "}" } template_string = @{ "`" ~ (template_string_expression | (escape_sequence | (!("\\" | "`" | NEWLINE) ~ ANY)))* ~ "`" } string = { normal_string | char_string | long_string } // Literals --------------------------------------------------------------------------------------------------------------------------- boolean = { "false" | "true" } nil = { "nil" } name = @{ !("break" | "return" | "goto" | "repeat" | "until" | "function" | "local" | "do" | "while" | "end" | "if" | "elseif" | "else" | "end" | "then" | "true" | "false" | "nil" | "not") ~ ("..." | ((ASCII_ALPHA | "_" | "$") ~ (ASCII_ALPHANUMERIC | "_" | "$" | ".")*)) } function_expression = { "function" ~ "(" ~ (name ~ ("," ~ name)*)? ~ (",")? ~ ")" ~ block ~ "end" } simple_field_initializer = { expression } complex_field_initializer = { (name | ("[" ~ expression ~ "]")) ~ "=" ~ expression } field_initializer = _{ complex_field_initializer | simple_field_initializer } table_literal = { "{" ~ (field_initializer ~ (("," | ";") ~ field_initializer)*)? ~ ("," | ";")? ~ "}" } capture_expression = { "$" ~ "(" ~ expression ~ ")" } literal = _{ boolean | nil | number | template_string | string | table_literal | function_expression | capture_expression | name } // Operators --------------------------------------------------------------------------------------------------------------------------- // Prefix negative = { "-" } length = { "#" } not = { "not" } bitwise_not = { "~" } prefix = _{ negative | length | not | bitwise_not } // Infix add = { "+" } subtract = { "-" } multiply = { "*" } divide = { "/" } modulus = { "%" } power = { "^" } concatenate = { ".." } bitwise_or = { "|" } bitwise_and = { "&" } bitwise_xor = { "~" } bitwise_left_shift = { "<<" } bitwise_right_shift = { ">>" } pipe = { "|>" } less_than = { "<" } less_than_or_equal = { "<=" } greater_than = { ">" } greater_than_or_equal = { ">=" } equal = { "==" } not_equal = { "~=" } and = { "and" } or = { "or" } infix = _{ add | subtract | multiply | divide | modulus | power | concatenate | pipe | less_than | less_than_or_equal | greater_than | greater_than_or_equal | equal | not_equal | and | or | bitwise_or | bitwise_and | bitwise_xor | bitwise_left_shift | bitwise_right_shift } // Postfix regular_function_call = { "(" ~ (expression ~ ("," ~ expression)* ~ (",")?)? ~ ")" } no_parentheses_function_call = { template_string | string | table_literal } function_call = _{ regular_function_call | no_parentheses_function_call } index = { "[" ~ expression ~ "]" } member_function_call = { ":" ~ name ~ regular_function_call } postfix = _{ index | function_call | member_function_call } // Expressions primary = _{ literal | ("(" ~ expression ~ ")") | name } expression = { prefix* ~ primary ~ postfix* ~ (infix ~ prefix* ~ primary ~ postfix*)* } // Statements -------------------------------------------------------------------------------------------------------------------------- label_statement = { "::" ~ name ~ "::" } goto_statement = { "goto" ~ name } expression_list = { expression ~ ("," ~ expression)* } equals = { "=" } global_variable_assignment = { expression ~ ("," ~ expression)* ~ equals ~ expression } local_variable_assignment = { "local" ~ name ~ ("," ~ name)* ~ (equals ~ expression_list)? } colon_name = { ":" ~ name } function_name = { name ~ ("." ~ name)* ~ colon_name? } global_function_assignment = { "function" ~ function_name ~ "(" ~ (name ~ ("," ~ name)*)? ~ ")" ~ block ~ "end" } local_function_assignment = { "local" ~ "function" ~ function_name ~ "(" ~ (name ~ ("," ~ name)*)? ~ ")" ~ block ~ "end" } while_loop = { "while" ~ expression ~ "do" ~ block ~ "end" } repeat_loop = { "repeat" ~ block ~ "until" ~ expression } name_list = { name ~ ("," ~ name)* } for_in_loop = { "for" ~ name_list ~ "in" ~ expression ~ "do" ~ block ~ "end" } for_range_loop = { "for" ~ name ~ "=" ~ expression ~ "," ~ expression ~ ("," ~ expression)? ~ "do" ~ block ~ "end" } do_statement = { "do" ~ block ~ "end" } else_statement = { "else" ~ block } elseif_statement = { "elseif" ~ expression ~ "then" ~ block } if_statement = { "if" ~ expression ~ "then" ~ block ~ (elseif_statement)* ~ (else_statement)? ~ "end" } return_statement = { "return" ~ (expression ~ ("," ~ expression)*)? } break_statement = { "break" } last_statement = _{ return_statement | break_statement } statement = _{ for_range_loop | for_in_loop | goto_statement | repeat_loop | if_statement | do_statement | while_loop | local_function_assignment | local_variable_assignment | label_statement | global_function_assignment | global_variable_assignment | expression } block = { (statement ~ (";")?)* ~ (last_statement ~ (";")?)? } // Program ---------------------------------------------------------------------------------------------------------------------------- program = { SOI ~ block ~ EOI }