file = { SOI ~ ((proxy | preprocessor | snippet | using | forward_declaration | element | macro_call | identifier) ~ ows)* ~ EOI }
ignore = @{ ignore_start ~ ignore_inner ~ ignore_end }
ignore_start = @{ "////" ~ ows ~ "[" ~ ows ~ "ignore" ~ ows ~ "]" }
ignore_end = @{ "////" ~ ows ~ "[" ~ ows ~ "/" ~ ows ~ "ignore" ~ ows ~ "]" }
ignore_inner = @{ (!ignore_end ~ ANY)* }
proxy = { doc_comment_lines? ~ ows ~ proxy_header ~ NEWLINE ~ (!proxy_end ~ ows ~ proxy_line)+ ~ ows ~ proxy_end }
proxy_line = _{ "////" ~ ows ~ proxy_line_content }
proxy_line_content = { (!NEWLINE ~ ANY)* ~ NEWLINE }
proxy_header = _{ "////" ~ ows ~ "[" ~ ows ~ "proxy" ~ ows ~ ":" ~ (ows ~ proxy_tags)? ~ ows ~ "]" }
proxy_end = { "////" ~ ows ~ "[" ~ ows ~ "/" ~ ows ~ "proxy" ~ ows ~ "]" }
proxy_tags = { identifier ~ (ows ~ "," ~ ows ~ identifier)* }
inject = { "////" ~ ows ~ "[" ~ ows ~ "inject" ~ ows ~ ":" ~ ows ~ inject_tags ~ ows ~ "]" }
inject_tags = _{ identifier ~ (ows ~ "," ~ ows ~ identifier)* }
snippet = { snippet_start ~ snippet_inner ~ snippet_end }
snippet_start = _{ "////" ~ ows ~ "[" ~ ows ~ "snippet" ~ ows ~ ":" ~ ows ~ identifier ~ ows ~ "]" ~ NEWLINE }
snippet_end = _{ NEWLINE ~ ows ~ "////" ~ ows ~ "[" ~ ows ~ "/" ~ ows ~ "snippet" ~ ows ~ "]" }
snippet_inner = @{ (!snippet_end ~ ANY)* }
preprocessor = _{ "#" ~ (("\\" ~ NEWLINE+ ~ ANY) | (!NEWLINE ~ ANY))* ~ NEWLINE }
forward_declaration = { (enum_signature | class_signature | struct_signature | function_signature) ~ ows ~ ";" }
using = { "using" ~ mws ~ identifier ~ ows ~ "=" ~ ows ~ (!";" ~ ANY)+ ~ ";" }
doc_comment_line = { !"////" ~ "///" ~ (!NEWLINE ~ ANY)* ~ NEWLINE }
doc_comment_lines = @{ (ows ~ doc_comment_line)+ }
element = { doc_comment_lines? ~ ows ~ (element_enum | element_class | element_struct | element_function | element_property | preprocessor) }
element_enum = { uenum? ~ ows ~ enum_signature ~ (ows ~ "{" ~ ows ~ enum_body ~ ows ~ "}")? ~ ows ~ ";" }
element_class = { uclass? ~ ows ~ class_signature ~ (ows ~ "{" ~ ows ~ struct_class_body ~ ows ~ "}")? ~ ows ~ ";" }
element_struct = { ustruct? ~ ows ~ struct_signature ~ (ows ~ "{" ~ ows ~ struct_class_body ~ ows ~ "}")? ~ ows ~ ";" }
element_function = { ufunction? ~ ows ~ (function_signature | constructor_signature) ~ ows ~ (";" | ("{" ~ ows ~ function_body ~ ows ~ "}")) }
element_property = { uproperty? ~ ows ~ property_signature ~ ows ~ ";" }
template_declaration = { "template" ~ ows ~ "<" ~ ows ~ (template_declaration_arguments ~ ows)? ~ ">" }
template_declaration_arguments = { template_declaration_argument ~ (ows ~ "," ~ ows ~ template_declaration_argument)* }
template_declaration_argument = { template_declaration_constant | value_type }
template_declaration_constant = { !dependentness ~ identifier ~ mws ~ identifier }
enum_signature = { "enum" ~ mws ~ "class" ~ mws ~ identifier ~ ows ~ ":" ~ ows ~ "uint8" }
enum_body = { identifier ~ (ows ~ "," ~ ows ~ identifier)* ~ (ows ~ ",")? }
class_signature = { (template_declaration ~ mws)? ~ "class" ~ mws ~ (api ~ mws)? ~ identifier ~ (ows ~ ":" ~ ows ~ inheritances)? }
struct_signature = { (template_declaration ~ mws)? ~ "struct" ~ mws ~ (api ~ mws)? ~ identifier ~ (ows ~ ":" ~ ows ~ inheritances)? }
struct_class_body = { struct_class_body_element ~ (ows ~ struct_class_body_element)* }
struct_class_body_element = _{ (visibility ~ ows ~ ":") | inject | using | friend | element | macro_call | identifier }
constructor_signature = { identifier ~ ows ~ "(" ~ ows ~ (function_arguments ~ ows)? ~ ")" ~ (ows ~ ":" ~ ows ~ constructor_initialization_list)? }
constructor_initialization_list = { constructor_initialization_field ~ (ows ~ "," ~ ows ~ constructor_initialization_field)* }
constructor_initialization_field = { identifier ~ ows ~ "(" ~ ows ~ expression? ~ ows ~ ")" }
function_signature = { (template_declaration ~ ows)? ~ ("friend" ~ mws)? ~ (staticness ~ mws)? ~ (virtualness ~ mws)? ~ value_type ~ (api ~ mws)? ~ function_name ~ ows ~ "(" ~ (ows ~ function_arguments)? ~ ows ~ ")" ~ (mws ~ constness)? ~ (mws ~ overrideness)? }
function_name = _{ operator | (identifier ~ (ows ~ function_template)?) }
function_arguments = { function_argument ~ (ows ~ "," ~ ows ~ function_argument)* ~ (ows ~ ",")? }
function_argument = { (doc_comment_lines ~ mws)? ~ value_type ~ (identifier ~ (ows ~ default_value)?)? }
function_template = { "<" ~ ows ~ template_arguments ~ ows ~ ">" }
function_body = { (snippet ~ ows)* }
operator = { "operator" ~ (ows ~ (!"(" ~ ANY)+)? }
property_signature = { (staticness ~ mws)? ~ value_type ~ identifier ~ (ows ~ property_array)? ~ (ows ~ default_value)? }
property_array = { "[" ~ ows ~ (index | macro_call | identifier)? ~ ows ~ "]" }
default_value = { "=" ~ ows ~ expression }
expression = { empty_bracket_expression | bracket_expression | parens_expression | reference_expression | dereference_expression | call | path | literal }
empty_bracket_expression = { "{" ~ ows ~ "}" }
bracket_expression = { "{" ~ ows ~ expression ~ (ows ~ "," ~ ows ~ expression)* ~ ows ~ "}" }
parens_expression = { "(" ~ ows ~ expression ~ (ows ~ "," ~ ows ~ expression)* ~ ows ~ ")" }
reference_expression = { "&" ~ ows ~ expression }
dereference_expression = { "*" ~ ows ~ expression }
friend = { (template_declaration ~ ows)? ~ "friend" ~ mws ~ (friend_class | friend_struct | friend_function) ~ ows ~ ";" }
friend_class = { "class" ~ mws ~ path }
friend_struct = { "struct" ~ mws ~ path }
friend_function = { function_signature }
macro_call = { path ~ ows ~ "(" ~ ows ~ call_arguments? ~ ows ~ ")" ~ ows ~ ";"? }
call = { path ~ ows ~ "(" ~ ows ~ call_arguments? ~ ows ~ ")" }
call_arguments = { expression ~ (ows ~ "," ~ ows ~ expression)* }
literal = { character | string | number }
api = @{ api_start ~ api_continue* ~ !api_continue }
api_start = { ASCII_ALPHA_UPPER | "_" }
api_continue = { ASCII_ALPHANUMERIC_UPPER | "_" }
uenum = { "UENUM" ~ ows ~ "(" ~ (ows ~ specifiers ~ ows)? ~ ")" }
uclass = { "UCLASS" ~ ows ~ "(" ~ (ows ~ specifiers ~ ows)? ~ ")" }
ustruct = { "USTRUCT" ~ ows ~ "(" ~ (ows ~ specifiers ~ ows)? ~ ")" }
ufunction = { "UFUNCTION" ~ ows ~ "(" ~ (ows ~ specifiers ~ ows)? ~ ")" }
uproperty = { "UPROPERTY" ~ ows ~ "(" ~ (ows ~ specifiers ~ ows)? ~ ")" }
inheritances = { inheritance ~ (ows ~ "," ~ ows ~ inheritance)* }
inheritance = { visibility ~ mws ~ value_type }
visibility = { "private" | "protected" | "public" }
specifiers = { specifier ~ ows ~ ("," ~ ows ~ specifier)* }
specifier = _{ specifier_meta | specifier_pair | specifier_single }
specifier_meta = { ^"meta" ~ ows ~ "=" ~ ows ~ specifier_list }
specifier_list = _{ "(" ~ ows ~ specifier_element ~ ows ~ ("," ~ ows ~ specifier_element)* ~ ")" }
specifier_element = _{ specifier_pair | specifier_single }
specifier_pair = { identifier ~ ows ~ "=" ~ ows ~ specifier_value }
specifier_value = _{ string | identifier }
specifier_single = { identifier }
value_type = { (constness ~ mws)? ~ (dependentness ~ (ows ~ unpackness)? ~ ows)? ~ (array_type | template_type | function_type | path) ~ ows ~ (pointer_type | reference_type)* ~ (ows ~ unpackness)? }
function_type = { path ~ "(" ~ (ows ~ function_type_arguments)* ~ ows ~ ")" }
function_type_arguments = { value_type ~ (ows ~ "," ~ ows ~ value_type)* ~ (ows ~ ",")? }
single_type = { identifier }
array_type = { identifier ~ ows ~ "[" ~ ows ~ ((index | macro_call | identifier) ~ ows)? ~ "]" }
template_type = { identifier ~ ows ~ "<" ~ ows ~ template_arguments ~ ows ~ ">" }
template_arguments = { value_type ~ (ows ~ "," ~ ows ~ value_type)* }
pointer_type = { "*" ~ ows ~ constness? }
reference_type = { "&" ~ ows ~ constness? }
path = { ("::" ~ ows)? ~ (path_element ~ ows) ~ ("::" ~ ows ~ path_element ~ ows)* }
path_element = { template_type | single_type }
unpackness = { "..." }
staticness = { "static" }
constness = { "constexpr" | "const" }
virtualness = { "virtual" }
dependentness = { "struct" | "class" | "typename" }
overrideness = { "override" }
index = { ASCII_DIGIT+ }
character = { "'" ~ ASCII_ALPHANUMERIC ~ "'" }
number = @{ ("+" | "-")? ~ number_major ~ number_minor? ~ identifier? }
number_major = { ASCII_DIGIT+ }
number_minor = { "." ~ ASCII_DIGIT* }
string = _{ "\"" ~ string_inner ~ "\"" }
string_inner = @{ string_char* }
string_char = { !"\"" ~ ANY }
ASCII_ALPHANUMERIC_UPPER = _{ ASCII_DIGIT | ASCII_ALPHA_UPPER }
COMMENT = _{ ignore | comment_block | comment_line }
comment_block = _{ "/*" ~ (!"*/" ~ ANY)* ~ "*/" }
comment_line = _{ !("////" | "///") ~ "//" ~ (!NEWLINE ~ ANY)* ~ NEWLINE+ }
identifier = @{ identifier_start ~ identifier_continue* ~ !identifier_continue }
identifier_start = { ASCII_ALPHA | "_" }
identifier_continue = { ASCII_ALPHANUMERIC | "_" }
ws = _{ " " | "\t" | "\r" | "\n" }
mws = _{ ws+ }
ows = _{ ws* }