keyword = { "alignas" | "continue" | "friend" | "register" | "true" | "alignof" | "decltype" | "goto" | "reinterpret_cast" | "try" | "asm" | "default" | "if" | "return" | "typedef" | "auto" | "delete" | "inline" | "short" | "typeid" | "bool" | "do" | "int" | "signed" | "typename" | "break" | "double" | "long" | "sizeof" | "union" | "case" | "dynamic_cast" | "mutable" | "static" | "unsigned" | "catch" | "else" | "namespace" | "static_assert" | "using" | "char" | "enum" | "new" | "static_cast" | "virtual" | "char16_t" | "explicit" | "noexcept" | "struct" | "void" | "char32_t" | "export" | "nullptr" | "switch" | "volatile" | "class" | "extern" | "operator" | "template" | "wchar_t" | "const" | "false" | "private" | "this" | "while" | "constexpr" | "float" | "protected" | "thread_local" | "const_cast" | "for" | "public" | "throw" } punctuator = { preprocessing_op_or_punc } hex_quad = @{ hexadecimal_digit ~ hexadecimal_digit ~ hexadecimal_digit ~ hexadecimal_digit } universal_character_name = @{ ("\\u" ~ hex_quad) | ("\\U" ~ hex_quad ~ hex_quad) } preprocessing_token = @{ header_name | identifier | pp_number | character_literal | user_defined_character_literal | string_literal | user_defined_string_literal | preprocessing_op_or_punc | (!WHITE_SPACE ~ ANY) } token = @{ identifier | keyword | literal | operator | punctuator } header_name = @{ ("<" ~ h_char_sequence ~ ">") | ("\"" ~ q_char_sequence ~ "\"") } h_char_sequence = @{ h_char+ } h_char = @{ !(NEWLINE | ">") ~ ANY } q_char_sequence = @{ q_char+ } q_char = @{ !(NEWLINE | "\"") ~ ANY } pp_number = @{ "."? ~ digit ~ ( digit | identifier_nondigit | ("'" ~ digit) | ("'" ~ nondigit) | ("e" ~ sign) | ("E" ~ sign) | "." )* } identifier = @{ identifier_nondigit ~ (identifier_nondigit | digit)* } identifier_nondigit = @{ nondigit | universal_character_name // TODO "other implementation-defined characters" } nondigit = { ('a'..'z' | 'A'..'Z' | "_") } digit = { '0'..'9' } preprocessing_op_or_punc = { // sorted by length bc PEG ordered choice "delete" | "and_eq" | "bitand" | "not_eq" | "xor_eq" | "bitor" | "compl" | "or_eq" | "%:%:" | "..." | "new" | ">>=" | "<<=" | "->*" | "and" | "not" | "xor" | "##" | "<:" | ":>" | "<%" | "%>" | "%:" | "::" | ".*" | "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|=" | "<<" | ">>" | "==" | "!=" | "<=" | ">=" | "&&" | "||" | "++" | "--" | "->" | "or" | "{" | "}" | "[" | "]" | "#" | "(" | ")" | ";" | ":" | "?" | "." | "+" | "-" | "*" | "/" | "%" | "^" | "&" | "|" | "~" | "!" | "=" | "<" | ">" | "," } literal = { integer_literal | character_literal | floating_literal | string_literal | boolean_literal | pointer_literal | user_defined_literal } integer_literal = @{ (decimal_literal ~ integer_suffix?) | (octal_literal ~ integer_suffix?) | (hexadecimal_literal ~ integer_suffix?) | (binary_literal ~ integer_suffix?) } decimal_literal = @{ nonzero_digit ~ ("'"? ~ digit)* } octal_literal = @{ "0" ~ ("'"? ~ octal_digit)* } hexadecimal_literal = @{ ("0x" | "0X") ~ hexadecimal_digit ~ ("'"? ~ hexadecimal_digit)* } binary_literal = @{ ("0b" | "0B") ~ binary_digit ~ ("'"? ~ binary_digit)* } nonzero_digit = { '1'..'9' } octal_digit = { '0'..'7' } hexadecimal_digit = { '0'..'9' | 'a'..'f' | 'A'..'F' } binary_digit = { '0'..'1' } integer_suffix = @{ (unsigned_suffix ~ long_long_suffix?) | (unsigned_suffix ~ long_suffix?) | (long_long_suffix ~ unsigned_suffix?) | (long_suffix ~ unsigned_suffix?) } unsigned_suffix = { "u" | "U" } long_suffix = { "l" | "L" } long_long_suffix = { "ll" | "LL" } character_literal = @{ ("u" | "U" | "L")? ~ "'" ~ c_char_sequence ~ "'" } c_char_sequence = @{ c_char+ } c_char = @{ (!("'" | "\\" | NEWLINE) ~ ANY) | escape_sequence | universal_character_name } escape_sequence = { simple_escape_sequence | octal_escape_sequence | hexadecimal_escape_sequence } simple_escape_sequence = { "\\'" | "\\\"" | "\\?" | "\\\\" | "\\a" | "\\b" | "\\f" | "\\n" | "\\r" | "\\t" | "\\v" } octal_escape_sequence = @{ "\\" ~ octal_digit ~ octal_digit? ~ octal_digit? } hexadecimal_escape_sequence = @{ "\\x" ~ hexadecimal_digit+ } floating_literal = @{ (fractional_constant ~ exponent_part? ~ floating_suffix?) | (digit_sequence ~ exponent_part ~ floating_suffix?) } fractional_constant = @{ (digit_sequence? ~ "." ~ digit_sequence) | (digit_sequence ~ ".") } exponent_part = @{ ("e" | "E") ~ sign? ~ digit_sequence } sign = { "+" | "-" } digit_sequence = @{ digit ~ ("'"? ~ digit)* } floating_suffix = { "f" | "l" | "F" | "L" } string_literal = @{ encoding_prefix? ~ (("\"" ~ s_char_sequence? ~ "\"") | ("R" ~ raw_string)) } encoding_prefix = { "u8" | "u" | "U" | "L" } s_char_sequence = @{ s_char+ } s_char = @{ (!("\"" | "\\" | NEWLINE) ~ ANY) | escape_sequence | universal_character_name } raw_string = @{ "\"" ~ d_char_sequence? ~ "(" ~ r_char_sequence? ~ ")" ~ d_char_sequence? ~ "\"" } r_char_sequence = @{ r_char+ } r_char = @{ // TODO what uhhh the fuck ANY } d_char_sequence = @{ d_char+ } d_char = @{ !(" " | "(" | ")" | "\\" | "\t" | "\u{0B}" | "\r" | "\n") ~ ANY } boolean_literal = { "false" | "true" } pointer_literal = { "nullptr" } user_defined_literal = { user_defined_integer_literal | user_defined_floating_literal | user_defined_string_literal | user_defined_character_literal } user_defined_integer_literal = @{ (decimal_literal | octal_literal | hexadecimal_literal | binary_literal) ~ ud_suffix } user_defined_floating_literal = @{ (fractional_constant ~ exponent_part? ~ ud_suffix) | (digit_sequence ~ exponent_part ~ ud_suffix) } user_defined_string_literal = @{ string_literal ~ ud_suffix } user_defined_character_literal = @{ character_literal ~ ud_suffix } ud_suffix = { identifier } translation_unit = { SOI ~ declaration_seq? ~ EOI } primary_expression = { literal | "this" | ("(" ~ expression ~ ")") | id_expression | lambda_expression } id_expression = { unqualified_id | qualified_id } unqualified_id = { identifier | operator_function_id | conversion_function_id | literal_operator_id | ("~" ~ class_name) | ("~" ~ decltype_specifier) | template_id } qualified_id = { nested_name_specifier ~ "template"? ~ unqualified_id } nested_name_specifier = { ( "::" | (type_name ~ "::") | (namespace_name ~ "::") | (decltype_specifier ~ "::") ) ~ ( (identifier ~ "::") | ("template"? ~ simple_template_id ~ "::") )* } lambda_expression = { lambda_introducer ~ lambda_declarator? ~ compound_statement } lambda_introducer = { "[" ~ lambda_capture? ~ "]" } lambda_capture = { capture_default | capture_list | (capture_default ~ "," ~ capture_list) } capture_default = { "&" | "=" } capture_list = { capture ~ "..."? ~ ("," ~ capture ~ "..."?)* } capture = { simple_capture | init_capture } simple_capture = { identifier | ("&" ~ identifier) | "this" } init_capture = { "&"? ~ identifier ~ initializer } lambda_declarator = { ("(" ~ parameter_declaration_clause ~ ")" ~ "mutable"?) | (exception_specification? ~ attribute_specifier_seq? ~ trailing_return_type?) } postfix_expression = { ( primary_expression | (simple_type_specifier ~ "(" ~ expression_list? ~ ")") | (typename_specifier ~ "(" ~ expression_list? ~ ")") | (simple_type_specifier ~ braced_init_list) | (typename_specifier ~ braced_init_list) | ("dynamic_cast" ~ "<" ~ type_id ~ ">" ~ "(" ~ expression ~ ")") | ("static_cast" ~ "<" ~ type_id ~ ">" ~ "(" ~ expression ~ ")") | ("reinterpret_cast" ~ "<" ~ type_id ~ ">" ~ "(" ~ expression ~ ")") | ("const_cast" ~ "<" ~ type_id ~ ">" ~ "(" ~ expression ~ ")") | ("typeid" ~ "(" ~ expression ~ ")") | ("typeid" ~ "(" ~ type_id ~ ")") ) ~ ( ("[" ~ expression ~ "]") | ("[" ~ braced_init_list ~ "]") | ("(" ~ expression_list? ~ ")") | ("." ~ "template"? ~ id_expression) | ("->" ~ "template"? ~ id_expression) | ("." ~ pseudo_destructor_name) | ("->" ~ pseudo_destructor_name) | "++" | "--" )* } expression_list = { initializer_list } pseudo_destructor_name = { (nested_name_specifier? ~ type_name ~ "::" ~ "~" ~ type_name) | (nested_name_specifier ~ "template" ~ simple_template_id ~ "::" ~ "~" ~ type_name) | (nested_name_specifier? ~ "~" ~ type_name) | ("~" ~ decltype_specifier) } unary_expression = { postfix_expression | ("++" ~ cast_expression) | ("--" ~ cast_expression) | (unary_operator ~ cast_expression) | ("sizeof" ~ unary_expression) | ("sizeof" ~ "(" ~ type_id ~ ")") | ("sizeof" ~ "..." ~ "(" ~ identifier ~ ")") | ("alignof" ~ "(" ~ type_id ~ ")") | noexcept_expression | new_expression | delete_expression } unary_operator = { "*" | "&" | "+" | "-" | "!" | "~" } new_expression = { "::"? ~ "new" ~ new_placement? ~ (new_type_id | ("(" ~ type_id ~ ")")) ~ new_initializer? } new_placement = { "(" ~ expression_list ~ ")" } new_type_id = { type_specifier_seq ~ new_declarator? } new_declarator = { (ptr_operator ~ new_declarator?) | noptr_new_declarator } noptr_new_declarator = { "[" ~ expression ~ "]" ~ attribute_specifier_seq? ~ ("[" ~ constant_expression ~ "]" ~ attribute_specifier_seq?)* } new_initializer = { ("(" ~ expression_list? ~ ")") | braced_init_list } delete_expression = { "::"? ~ "delete" ~ ("[" ~ "]")? ~ cast_expression } noexcept_expression = { "noexcept" ~ "(" ~ expression ~ ")" } cast_expression = { unary_expression | ("(" ~ type_id ~ ")" ~ cast_expression) } pm_expression = { cast_expression ~ ((".*" | "->*") ~ cast_expression)* } multiplicative_expression = { pm_expression ~ (("*" | "/" | "%") ~ pm_expression)* } additive_expression = { multiplicative_expression ~ (("+" | "-") ~ multiplicative_expression)* } shift_expression = { additive_expression ~ (("<<" | ">>") ~ additive_expression)* } relational_expression = { shift_expression ~ (("<=" | ">=" | "<" | ">") ~ shift_expression)* } equality_expression = { relational_expression ~ (("==" | "!=") ~ relational_expression)* } and_expression = { equality_expression ~ ("&" ~ equality_expression)* } exclusive_or_expression = { and_expression ~ ("^" ~ and_expression)* } inclusive_or_expression = { exclusive_or_expression ~ ("|" ~ exclusive_or_expression)* } logical_and_expression = { inclusive_or_expression ~ ("&&" ~ inclusive_or_expression)* } logical_or_expression = { logical_and_expression ~ ("||" ~ logical_and_expression)* } conditional_expression = { logical_or_expression | (logical_or_expression ~ "?" ~ expression ~ ":" ~ assignment_expression) } assignment_expression = { conditional_expression | (logical_or_expression ~ assignment_operator ~ initializer_clause) | throw_expression } assignment_operator = { "=" | "*=" | "/=" | "%=" | "+=" | "-=" | ">>=" | "<<=" | "&=" | "^=" | "|=" } expression = { assignment_expression ~ ("," ~ assignment_expression)* } constant_expression = { conditional_expression } statement = { labeled_statement | (attribute_specifier_seq? ~ expression_statement) | (attribute_specifier_seq? ~ compound_statement) | (attribute_specifier_seq? ~ selection_statement) | (attribute_specifier_seq? ~ iteration_statement) | (attribute_specifier_seq? ~ jump_statement) | declaration_statement | (attribute_specifier_seq? ~ try_block) } labeled_statement = { (attribute_specifier_seq? ~ identifier ~ ":" ~ statement) | (attribute_specifier_seq? ~ "case" ~ constant_expression ~ ":" ~ statement) | (attribute_specifier_seq? ~ "default" ~ ":" ~ statement) } expression_statement = { expression? ~ ";" } compound_statement = { "{" ~ statement_seq? ~ "}" } statement_seq = { statement+ } selection_statement = { ("if" ~ "(" ~ condition ~ ")" ~ statement ~ ("else" ~ statement)?) | ("switch" ~ "(" ~ condition ~ ")" ~ statement) } condition = { expression | (attribute_specifier_seq? ~ decl_specifier_seq ~ declarator ~ "=" ~ initializer_clause) | (attribute_specifier_seq? ~ decl_specifier_seq ~ declarator ~ braced_init_list) } iteration_statement = { ("while" ~ "(" ~ condition ~ ")" ~ statement) | ("do" ~ statement ~ "while" ~ "(" ~ expression ~ ")" ~ ";") | ("for" ~ "(" ~ ((for_init_statement ~ condition? ~ ";" ~ expression?) | (for_range_declaration ~ ":" ~ for_range_initializer)) ~ ")" ~ statement) } for_init_statement = { expression_statement | simple_declaration } for_range_declaration = { attribute_specifier_seq? ~ decl_specifier_seq ~ declarator } for_range_initializer = { expression | braced_init_list } jump_statement = { ("break" ~ ";") | ("continue" ~ ";") | ("return" ~ (braced_init_list | expression?) ~ ";") | ("goto" ~ identifier ~ ";") } declaration_statement = { block_declaration } declaration_seq = { declaration+ } declaration = { block_declaration | function_definition | template_declaration | explicit_instantiation | explicit_specialization | linkage_specification | namespace_definition | empty_declaration | attribute_declaration } block_declaration = { simple_declaration | asm_definition | namespace_alias_definition | using_declaration | using_directive | static_assert_declaration | alias_declaration | opaque_enum_declaration } alias_declaration = { "using" ~ identifier ~ attribute_specifier_seq? ~ "=" ~ type_id ~ ";" } simple_declaration = { (decl_specifier_seq? ~ init_declarator_list? ~ ";") | (attribute_specifier_seq ~ decl_specifier_seq? ~ init_declarator_list ~ ";") } static_assert_declaration = { "static_assert" ~ "(" ~ constant_expression ~ "," ~ string_literal ~ ")" ~ ";" } empty_declaration = { ";" } attribute_declaration = { attribute_specifier_seq ~ ";" } decl_specifier = { storage_class_specifier | type_specifier | function_specifier | "friend" | "typedef" | "constexpr" } decl_specifier_seq = { (decl_specifier ~ attribute_specifier_seq?)+ } storage_class_specifier = { "register" | "static" | "thread_local" | "extern" | "mutable" } function_specifier = { "inline" | "virtual" | "explicit" } typedef_name = { identifier } type_specifier = { trailing_type_specifier | class_specifier | enum_specifier } trailing_type_specifier = { simple_type_specifier | elaborated_type_specifier | typename_specifier | cv_qualifier } type_specifier_seq = { (trailing_type_specifier ~ attribute_specifier_seq?)+ } trailing_type_specifier_seq = { trailing_type_specifier+ ~ attribute_specifier_seq? } simple_type_specifier = { (nested_name_specifier? ~ type_name) | (nested_name_specifier ~ "template" ~ simple_template_id) | "char" | "char16_t" | "char32_t" | "wchar_t" | "bool" | "short" | "int" | "long" | "signed" | "unsigned" | "float" | "double" | "void" | "auto" | decltype_specifier } type_name = { class_name | enum_name | typedef_name | simple_template_id } decltype_specifier = { "decltype" ~ "(" ~ (expression | "auto") ~ ")" } elaborated_type_specifier = { (class_key ~ attribute_specifier_seq? ~ nested_name_specifier? ~ identifier) | (class_key ~ simple_template_id) | (class_key ~ nested_name_specifier ~ "template"? ~ simple_template_id) | ("enum" ~ nested_name_specifier? ~ identifier) } enum_name = { identifier } enum_specifier = { enum_head ~ "{" ~ enumerator_list? ~ ","? ~ "}" } enum_head = { enum_key ~ attribute_specifier_seq? ~ ((nested_name_specifier ~ identifier ~ enum_base?) | (identifier? ~ enum_base?)) } opaque_enum_declaration = { enum_key ~ attribute_specifier_seq? ~ identifier ~ enum_base? ~ ";" } enum_key = { "enum" ~ ("class" | "struct")? } enum_base = { ":" ~ type_specifier_seq } enumerator_list = { enumerator_definition ~ ("," ~ enumerator_definition)* } enumerator_definition = { enumerator ~ ("=" ~ constant_expression)? } enumerator = { identifier } namespace_name = { original_namespace_name | namespace_alias } original_namespace_name = { identifier } namespace_definition = { named_namespace_definition | unnamed_namespace_definition } named_namespace_definition = { original_namespace_definition | extension_namespace_definition } original_namespace_definition = { "inline"? ~ "namespace" ~ identifier ~ "{" ~ namespace_body ~ "}" } extension_namespace_definition = { "inline"? ~ "namespace" ~ original_namespace_name ~ "{" ~ namespace_body ~ "}" } unnamed_namespace_definition = { "inline"? ~ "namespace" ~ "{" ~ namespace_body ~ "}" } namespace_body = { declaration_seq? } namespace_alias = { identifier } namespace_alias_definition = { "namespace" ~ identifier ~ "=" ~ qualified_namespace_specifier ~ ";" } qualified_namespace_specifier = { nested_name_specifier? ~ namespace_name } using_declaration = { ("using" ~ "typename"? ~ nested_name_specifier ~ unqualified_id ~ ";") | ("using" ~ "::" ~ unqualified_id ~ ";") } using_directive = { attribute_specifier_seq? ~ "using" ~ "namespace" ~ nested_name_specifier? ~ namespace_name ~ ";" } asm_definition = { "asm" ~ "(" ~ string_literal ~ ")" ~ ";" } linkage_specification = { "extern" ~ string_literal ~ (("{" ~ declaration_seq? ~ "}") | declaration) } attribute_specifier_seq = { attribute_specifier* } attribute_specifier = { ("[" ~ "[" ~ attribute_list ~ "]" ~ "]") | alignment_specifier } alignment_specifier = { "alignas" ~ "(" ~ (type_id | constant_expression) ~ "..."? ~ ")" } attribute_list = { attribute? ~ "..."? ~ ("," ~ attribute? ~ "..."?)* } attribute = { attribute_token ~ attribute_argument_clause? } attribute_token = { identifier | attribute_scoped_token } attribute_scoped_token = { attribute_namespace ~ "::" ~ identifier } attribute_namespace = { identifier } attribute_argument_clause = { "(" ~ balanced_token_seq ~ ")" } balanced_token_seq = { balanced_token* } balanced_token = { ("(" ~ balanced_token_seq ~ ")") | ("[" ~ balanced_token_seq ~ "]") | ("{" ~ balanced_token_seq ~ "}") | (!("(" | ")" | "[" | "]" | "{" | "}") ~ token) } init_declarator_list = { init_declarator ~ ("," ~ init_declarator)* } init_declarator = { declarator ~ initializer? } declarator = { ptr_declarator | (noptr_declarator ~ parameters_and_qualifiers ~ trailing_return_type) } ptr_declarator = { ptr_operator* ~ noptr_declarator } noptr_declarator = { (declarator_id ~ attribute_specifier_seq? ~ (parameters_and_qualifiers | ("[" ~ constant_expression? ~ "]" ~ attribute_specifier_seq?))*) | ("(" ~ ptr_declarator ~ ")") } parameters_and_qualifiers = { "(" ~ parameter_declaration_clause ~ ")" ~ cv_qualifier_seq? ~ ref_qualifier? ~ exception_specification? ~ attribute_specifier_seq? } trailing_return_type = { "->" ~ trailing_type_specifier_seq ~ abstract_declarator? } ptr_operator = { ("*" ~ attribute_specifier_seq? ~ cv_qualifier_seq?) | ("&&" ~ attribute_specifier_seq?) | ("&" ~ attribute_specifier_seq?) | (nested_name_specifier ~ "*" ~ attribute_specifier_seq? ~ cv_qualifier_seq?) } cv_qualifier_seq = { cv_qualifier+ } cv_qualifier = { "const" | "volatile" } ref_qualifier = { "&" | "&&" } declarator_id = { "..."? ~ id_expression } type_id = { type_specifier_seq ~ abstract_declarator? } abstract_declarator = { (noptr_abstract_declarator? ~ parameters_and_qualifiers ~ trailing_return_type) | abstract_pack_declarator | ptr_abstract_declarator } ptr_abstract_declarator = { ptr_operator* ~ noptr_abstract_declarator? } noptr_abstract_declarator = { ("(" ~ ptr_abstract_declarator ~ ")")? ~ (parameters_and_qualifiers | ("[" ~ constant_expression? ~ "]" ~ attribute_specifier_seq?))* } abstract_pack_declarator = { ptr_operator* ~ noptr_abstract_pack_declarator } noptr_abstract_pack_declarator = { "..." ~ (parameters_and_qualifiers | ("[" ~ constant_expression? ~ "]" ~ attribute_specifier_seq?))* } parameter_declaration_clause = { parameter_declaration_list? ~ ","? ~ "..."? } parameter_declaration_list = { parameter_declaration ~ ("," ~ parameter_declaration)* } parameter_declaration = { attribute_specifier_seq? ~ decl_specifier_seq ~ (declarator | abstract_declarator?) ~ ("=" ~ initializer_clause)? } function_definition = { attribute_specifier_seq? ~ decl_specifier_seq? ~ declarator ~ virt_specifier_seq? ~ function_body } function_body = { (ctor_initializer? ~ compound_statement) | function_try_block | ("=" ~ "default" ~ ";") | ("=" ~ "delete" ~ ";") } initializer = { brace_or_equal_initializer | ("(" ~ expression_list ~ ")") } brace_or_equal_initializer = { ("=" ~ initializer_clause) | braced_init_list } initializer_clause = { assignment_expression | braced_init_list } initializer_list = { initializer_clause ~ "..."? ~ ("," ~ initializer_clause ~ "..."?)* } braced_init_list = { "{" ~ initializer_list? ~ ","? ~ "}" } class_name = { identifier | simple_template_id } class_specifier = { class_head ~ "{" ~ member_specification? ~ "}" } class_head = { class_key ~ attribute_specifier_seq? ~ ((class_head_name ~ class_virt_specifier? ~ base_clause?) | (base_clause?)) } class_head_name = { nested_name_specifier? ~ class_name } class_virt_specifier = { "final" } class_key = { "class" | "struct" | "union" } member_specification = { (member_declaration | (access_specifier ~ ":"))+ } member_declaration = { (attribute_specifier_seq? ~ decl_specifier_seq? ~ member_declarator_list? ~ ";") | function_definition | using_declaration | static_assert_declaration | template_declaration | alias_declaration | empty_declaration } member_declarator_list = { member_declarator ~ ("," ~ member_declarator)* } member_declarator = { (declarator ~ virt_specifier_seq? ~ pure_specifier?) | (declarator ~ brace_or_equal_initializer?) | (identifier? ~ attribute_specifier_seq? ~ ":" ~ constant_expression) } virt_specifier_seq = { virt_specifier+ } virt_specifier = { "override" | "final" } pure_specifier = { "=" ~ "0" } base_clause = { ":" ~ base_specifier_list } base_specifier_list = { base_specifier ~ "..."? ~ ("," ~ base_specifier ~ "..."?)* } base_specifier = { attribute_specifier_seq? ~ (("virtual" ~ access_specifier?) | (access_specifier ~ "virtual"?))? ~ base_type_specifier } class_or_decltype = { (nested_name_specifier? ~ class_name) | decltype_specifier } base_type_specifier = { class_or_decltype } access_specifier = { "private" | "protected" | "public" } conversion_function_id = { "operator" ~ conversion_type_id } conversion_type_id = { type_specifier_seq ~ conversion_declarator? } conversion_declarator = { ptr_operator+ } ctor_initializer = { ":" ~ mem_initializer_list } mem_initializer_list = { mem_initializer ~ "..."? ~ ("," ~ mem_initializer ~ "..."?)* } mem_initializer = { mem_initializer_id ~ (("(" ~ expression_list? ~ ")") | braced_init_list) } mem_initializer_id = { class_or_decltype | identifier } operator_function_id = { "operator" ~ operator } operator = { // sorted by length bc PEG ordered choice "delete[]" | "delete" | "new[]" | "new" | ">>=" | "<<=" | "->*" | "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|=" | "<<" | ">>" | "==" | "!=" | "<=" | ">=" | "&&" | "||" | "++" | "--" | "->" | ("[" ~ "]") | ("(" ~ ")") | "+" | "-" | "*" | "/" | "%" | "^" | "&" | "|" | "~" | "!" | "=" | "<" | ">" | "," } literal_operator_id = { "operator" ~ ((string_literal ~ identifier) | user_defined_string_literal) } template_declaration = { "template" ~ "<" ~ template_parameter_list ~ ">" ~ declaration } template_parameter_list = { template_parameter ~ ("," ~ template_parameter)* } template_parameter = { type_parameter | parameter_declaration } type_parameter = { ("class" ~ "..."? ~ identifier?) | ("class" ~ identifier? ~ "=" ~ type_id) | ("typename" ~ "..."? ~ identifier?) | ("typename" ~ identifier? ~ "=" ~ type_id) | ("template" ~ "<" ~ template_parameter_list ~ ">" ~ "class" ~ "..."? ~ identifier?) | ("template" ~ "<" ~ template_parameter_list ~ ">" ~ "class" ~ identifier? ~ "=" ~ id_expression) } simple_template_id = { template_name ~ "<" ~ template_argument_list? ~ ">" } template_id = { simple_template_id | (operator_function_id ~ "<" ~ template_argument_list? ~ ">") | (literal_operator_id ~ "<" ~ template_argument_list? ~ ">") } template_name = { identifier } template_argument_list = { template_argument ~ "..."? ~ ("," ~ template_argument ~ "..."?)* } template_argument = { constant_expression | type_id | id_expression } typename_specifier = { "typename" ~ nested_name_specifier ~ (identifier | ("template"? ~ simple_template_id)) } explicit_instantiation = { "extern"? ~ "template" ~ declaration } explicit_specialization = { "template" ~ "<" ~ ">" ~ declaration } try_block = { "try" ~ compound_statement ~ handler_seq } function_try_block = { "try" ~ ctor_initializer? ~ compound_statement ~ handler_seq } handler_seq = { handler+ } handler = { "catch" ~ "(" ~ exception_declaration ~ ")" ~ compound_statement } exception_declaration = { (attribute_specifier_seq? ~ type_specifier_seq ~ (declarator | abstract_declarator?)) | "..." } throw_expression = { "throw" ~ assignment_expression? } exception_specification = { dynamic_exception_specification | noexcept_specification } dynamic_exception_specification = { "throw" ~ "(" ~ type_id_list? ~ ")" } type_id_list = { type_id ~ "..."? ~ ("," ~ type_id ~ "..."?)* } noexcept_specification = { "noexcept" ~ ("(" ~ constant_expression ~ ")")? } preprocessing_file = { SOI ~ group? ~ EOI } group = { group_part+ } group_part = { if_section | control_line | text_line | ("#" ~ non_directive) } if_section = { if_group ~ elif_groups? ~ else_group? ~ endif_line } if_group = { ("#" ~ "if" ~ constant_expression ~ NEWLINE ~ group?) | ("#" ~ "ifdef" ~ identifier ~ NEWLINE ~ group?) | ("#" ~ "ifndef" ~ identifier ~ NEWLINE ~ group?) } elif_groups = { elif_group+ } elif_group = { "#" ~ "elif" ~ constant_expression ~ NEWLINE ~ group? } else_group = { "#" ~ "else" ~ NEWLINE ~ group? } endif_line = { "#" ~ "endif" ~ NEWLINE } control_line = { ("#" ~ "include" ~ pp_tokens ~ NEWLINE) | ("#" ~ "define" ~ identifier ~ replacement_list ~ NEWLINE) | ("#" ~ "define" ~ identifier_lparen ~ identifier_list? ~ ")" ~ replacement_list ~ NEWLINE) | ("#" ~ "define" ~ identifier_lparen ~ "..." ~ ")" ~ replacement_list ~ NEWLINE) | ("#" ~ "define" ~ identifier_lparen ~ identifier_list ~ "," ~ "..." ~ ")" ~ replacement_list ~ NEWLINE) | ("#" ~ "undef" ~ identifier ~ NEWLINE) | ("#" ~ "line" ~ pp_tokens ~ NEWLINE) | ("#" ~ "error" ~ pp_tokens? ~ NEWLINE) | ("#" ~ "pragma" ~ pp_tokens? ~ NEWLINE) | ("#" ~ NEWLINE) } text_line = { pp_tokens? ~ NEWLINE } non_directive = { pp_tokens ~ NEWLINE } identifier_lparen = ${ identifier ~ "(" } identifier_list = { identifier ~ ("," ~ identifier)* } replacement_list = { pp_tokens? } pp_tokens = { preprocessing_token+ } WHITESPACE = _{ " " | "\n" | "\t" } COMMENT = _{ ("//" ~ (!"\n" ~ ANY)*) | ("/*" ~ (!"*/") ~ ANY)* ~ "*/"}