Grammar (generated)
This is the Pest grammar shipped in CL++ 0.7.0 (src/parser/grammar.pest). Productions: @ident, continue, do/while, try/catch, ?., ??, ranges, enum, using, [[attr]], signal, template strings, ~>.
WHITESPACE = _{ " " | "\t" | "\r" | "\n" }COMMENT = _{ "//" ~ (!NEWLINE ~ ANY)* | "/*" ~ (!"*/" ~ ANY)* ~ "*/" }NEWLINE = _{ "\n" | "\r\n" }ident_char = _{ ASCII_ALPHANUMERIC | "_" }
KW_CONSTEXPR = @{ "constexpr" ~ !ident_char }KW_NAMESPACE = @{ "namespace" ~ !ident_char }KW_OBSERVABLE = @{ "observable" ~ !ident_char }KW_PROTECTED = @{ "protected" ~ !ident_char }KW_PARALLEL = @{ "parallel" ~ !ident_char }KW_NULLPTR = @{ "nullptr" ~ !ident_char }KW_PRIVATE = @{ "private" ~ !ident_char }KW_PUBLIC = @{ "public" ~ !ident_char }KW_TEMPLATE = @{ "template" ~ !ident_char }KW_TYPENAME = @{ "typename" ~ !ident_char }KW_TYPEDEF = @{ "typedef" ~ !ident_char }KW_DEFAULT = @{ "default" ~ !ident_char }KW_STATIC = @{ "static" ~ !ident_char }KW_STRUCT = @{ "struct" ~ !ident_char }KW_SWITCH = @{ "switch" ~ !ident_char }KW_RETURN = @{ "return" ~ !ident_char }KW_SIGNAL = @{ "signal" ~ !ident_char }KW_BREAK = @{ "break" ~ !ident_char }KW_CONTINUE = @{ "continue" ~ !ident_char }KW_CLASS = @{ "class" ~ !ident_char }KW_CONST = @{ "const" ~ !ident_char }KW_FALSE = @{ "false" ~ !ident_char }KW_FLOAT = @{ "float" ~ !ident_char }KW_WHILE = @{ "while" ~ !ident_char }KW_ASYNC = @{ "async" ~ !ident_char }KW_AWAIT = @{ "await" ~ !ident_char }KW_GUARD = @{ "guard" ~ !ident_char }KW_MATCH = @{ "match" ~ !ident_char }KW_SPAWN = @{ "spawn" ~ !ident_char }KW_DELAY = @{ "delay" ~ !ident_char }KW_DEFER = @{ "defer" ~ !ident_char }KW_CATCH = @{ "catch" ~ !ident_char }KW_OVERRIDE = @{ "override" ~ !ident_char }KW_TRY = @{ "try" ~ !ident_char }KW_DO = @{ "do" ~ !ident_char }KW_AUTO = @{ "auto" ~ !ident_char }KW_BOOL = @{ "bool" ~ !ident_char }KW_CASE = @{ "case" ~ !ident_char }KW_ELSE = @{ "else" ~ !ident_char }KW_ENUM = @{ "enum" ~ !ident_char }KW_TRUE = @{ "true" ~ !ident_char }KW_VOID = @{ "void" ~ !ident_char }KW_FOR = @{ "for" ~ !ident_char }KW_INT = @{ "int" ~ !ident_char }KW_IN = @{ "in" ~ !ident_char }KW_NEW = @{ "new" ~ !ident_char }KW_USING = @{ "using" ~ !ident_char }KW_EXTERN = @{ "extern" ~ !ident_char }KW_INLINE = @{ "inline" ~ !ident_char }KW_DOUBLE = @{ "double" ~ !ident_char }KW_STRING = @{ "string" ~ !ident_char }KW_FUNC = @{ "func" ~ !ident_char }KW_NULL = @{ "null" ~ !ident_char }KW_IF = @{ "if" ~ !ident_char }KW_BY = @{ "by" ~ !ident_char }KW_TUPLE = @{ "tuple" ~ !ident_char }KW_VARIANT = @{ "variant" ~ !ident_char }
kw = _{ KW_CONSTEXPR | KW_NAMESPACE | KW_OBSERVABLE | KW_PROTECTED | KW_PARALLEL | KW_NULLPTR | KW_PRIVATE | KW_PUBLIC | KW_TEMPLATE | KW_TYPENAME | KW_TYPEDEF | KW_DEFAULT | KW_STATIC | KW_STRUCT | KW_SWITCH | KW_RETURN | KW_SIGNAL | KW_BREAK | KW_CONTINUE | KW_CLASS | KW_CONST | KW_FALSE | KW_FLOAT | KW_WHILE | KW_ASYNC | KW_AWAIT | KW_GUARD | KW_MATCH | KW_SPAWN | KW_DELAY | KW_DEFER | KW_CATCH | KW_OVERRIDE | KW_TRY | KW_DO | KW_AUTO | KW_BOOL | KW_CASE | KW_ELSE | KW_ENUM | KW_TRUE | KW_VOID | KW_FOR | KW_INT | KW_NEW | KW_USING | KW_EXTERN | KW_INLINE | KW_DOUBLE | KW_STRING | KW_FUNC | KW_NULL | KW_IF | KW_IN | KW_BY | KW_TUPLE | KW_VARIANT}
ident = @{ !kw ~ (ASCII_ALPHA | "_") ~ ident_char* }number = @{ ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT+)? }string = @{ "\"" ~ ("\\" ~ ANY | !"\"" ~ ANY)* ~ "\"" }char_string = @{ "'" ~ ("\\" ~ ANY | !"'" ~ ANY)* ~ "'" }raw_string = @{ "R\"(" ~ (!")\"" ~ ANY)* ~ ")\"" }template_string = { "`" ~ template_chunk* ~ "`" }template_chunk = { template_interp | template_escaped | template_text }template_interp = { "{" ~ expr ~ "}" }template_escaped = @{ "\\`" | "\\{" | "\\}" | "\\\\" }template_text = @{ (!("`" | "{" | "\\") ~ ANY)+ }string_join = { template_string ~ ("," ~ expr)+ }
file = { SOI ~ item* ~ EOI }
item = { struct_decl | enum_decl | function_item | field_destructure | destructure | var_decl | using_namespace | using_stmt | namespace_item | skip_decl | hash_line}
hash_line = { "#" ~ (!NEWLINE ~ ANY)* }
using_namespace = { KW_USING ~ KW_NAMESPACE ~ ident? ~ ";" }using_stmt = { KW_USING ~ ident ~ "=" ~ type_spec ~ ";" }namespace_item = { KW_NAMESPACE ~ ident? ~ "{" ~ item* ~ "}" }skip_decl = { (KW_TYPEDEF | KW_EXTERN) ~ skip_balanced }
skip_balanced = { (!("{" | ";") ~ ANY)* ~ ( "{" ~ skip_nested ~ "}" ~ ";"? | ";" )}skip_nested = _{ (!("{" | "}") ~ ANY)* ~ ("{" ~ skip_nested ~ "}" ~ (!("{" | "}") ~ ANY)*)* }
specifiers = { (KW_STATIC | KW_CONSTEXPR | KW_INLINE | KW_CONST | KW_OBSERVABLE | KW_ASYNC | KW_OVERRIDE)+ }
attr = { "[[" ~ ident ~ ("(" ~ string ~ ")")? ~ "]]" }
template_head = { KW_TEMPLATE ~ "<" ~ template_param ~ ("," ~ template_param)* ~ ">" }template_param = { (KW_TYPENAME | KW_CLASS) ~ ident ~ ("=" ~ type_spec)? }
type_name = { KW_VOID | KW_DOUBLE | KW_FLOAT | KW_AUTO | KW_BOOL | KW_INT | KW_STRING | KW_FUNC | KW_SIGNAL | KW_TUPLE | KW_VARIANT | ident ~ ("::" ~ ident)*}type_generic = { "<" ~ type_spec ~ ("," ~ type_spec)* ~ ">" }function_type = { "function" ~ "<" ~ type_spec ~ "(" ~ type_spec? ~ ("," ~ type_spec)* ~ ")" ~ ">" }type_atom = { specifiers? ~ (function_type | type_name ~ type_generic?) ~ "*"* }type_spec = { type_atom ~ (("|" | "&") ~ type_atom)* }
param = { type_spec ~ ident | ident ~ ":" ~ type_spec }param_list = { param ~ ("," ~ param)* }
function_item = { template_head? ~ attr* ~ specifiers? ~ type_spec ~ ident ~ ("::" ~ ident)? ~ "(" ~ param_list? ~ ")" ~ (block | ";")}
var_decl = { specifiers? ~ (type_spec ~ ident | ident ~ ":" ~ type_spec) ~ ("=" ~ expr)? ~ ";" }destructure = { KW_AUTO ~ "[" ~ ident ~ ("," ~ ident)* ~ "]" ~ "=" ~ expr ~ ";" }field_destructure = { KW_AUTO ~ "{" ~ ident ~ ("," ~ ident)* ~ "}" ~ "=" ~ expr ~ ";" }
enum_decl = { KW_ENUM ~ KW_CLASS? ~ ident ~ (":" ~ type_spec)? ~ "{" ~ enum_variant? ~ ("," ~ enum_variant)* ~ ","? ~ "}" ~ ";"}enum_variant = { ident ~ ("=" ~ number)? }
struct_decl = { template_head? ~ (KW_STRUCT | KW_CLASS) ~ ident ~ type_generic? ~ (":" ~ ident)? ~ "{" ~ struct_member* ~ "}" ~ ";"}
struct_member = { access_label | nested_struct | ctor_proto | method_proto | field_decl}
access_label = { (KW_PUBLIC | KW_PRIVATE | KW_PROTECTED) ~ ":" }nested_struct = { struct_decl ~ ident? ~ ("=" ~ expr)? ~ ";"? }ctor_proto = { ident ~ "(" ~ param_list? ~ ")" ~ ";" }method_proto = { specifiers? ~ type_spec ~ ident ~ "(" ~ param_list? ~ ")" ~ ";" }field_decl = { specifiers? ~ (type_spec ~ ident | ident ~ ":" ~ type_spec) ~ ("=" ~ expr)? ~ ";" }
block = { "{" ~ stmt* ~ "}" }
stmt = { if_stmt | guard_stmt | match_stmt | switch_stmt | try_stmt | for_stmt | do_while_stmt | while_stmt | spawn_stmt | parallel_stmt | delay_stmt | defer_stmt | return_stmt | break_stmt | continue_stmt | field_destructure | destructure | var_decl | expr_stmt | empty_stmt | block}
empty_stmt = { ";" }
if_stmt = { KW_IF ~ "(" ~ expr ~ ")" ~ stmt ~ (KW_ELSE ~ stmt)? }guard_stmt = { KW_GUARD ~ "(" ~ expr ~ ")" ~ KW_ELSE ~ stmt }while_stmt = { KW_WHILE ~ "(" ~ expr ~ ")" ~ stmt }do_while_stmt = { KW_DO ~ stmt ~ KW_WHILE ~ "(" ~ expr ~ ")" ~ ";" }for_stmt = { c_for_stmt | range_for_stmt }c_for_stmt = { KW_FOR ~ "(" ~ c_for_init? ~ ";" ~ expr? ~ ";" ~ expr? ~ ")" ~ stmt }c_for_init = { specifiers? ~ (type_spec ~ ident | ident ~ ":" ~ type_spec) ~ ("=" ~ expr)? }range_for_stmt = { KW_FOR ~ "(" ~ type_spec ~ ident ~ (KW_IN | ":") ~ range_src ~ ")" ~ stmt }range_src = { expr ~ (range_dots ~ expr ~ (KW_BY ~ expr)?)? }range_dots = { "..<" | ".." }return_stmt = { KW_RETURN ~ (expr ~ ("," ~ expr)*)? ~ ";" }break_stmt = { KW_BREAK ~ ";" }continue_stmt = { KW_CONTINUE ~ ";" }expr_stmt = { expr ~ ";" }spawn_stmt = { KW_SPAWN ~ block ~ ";"? }parallel_stmt = { KW_PARALLEL ~ block ~ ";"? }delay_stmt = { KW_DELAY ~ "(" ~ expr ~ ")" ~ block ~ ";"? }defer_stmt = { KW_DEFER ~ block ~ ";"? }try_stmt = { KW_TRY ~ block ~ KW_CATCH ~ "(" ~ (KW_AUTO | type_spec) ~ ident ~ ")" ~ block }
switch_stmt = { KW_SWITCH ~ "(" ~ expr ~ ")" ~ "{" ~ switch_clause* ~ "}" }switch_clause = { (case_clause | default_clause) ~ stmt* }case_clause = { KW_CASE ~ expr ~ ":" }default_clause = { KW_DEFAULT ~ ":" }
match_stmt = { KW_MATCH ~ "(" ~ expr ~ ")" ~ "{" ~ match_arm* ~ "}" ~ ";"? }match_arm = { match_pat ~ "=>" ~ match_body ~ ","? }match_pat = { "_" | type_spec ~ ident | ident }match_body = { block | expr }
expr = { assign }
assign_op = { "+=" | "-=" | "*=" | "/=" | "//=" | "^=" | "%=" | ".:=" | "=" }assign = { ternary ~ (assign_op ~ assign)? }ternary = { coalesce ~ ("?" ~ ternary ~ ":" ~ ternary)? }coalesce = { shift ~ ("??" ~ shift)* }shift = { or_expr ~ ("<<" ~ or_expr)* }or_expr = { and_expr ~ ("||" ~ and_expr)* }and_expr = { cmp ~ ("&&" ~ cmp)* }cmp = { concat ~ (cmp_op ~ concat)* }cmp_op = { "==" | "!=" | "<=" | ">=" | "<" | ">" }concat = { add ~ (".:" ~ add)* }add = { mul ~ (add_op ~ mul)* }add_op = { "+" | "-" }mul = { unary ~ (mul_op ~ unary)* }mul_op = { "*" | "/" | "%" }pow_op = { "**" }unary = { KW_AWAIT ~ unary | unary_op ~ unary | pow }pow = { primary ~ (pow_op ~ unary)? }unary_op = { "!" | "-" }
primary = { atom ~ postfix* }
atom = { lambda | new_expr | get_service | named_cast | boolean | null_lit | number | raw_string | string_join | template_string | char_string | string | init_list | at_sigil | ident | "(" ~ expr ~ ")"}
at_sigil = { "@" ~ ident }
boolean = { KW_TRUE | KW_FALSE }null_lit = { KW_NULL | KW_NULLPTR }
postfix = { qmark_dot_suf | cleanup_suf | scope_suf | colon_suf | dot_suf | index_suf | inc_suf | call_args | init_suf }
qmark_dot_suf = { "?." ~ ident ~ call_args? }cleanup_suf = { "~>" ~ ident ~ call_args? }scope_suf = { "::" ~ ident ~ call_args? }colon_suf = { ":" ~ !":" ~ ident ~ call_args? }dot_suf = { "." ~ !":" ~ ident ~ call_args? }index_suf = { "[" ~ expr ~ "]" }inc_suf = { "++" | "--" }call_args = { "(" ~ args? ~ ")" }init_suf = { init_list }
args = { expr ~ ("," ~ expr)* }
init_list = { "{" ~ init_body? ~ "}" }init_body = { designated_fields | dict_pairs | expr_list }designated_fields = { designated_field ~ ("," ~ designated_field)* ~ ","? }designated_field = { "." ~ ident ~ "=" ~ expr }dict_pairs = { dict_pair ~ ("," ~ dict_pair)* ~ ","? }dict_pair = { "{" ~ expr ~ "," ~ expr ~ "}" }expr_list = { expr ~ ("," ~ expr)* ~ ","? }
new_expr = { KW_NEW ~ ident ~ call_args? }get_service = { "GetService" ~ "<" ~ ident ~ ">" ~ "(" ~ ")" }named_cast_kw = { "static_cast" | "const_cast" | "reinterpret_cast" | "dynamic_cast" }named_cast = { named_cast_kw ~ "<" ~ type_spec ~ ">" ~ "(" ~ expr ~ ")" }
lambda = { KW_FUNC ~ "(" ~ param_list? ~ ")" ~ block }