Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grammar railroad diagram #1634

Open
mingodad opened this issue Mar 26, 2024 · 5 comments
Open

Grammar railroad diagram #1634

mingodad opened this issue Mar 26, 2024 · 5 comments

Comments

@mingodad
Copy link
Contributor

I've just added this project grammar to https://mingodad.github.io/parsertl-playground/playground/ an Yacc/Lex compatible online editor/tester (select Panda3d cppparser (partially working) from Examples then click Parse to see a parse tree for the content in Input source).

Notice that I've replaced right recursion by left recursion in some rules.

And here is an EBNF to generate a nice navigable railroad diagram:

//
// EBNF to be viewd at
//    (IPV6) https://www.bottlecaps.de/rr/ui
//    (IPV4) https://rr.red-dove.com/ui
//
// Copy and paste this at one of the urls shown above in the 'Edit Grammar' tab
// then click the 'View Diagram' tab.
//

grammar::=
	START_CPP cpp
	| START_CONST_EXPR const_expr
	| START_TYPE full_type

cpp::=
	  /*%empty*/
	| cpp optional_attributes ';'
	| cpp optional_attributes declaration

constructor_inits::=
	  constructor_init
	| constructor_inits ',' constructor_init

constructor_init::=
	  name '(' optional_const_expr_comma ')'
	| name '(' optional_const_expr_comma ')' ELLIPSIS
	| name '{' optional_const_expr_comma '}'

extern_c::=
	  storage_class '{' cpp '}'

declaration::=
	  type_like_declaration
	| template_declaration
	| extern_c
	| namespace_declaration
	| friend_declaration
	| KW_TYPEDEF typedef_declaration
	| KW_BEGIN_PUBLISH
	| KW_END_PUBLISH
	| KW_PUBLISHED ':'
	| KW_PUBLIC ':'
	| KW_PROTECTED ':'
	| KW_PRIVATE ':'
	| KW_MAKE_PROPERTY '(' name ',' IDENTIFIER maybe_comma_identifier ')' ';'
	| KW_MAKE_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_SEQ_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ')' ';'
	| KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_MAP_PROPERTY '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER maybe_comma_identifier ')' ';'
	| KW_MAKE_MAP_KEYS_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_PROPERTY2 '(' name ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_MAKE_SEQ '(' name ',' IDENTIFIER ',' IDENTIFIER ')' ';'
	| KW_STATIC_ASSERT '(' const_expr ',' string_literal ')' ';'
	| KW_STATIC_ASSERT '(' const_expr ')' ';'

friend_declaration::=
	  KW_FRIEND declaration

storage_class::=
	  /*%empty*/
	| KW_CONST storage_class
	| KW_EXTERN storage_class
	| KW_EXTERN SIMPLE_STRING storage_class
	| KW_STATIC storage_class
	| KW_INLINE storage_class
	| KW_VIRTUAL storage_class
	| KW_EXPLICIT storage_class
	| KW_EXPLICIT_LPAREN const_expr ')' storage_class
	| KW_REGISTER storage_class
	| KW_VOLATILE storage_class
	| KW_MUTABLE storage_class
	| KW_CONSTEVAL storage_class
	| KW_CONSTEXPR storage_class
	| KW_CONSTINIT storage_class
	| KW_BLOCKING storage_class
	| KW_EXTENSION storage_class
	| KW_THREAD_LOCAL storage_class

optional_attributes::=
	  /*%empty*/
	| optional_attributes ATTR_LEFT attribute_specifiers ATTR_RIGHT
	| optional_attributes ATTR_LEFT KW_USING name ':' attribute_specifiers ATTR_RIGHT
	| optional_attributes KW_ALIGNAS '(' const_expr ')'
	| optional_attributes KW_ALIGNAS '(' type_decl ')'

attribute_specifiers::=
	  attribute_specifier
	| attribute_specifiers ',' attribute_specifier

attribute_specifier::=
	  name
	| name '(' formal_parameter_list ')'

type_like_declaration::=
	  storage_class var_type_decl multiple_instance_identifiers
	| storage_class type_decl ';'
	| storage_class constructor_prototype maybe_initialize_or_constructor_body
	| storage_class function_prototype maybe_initialize_or_function_body
	| using_declaration

multiple_instance_identifiers::=
	  instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body
	| instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' multiple_instance_identifiers

typedef_declaration::=
	  storage_class var_type_decl typedef_instance_identifiers
	| storage_class function_prototype maybe_initialize_or_function_body

typedef_instance_identifiers::=
	  instance_identifier_and_maybe_trailing_return_type maybe_initialize_or_function_body
	| instance_identifier_and_maybe_trailing_return_type maybe_initialize ',' typedef_instance_identifiers

constructor_prototype::=
	  IDENTIFIER '(' function_parameter_list ')' function_post optional_attributes
	| TYPENAME_IDENTIFIER '(' IDENTIFIER ')' '(' function_parameter_list ')' function_post optional_attributes
	| TYPENAME_IDENTIFIER '(' function_parameter_list ')' function_post optional_attributes

function_prototype::=
	  '~' name '(' function_parameter_list ')' function_post optional_attributes
	| TYPENAME_IDENTIFIER '(' '*' instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type
	| TYPENAME_IDENTIFIER '(' SCOPING '*' instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type
	| KW_OPERATOR type not_paren_formal_parameter_identifier '(' function_parameter_list ')' function_post
	| KW_OPERATOR KW_CONST type not_paren_formal_parameter_identifier '(' function_parameter_list ')' function_post
	| IDENTIFIER

function_post::=
	  /*%empty*/
	| function_post KW_CONST
	| function_post KW_VOLATILE
	| function_post KW_NOEXCEPT
	| function_post KW_NOEXCEPT_LPAREN const_expr ')'
	| function_post KW_FINAL
	| function_post KW_OVERRIDE
	| function_post '&'
	| function_post ANDAND
	| function_post KW_MUTABLE
	| function_post KW_CONSTEXPR
	| function_post KW_THROW '(' ')'
	| function_post KW_THROW '(' name ')'
	| function_post KW_THROW '(' name ELLIPSIS ')'

function_operator::=
	  '!'
	| '~'
	| '*'
	| '/'
	| '%'
	| '+'
	| '-'
	| '|'
	| '&'
	| '^'
	| OROR
	| ANDAND
	| EQCOMPARE
	| NECOMPARE
	| LECOMPARE
	| GECOMPARE
	| '<'
	| '>'
	| SPACESHIP
	| LSHIFT
	| RSHIFT
	| '='
	| ','
	| PLUSPLUS
	| MINUSMINUS
	| TIMESEQUAL
	| DIVIDEEQUAL
	| MODEQUAL
	| PLUSEQUAL
	| MINUSEQUAL
	| OREQUAL
	| ANDEQUAL
	| XOREQUAL
	| LSHIFTEQUAL
	| RSHIFTEQUAL
	| POINTSAT
	| '[' ']'
	| '(' ')'
	| KW_NEW
	| KW_DELETE

more_template_declaration::=
	  type_like_declaration
	| template_declaration
	| friend_declaration

template_declaration::=
	  KW_EXTERN template_declaration
	| KW_TEMPLATE '<' template_formal_parameters '>' more_template_declaration
	| KW_TEMPLATE type_like_declaration
	| KW_TEMPLATE friend_declaration

template_formal_parameters::=
	  /*%empty*/
	| template_nonempty_formal_parameters

template_nonempty_formal_parameters::=
	  template_formal_parameter
	| template_nonempty_formal_parameters ',' template_formal_parameter

typename_keyword::=
	  KW_CLASS
	| KW_TYPENAME

template_formal_parameter::=
	  typename_keyword
	| typename_keyword name
	| typename_keyword name '=' full_type
	| typename_keyword ELLIPSIS
	| typename_keyword ELLIPSIS name
	| template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize
	| KW_CONST template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize
	| template_formal_parameter_type parameter_pack_identifier
	| KW_CONST template_formal_parameter_type parameter_pack_identifier

template_formal_parameter_type::=
	  simple_type
	| IDENTIFIER
	| TYPENAME_IDENTIFIER
	| TYPEPACK_IDENTIFIER

instance_identifier::=
	  name_no_final optional_attributes
	| KW_OPERATOR function_operator optional_attributes
	| KW_OPERATOR SIMPLE_STRING IDENTIFIER optional_attributes
	| KW_CONST instance_identifier
	| KW_VOLATILE instance_identifier
	| '*' optional_attributes instance_identifier
	| '&' optional_attributes instance_identifier
	| ANDAND optional_attributes instance_identifier
	| SCOPING '*' optional_attributes instance_identifier
	| instance_identifier '[' optional_const_expr ']' optional_attributes
	| '(' instance_identifier ')'
	| instance_identifier '(' formal_parameter_list ')' function_post optional_attributes

instance_identifier_and_maybe_trailing_return_type::=
	  instance_identifier maybe_trailing_return_type
	| instance_identifier ':' const_expr

maybe_trailing_return_type::=
	  /*%empty*/
	| POINTSAT predefined_type empty_instance_identifier
	| POINTSAT KW_CONST predefined_type empty_instance_identifier

maybe_comma_identifier::=
	  /*%empty*/
	| ',' IDENTIFIER

function_parameter_list::=
	  /*%empty*/
	| ELLIPSIS
	| function_parameters
	| function_parameters ',' ELLIPSIS
	| function_parameters ELLIPSIS

function_parameters::=
	  function_parameter
	| function_parameters ',' function_parameter

formal_parameter_list::=
	  /*%empty*/
	| ELLIPSIS
	| formal_parameters
	| formal_parameters ',' ELLIPSIS
	| formal_parameters ELLIPSIS

formal_parameters::=
	  formal_parameter
	| formal_parameters ',' formal_parameter

template_parameter_maybe_initialize::=
	  /*%empty*/
	| '=' no_angle_bracket_const_expr

maybe_initialize::=
	  /*%empty*/
	| '=' const_expr

maybe_initialize_or_constructor_body::=
	  ';'
	| '{' code '}'
	| ':' constructor_inits '{' code '}'
	| '=' KW_DEFAULT ';'
	| '=' KW_DELETE ';'

maybe_initialize_or_function_body::=
	  ';'
	| '{' code '}'
	| '=' const_expr ';'
	| '=' KW_DEFAULT ';'
	| '=' KW_DELETE ';'
	| '=' '{' structure_init '}'

structure_init::=
	  /*%empty*/
	| structure_init_body
	| structure_init_body ','

structure_init_body::=
	  const_expr
	| '{' structure_init '}'
	| structure_init_body ',' const_expr
	| structure_init_body ',' '{' structure_init '}'

function_parameter::=
	  optional_attributes type formal_parameter_identifier maybe_initialize
	| optional_attributes KW_CONST type formal_parameter_identifier maybe_initialize
	| optional_attributes KW_CONST KW_REGISTER type formal_parameter_identifier maybe_initialize
	| optional_attributes type_pack parameter_pack_identifier maybe_initialize
	| optional_attributes KW_CONST type_pack parameter_pack_identifier maybe_initialize
	| optional_attributes KW_CONST KW_REGISTER type_pack parameter_pack_identifier maybe_initialize
	| optional_attributes KW_REGISTER function_parameter

formal_parameter::=
	  function_parameter
	| formal_const_expr

not_paren_formal_parameter_identifier::=
	  /*%empty*/
	| name_no_final optional_attributes
	| KW_CONST not_paren_formal_parameter_identifier
	| KW_VOLATILE not_paren_formal_parameter_identifier
	| '*' optional_attributes not_paren_formal_parameter_identifier
	| '&' optional_attributes not_paren_formal_parameter_identifier
	| ANDAND optional_attributes not_paren_formal_parameter_identifier
	| SCOPING '*' optional_attributes not_paren_formal_parameter_identifier
	| not_paren_formal_parameter_identifier '[' optional_const_expr ']' optional_attributes

formal_parameter_identifier::=
	  /*%empty*/
	| name_no_final optional_attributes
	| KW_CONST formal_parameter_identifier
	| KW_VOLATILE formal_parameter_identifier
	| '*' optional_attributes formal_parameter_identifier
	| '&' optional_attributes formal_parameter_identifier
	| ANDAND optional_attributes formal_parameter_identifier
	| SCOPING '*' optional_attributes formal_parameter_identifier
	| formal_parameter_identifier '[' optional_const_expr ']' optional_attributes
	| '(' formal_parameter_identifier ')' '(' function_parameter_list ')' function_post optional_attributes
	| '(' formal_parameter_identifier ')'

parameter_pack_identifier::=
	  ELLIPSIS
	| ELLIPSIS name optional_attributes
	| KW_CONST parameter_pack_identifier
	| KW_VOLATILE parameter_pack_identifier
	| '*' optional_attributes parameter_pack_identifier
	| '&' optional_attributes parameter_pack_identifier
	| ANDAND optional_attributes parameter_pack_identifier
	| SCOPING '*' optional_attributes parameter_pack_identifier
	| parameter_pack_identifier '[' optional_const_expr ']' optional_attributes
	| '(' parameter_pack_identifier ')' '(' function_parameter_list ')' function_post optional_attributes
	| '(' parameter_pack_identifier ')'

not_paren_empty_instance_identifier::=
	  /*%empty*/
	| ELLIPSIS
	| ELLIPSIS name optional_attributes
	| KW_CONST not_paren_empty_instance_identifier
	| KW_VOLATILE not_paren_empty_instance_identifier
	| '*' optional_attributes not_paren_empty_instance_identifier
	| '&' optional_attributes not_paren_empty_instance_identifier
	| ANDAND optional_attributes not_paren_empty_instance_identifier
	| SCOPING '*' optional_attributes not_paren_empty_instance_identifier
	| not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes

empty_instance_identifier::=
	  /*%empty*/
	| ELLIPSIS
	| ELLIPSIS name optional_attributes
	| KW_CONST empty_instance_identifier
	| KW_VOLATILE empty_instance_identifier
	| '*' optional_attributes not_paren_empty_instance_identifier
	| '&' optional_attributes not_paren_empty_instance_identifier
	| ANDAND optional_attributes not_paren_empty_instance_identifier
	| SCOPING '*' optional_attributes not_paren_empty_instance_identifier
	| not_paren_empty_instance_identifier '[' optional_const_expr ']' optional_attributes
	| '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type
	| '(' '*' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type
	| '(' '&' optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type
	| '(' ANDAND optional_attributes not_paren_empty_instance_identifier ')' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type

type::=
	  simple_type
	| TYPENAME_IDENTIFIER
	| KW_TYPENAME name
	| anonymous_struct
	| named_struct
	| enum
	| struct_keyword optional_attributes name
	| enum_keyword optional_attributes name_no_final ':' enum_element_type
	| KW_DECLTYPE '(' const_expr ')'
	| KW_DECLTYPE '(' KW_AUTO ')'
	| KW_UNDERLYING_TYPE '(' full_type ')'
	| KW_AUTO

type_pack::=
	  TYPEPACK_IDENTIFIER

type_decl::=
	  simple_type
	| TYPENAME_IDENTIFIER
	| KW_TYPENAME name
	| anonymous_struct
	| named_struct
	| enum
	| struct_keyword optional_attributes name
	| enum_keyword optional_attributes name_no_final ':' enum_element_type
	| enum_keyword optional_attributes name
	| KW_DECLTYPE '(' const_expr ')'
	| KW_DECLTYPE '(' KW_AUTO ')'
	| KW_UNDERLYING_TYPE '(' full_type ')'
	| KW_AUTO

predefined_type::=
	  simple_type
	| TYPENAME_IDENTIFIER
	| KW_TYPENAME name
	| struct_keyword optional_attributes name
	| enum_keyword optional_attributes name
	| KW_DECLTYPE '(' const_expr ')'
	| KW_UNDERLYING_TYPE '(' full_type ')'
	| KW_AUTO

var_type_decl::=
	  type_decl
	| IDENTIFIER

full_type::=
	  type empty_instance_identifier
	| KW_CONST type empty_instance_identifier
	| type_pack empty_instance_identifier
	| KW_CONST type_pack empty_instance_identifier

anonymous_struct::=
	  struct_keyword optional_attributes '{' cpp '}'

named_struct::=
	  struct_keyword optional_attributes name_no_final maybe_final maybe_class_derivation '{' cpp '}'

maybe_final::=
	  /*%empty*/
	| KW_FINAL

maybe_class_derivation::=
	  /*%empty*/
	| class_derivation

class_derivation::=
	  ':' base_specification
	| class_derivation ',' base_specification

base_specification::=
	  class_derivation_name
	| KW_PUBLIC class_derivation_name
	| KW_PROTECTED class_derivation_name
	| KW_PRIVATE class_derivation_name
	| KW_VIRTUAL KW_PUBLIC class_derivation_name
	| KW_VIRTUAL KW_PROTECTED class_derivation_name
	| KW_VIRTUAL KW_PRIVATE class_derivation_name
	| KW_PUBLIC KW_VIRTUAL class_derivation_name
	| KW_PROTECTED KW_VIRTUAL class_derivation_name
	| KW_PRIVATE KW_VIRTUAL class_derivation_name

enum::=
	  enum_decl '{' enum_body '}'

enum_decl::=
	  enum_keyword optional_attributes ':' enum_element_type
	| enum_keyword optional_attributes
	| enum_keyword optional_attributes name_no_final ':' enum_element_type
	| enum_keyword optional_attributes name_no_final

enum_element_type::=
	  simple_int_type
	| TYPENAME_IDENTIFIER

enum_body_trailing_comma::=
	  /*%empty*/
	| enum_body_trailing_comma name optional_attributes ','
	| enum_body_trailing_comma name optional_attributes '=' const_expr ','

enum_body::=
	  enum_body_trailing_comma
	| enum_body_trailing_comma name optional_attributes
	| enum_body_trailing_comma name optional_attributes '=' const_expr

enum_keyword::=
	  KW_ENUM
	| KW_ENUM KW_CLASS
	| KW_ENUM KW_STRUCT

struct_keyword::=
	  KW_CLASS
	| KW_STRUCT
	| KW_UNION

namespace_declaration::=
	  KW_NAMESPACE optional_attributes name '{' cpp '}'
	| KW_INLINE KW_NAMESPACE name '{' cpp '}'
	| KW_NAMESPACE '{' cpp '}'
	| KW_INLINE KW_NAMESPACE '{' cpp '}'

using_declaration::=
	  KW_USING name ';'
	| KW_USING name optional_attributes '=' full_type ';'
	| KW_USING KW_NAMESPACE name ';'
	| KW_USING KW_ENUM name ';'

simple_type::=
	  simple_int_type
	| simple_float_type
	| simple_void_type

simple_int_type::=
	  KW_BOOL
	| KW_CHAR
	| KW_WCHAR_T
	| KW_CHAR8_T
	| KW_CHAR16_T
	| KW_CHAR32_T
	| KW_SHORT
	| KW_LONG
	| KW_UNSIGNED
	| KW_SIGNED
	| KW_INT
	| KW_SHORT simple_int_type
	| KW_LONG simple_int_type
	| KW_UNSIGNED simple_int_type
	| KW_SIGNED simple_int_type

simple_float_type::=
	  KW_FLOAT
	| KW_DOUBLE
	| KW_LONG KW_DOUBLE

simple_void_type::=
	  KW_VOID

code::=
	  code_block

code_block::=
	  /*%empty*/
	| code_block element

element::=
	  REAL
	| INTEGER
	| SIMPLE_STRING
	| STRING_LITERAL
	| CUSTOM_LITERAL
	| CHAR_TOK
	| IDENTIFIER
	| TYPENAME_IDENTIFIER
	| TYPEPACK_IDENTIFIER
	| SCOPING
	| SIMPLE_IDENTIFIER
	| ELLIPSIS
	| OROR
	| ANDAND
	| EQCOMPARE
	| NECOMPARE
	| LECOMPARE
	| GECOMPARE
	| SPACESHIP
	| LSHIFT
	| RSHIFT
	| POINTSAT_STAR
	| DOT_STAR
	| POINTSAT
	| SCOPE
	| PLUSPLUS
	| MINUSMINUS
	| TIMESEQUAL
	| DIVIDEEQUAL
	| MODEQUAL
	| PLUSEQUAL
	| MINUSEQUAL
	| OREQUAL
	| ANDEQUAL
	| XOREQUAL
	| LSHIFTEQUAL
	| RSHIFTEQUAL
	| ATTR_LEFT
	| ATTR_RIGHT
	| KW_ALIGNAS
	| KW_ALIGNOF
	| KW_AUTO
	| KW_BOOL
	| KW_CATCH
	| KW_CHAR
	| KW_CHAR8_T
	| KW_CHAR16_T
	| KW_CHAR32_T
	| KW_CLASS
	| KW_CONST
	| KW_CONSTEVAL
	| KW_CONSTEXPR
	| KW_CONSTINIT
	| KW_CONST_CAST
	| KW_DECLTYPE
	| KW_DEFAULT
	| KW_DELETE
	| KW_DOUBLE
	| KW_DYNAMIC_CAST
	| KW_ELSE
	| KW_ENUM
	| KW_EXTERN
	| KW_EXPLICIT
	| KW_EXPLICIT_LPAREN
	| KW_FALSE
	| KW_FINAL
	| KW_FLOAT
	| KW_FRIEND
	| KW_FOR
	| KW_GOTO
	| KW_IF
	| KW_INLINE
	| KW_INT
	| KW_LONG
	| KW_MUTABLE
	| KW_NAMESPACE
	| KW_NEW
	| KW_NOEXCEPT
	| KW_NOEXCEPT_LPAREN
	| KW_NULLPTR
	| KW_OPERATOR
	| KW_OVERRIDE
	| KW_PRIVATE
	| KW_PROTECTED
	| KW_PUBLIC
	| KW_PUBLISHED
	| KW_REGISTER
	| KW_REINTERPRET_CAST
	| KW_RETURN
	| KW_SHORT
	| KW_SIGNED
	| KW_SIZEOF
	| KW_STATIC
	| KW_STATIC_ASSERT
	| KW_STATIC_CAST
	| KW_STRUCT
	| KW_TEMPLATE
	| KW_THREAD_LOCAL
	| KW_THROW
	| KW_TRUE
	| KW_TRY
	| KW_TYPEDEF
	| KW_TYPEID
	| KW_TYPENAME
	| KW_UNDERLYING_TYPE
	| KW_UNION
	| KW_UNSIGNED
	| KW_USING
	| KW_VIRTUAL
	| KW_VOID
	| KW_VOLATILE
	| KW_WCHAR_T
	| KW_WHILE
	| '+'
	| '-'
	| '*'
	| '/'
	| '&'
	| '|'
	| '^'
	| '!'
	| '~'
	| '='
	| '%'
	| '<'
	| '>'
	| '('
	| ')'
	| '.'
	| ','
	| ';'
	| ':'
	| '['
	| ']'
	| '?'
	| '{' code_block '}'

optional_const_expr::=
	  /*%empty*/
	| const_expr

optional_const_expr_comma::=
	  /*%empty*/
	| const_expr_comma

const_expr_comma::=
	  const_expr
	| const_expr_comma ',' const_expr

no_angle_bracket_const_expr::=
	  const_operand
	| '(' full_type ')' no_angle_bracket_const_expr
	| KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_SIZEOF '(' full_type ')'
	| KW_SIZEOF no_angle_bracket_const_expr
	| KW_SIZEOF ELLIPSIS '(' name ')'
	| KW_ALIGNOF '(' full_type ')'
	| '!' no_angle_bracket_const_expr
	| '~' no_angle_bracket_const_expr
	| '-' no_angle_bracket_const_expr
	| '+' no_angle_bracket_const_expr
	| '*' no_angle_bracket_const_expr
	| '&' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '*' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '/' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '%' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '+' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '-' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '|' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '^' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '&' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr OROR no_angle_bracket_const_expr
	| no_angle_bracket_const_expr ANDAND no_angle_bracket_const_expr
	| no_angle_bracket_const_expr EQCOMPARE no_angle_bracket_const_expr
	| no_angle_bracket_const_expr NECOMPARE no_angle_bracket_const_expr
	| no_angle_bracket_const_expr LECOMPARE no_angle_bracket_const_expr
	| no_angle_bracket_const_expr GECOMPARE no_angle_bracket_const_expr
	| no_angle_bracket_const_expr SPACESHIP no_angle_bracket_const_expr
	| no_angle_bracket_const_expr LSHIFT no_angle_bracket_const_expr
	| no_angle_bracket_const_expr RSHIFT no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '?' no_angle_bracket_const_expr ':' no_angle_bracket_const_expr
	| no_angle_bracket_const_expr '[' const_expr ']'
	| no_angle_bracket_const_expr '(' const_expr_comma ')'
	| no_angle_bracket_const_expr '(' ')'
	| no_angle_bracket_const_expr '.' name
	| no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr
	| '(' const_expr_comma ')'

const_expr::=
	  const_operand
	| '(' full_type ')' const_expr
	| KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')'
	| TYPENAME_IDENTIFIER '(' optional_const_expr_comma ')'
	| TYPENAME_IDENTIFIER '{' optional_const_expr_comma '}'
	| KW_INT '(' optional_const_expr_comma ')'
	| KW_CHAR '(' optional_const_expr_comma ')'
	| KW_WCHAR_T '(' optional_const_expr_comma ')'
	| KW_CHAR8_T '(' optional_const_expr_comma ')'
	| KW_CHAR16_T '(' optional_const_expr_comma ')'
	| KW_CHAR32_T '(' optional_const_expr_comma ')'
	| KW_BOOL '(' optional_const_expr_comma ')'
	| KW_SHORT '(' optional_const_expr_comma ')'
	| KW_LONG '(' optional_const_expr_comma ')'
	| KW_UNSIGNED '(' optional_const_expr_comma ')'
	| KW_SIGNED '(' optional_const_expr_comma ')'
	| KW_FLOAT '(' optional_const_expr_comma ')'
	| KW_DOUBLE '(' optional_const_expr_comma ')'
	| KW_SIZEOF '(' full_type ')'
	| KW_SIZEOF const_expr
	| KW_SIZEOF ELLIPSIS '(' name ')'
	| KW_ALIGNOF '(' full_type ')'
	| KW_NEW predefined_type
	| KW_NEW predefined_type '(' optional_const_expr_comma ')'
	| KW_TYPEID '(' full_type ')'
	| KW_TYPEID '(' const_expr ')'
	| '!' const_expr
	| '~' const_expr
	| '-' const_expr
	| '+' const_expr
	| '*' const_expr
	| '&' const_expr
	| const_expr '*' const_expr
	| const_expr '/' const_expr
	| const_expr '%' const_expr
	| const_expr '+' const_expr
	| const_expr '-' const_expr
	| const_expr '|' const_expr
	| const_expr '^' const_expr
	| const_expr '&' const_expr
	| const_expr OROR const_expr
	| const_expr ANDAND const_expr
	| const_expr EQCOMPARE const_expr
	| const_expr NECOMPARE const_expr
	| const_expr LECOMPARE const_expr
	| const_expr GECOMPARE const_expr
	| const_expr SPACESHIP const_expr
	| const_expr '<' const_expr
	| const_expr '>' const_expr
	| const_expr LSHIFT const_expr
	| const_expr RSHIFT const_expr
	| const_expr '?' const_expr ':' const_expr
	| const_expr '[' const_expr ']'
	| const_expr '(' const_expr_comma ')'
	| const_expr '(' ')'
	| KW_NOEXCEPT_LPAREN const_expr ')'
	| const_expr '.' name
	| const_expr POINTSAT const_expr
	| '(' const_expr_comma ')'

const_operand::=
	  INTEGER
	| KW_TRUE
	| KW_FALSE
	| CHAR_TOK
	| REAL
	| string_literal
	| CUSTOM_LITERAL
	| IDENTIFIER
	| KW_FINAL
	| KW_OVERRIDE
	| KW_NULLPTR
	| '[' capture_list ']' function_post optional_attributes maybe_trailing_return_type '{' code '}'
	| '[' capture_list ']' '(' function_parameter_list ')' function_post optional_attributes maybe_trailing_return_type '{' code '}'
	| KW_HAS_VIRTUAL_DESTRUCTOR '(' full_type ')'
	| KW_IS_ABSTRACT '(' full_type ')'
	| KW_IS_BASE_OF '(' full_type ',' full_type ')'
	| KW_IS_CLASS '(' full_type ')'
	| KW_IS_CONSTRUCTIBLE '(' full_type ')'
	| KW_IS_CONSTRUCTIBLE '(' full_type ',' full_type ')'
	| KW_IS_CONVERTIBLE_TO '(' full_type ',' full_type ')'
	| KW_IS_DESTRUCTIBLE '(' full_type ')'
	| KW_IS_EMPTY '(' full_type ')'
	| KW_IS_ENUM '(' full_type ')'
	| KW_IS_FINAL '(' full_type ')'
	| KW_IS_FUNDAMENTAL '(' full_type ')'
	| KW_IS_POD '(' full_type ')'
	| KW_IS_POLYMORPHIC '(' full_type ')'
	| KW_IS_STANDARD_LAYOUT '(' full_type ')'
	| KW_IS_TRIVIAL '(' full_type ')'
	| KW_IS_TRIVIALLY_COPYABLE '(' full_type ')'
	| KW_IS_UNION '(' full_type ')'

formal_const_expr::=
	  formal_const_operand
	| '(' full_type ')' const_expr
	| KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_CONST_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_REINTERPRET_CAST '<' full_type '>' '(' const_expr_comma ')'
	| KW_SIZEOF '(' full_type ')'
	| KW_SIZEOF formal_const_expr
	| KW_SIZEOF ELLIPSIS '(' name ')'
	| KW_ALIGNOF '(' full_type ')'
	| KW_NEW predefined_type
	| KW_NEW predefined_type '(' optional_const_expr_comma ')'
	| KW_TYPEID '(' full_type ')'
	| KW_TYPEID '(' const_expr ')'
	| '!' const_expr
	| '~' const_expr
	| '-' const_expr
	| '+' const_expr
	| '&' const_expr
	| formal_const_expr '*' const_expr
	| formal_const_expr '/' const_expr
	| formal_const_expr '%' const_expr
	| formal_const_expr '+' const_expr
	| formal_const_expr '-' const_expr
	| formal_const_expr '|' const_expr
	| formal_const_expr '^' const_expr
	| formal_const_expr '&' const_expr
	| formal_const_expr OROR const_expr
	| formal_const_expr ANDAND const_expr
	| formal_const_expr EQCOMPARE const_expr
	| formal_const_expr NECOMPARE const_expr
	| formal_const_expr LECOMPARE const_expr
	| formal_const_expr GECOMPARE const_expr
	| formal_const_expr SPACESHIP const_expr
	| formal_const_expr '<' const_expr
	| formal_const_expr '>' const_expr
	| formal_const_expr LSHIFT const_expr
	| formal_const_expr RSHIFT const_expr
	| formal_const_expr '?' const_expr ':' const_expr
	| formal_const_expr '[' const_expr ']'
	| formal_const_expr '(' const_expr_comma ')'
	| formal_const_expr '(' ')'
	| formal_const_expr '.' name
	| formal_const_expr POINTSAT const_expr
	| '(' const_expr_comma ')'

formal_const_operand::=
	  INTEGER
	| KW_TRUE
	| KW_FALSE
	| CHAR_TOK
	| REAL
	| string_literal
	| CUSTOM_LITERAL
	| IDENTIFIER
	| KW_FINAL
	| KW_OVERRIDE
	| KW_NULLPTR

capture_list::=
	  /*%empty*/
	| '='
	| '&'
	| capture maybe_initialize
	| capture_list ',' capture maybe_initialize

capture::=
	  '&' name
	| '&' name ELLIPSIS
	| name
	| '*' name

class_derivation_name::=
	  name
	| KW_TYPENAME name
	| name ELLIPSIS

name::=
	  IDENTIFIER
	| TYPENAME_IDENTIFIER
	| TYPEPACK_IDENTIFIER
	| KW_FINAL
	| KW_OVERRIDE
	| KW_SIGNED
	| KW_FLOAT
	| KW_PUBLIC
	| KW_PRIVATE
	| KW_STATIC
	| KW_DEFAULT

name_no_final::=
	  IDENTIFIER
	| TYPENAME_IDENTIFIER
	| TYPEPACK_IDENTIFIER
	| KW_OVERRIDE

string_literal::=
	  SIMPLE_STRING
	| STRING_LITERAL
	| string_literal SIMPLE_STRING
	| string_literal STRING_LITERAL

//Tokens

KW_ALIGNAS ::= "alignas"
KW_ALIGNOF ::= "alignof"
KW_ALIGNOF ::= "__alignof"
KW_ALIGNOF ::= "__alignof__"
KW_AUTO ::= "auto"
KW_BEGIN_PUBLISH ::= "__begin_publish"
KW_BLOCKING ::= "__blocking"
KW_BOOL ::= "bool"
KW_CATCH ::= "catch"
KW_CHAR ::= "char"
KW_CHAR8_T ::= "char8_t"
KW_CHAR16_T ::= "char16_t"
KW_CHAR32_T ::= "char32_t"
KW_CLASS ::= "class"
KW_CONST ::= "const"
KW_CONST ::= "__const"
KW_CONST ::= "__const__"
KW_CONSTEVAL ::= "consteval"
KW_CONSTEXPR ::= "constexpr"
KW_CONSTINIT ::= "constinit"
KW_CONST_CAST ::= "const_cast"
KW_DECLTYPE ::= "decltype"
KW_DEFAULT ::= "default"
KW_DELETE ::= "delete"
KW_DOUBLE ::= "double"
KW_DYNAMIC_CAST ::= "dynamic_cast"
KW_ELSE ::= "else"
KW_END_PUBLISH ::= "__end_publish"
KW_ENUM ::= "enum"
KW_EXTERN ::= "extern"
KW_EXTENSION ::= "__extension"
KW_EXPLICIT ::= "explicit"
KW_PUBLISHED ::= "__published"
KW_FALSE ::= "false"
KW_FINAL ::= "final"
KW_FLOAT ::= "float"
KW_FRIEND ::= "friend"
KW_FOR ::= "for"
KW_GOTO ::= "goto"
KW_HAS_VIRTUAL_DESTRUCTOR ::= "__has_virtual_destructor"
KW_IF ::= "if"
KW_INLINE ::= "inline"
KW_INLINE ::= "__inline"
KW_INLINE ::= "__inline__"
KW_INT ::= "int"
KW_IS_ABSTRACT ::= "__is_abstract"
KW_IS_BASE_OF ::= "__is_base_of"
KW_IS_CLASS ::= "__is_class"
KW_IS_CONSTRUCTIBLE ::= "__is_constructible"
KW_IS_CONVERTIBLE_TO ::= "__is_convertible_to"
KW_IS_DESTRUCTIBLE ::= "__is_destructible"
KW_IS_EMPTY ::= "__is_empty"
KW_IS_ENUM ::= "__is_enum"
KW_IS_FINAL ::= "__is_final"
KW_IS_FUNDAMENTAL ::= "__is_fundamental"
KW_IS_POD ::= "__is_pod"
KW_IS_POLYMORPHIC ::= "__is_polymorphic"
KW_IS_STANDARD_LAYOUT ::= "__is_standard_layout"
KW_IS_TRIVIAL ::= "__is_trivial"
KW_IS_TRIVIALLY_COPYABLE ::= "__is_trivially_copyable"
KW_IS_UNION ::= "__is_union"
KW_LONG ::= "long"
KW_MAKE_MAP_KEYS_SEQ ::= "__make_map_keys_seq"
KW_MAKE_MAP_PROPERTY ::= "__make_map_property"
KW_MAKE_PROPERTY ::= "__make_property"
KW_MAKE_PROPERTY2 ::= "__make_property2"
KW_MAKE_SEQ ::= "__make_seq"
KW_MAKE_SEQ_PROPERTY ::= "__make_seq_property"
KW_MUTABLE ::= "mutable"
KW_NAMESPACE ::= "namespace"
KW_NOEXCEPT ::= "noexcept"
KW_NULLPTR ::= "nullptr"
KW_NEW ::= "new"
KW_OPERATOR ::= "operator"
KW_OVERRIDE ::= "override"
KW_PRIVATE ::= "private"
KW_PROTECTED ::= "protected"
KW_PUBLIC ::= "public"
KW_REGISTER ::= "register"
KW_REINTERPRET_CAST ::= "reinterpret_cast"
KW_RETURN ::= "return"
KW_SHORT ::= "short"
KW_SIGNED ::= "signed"
KW_SIZEOF ::= "sizeof"
KW_STATIC ::= "static"
KW_STATIC_ASSERT ::= "static_assert"
KW_STATIC_CAST ::= "static_cast"
KW_STRUCT ::= "struct"
KW_TEMPLATE ::= "template"
KW_THREAD_LOCAL ::= "thread_local"
KW_THROW ::= "throw"
KW_TRUE ::= "true"
KW_TRY ::= "try"
KW_TYPEDEF ::= "typedef"
KW_TYPEID ::= "typeid"
KW_TYPENAME ::= "typename"
KW_UNDERLYING_TYPE ::= "__underlying_type"
KW_UNION ::= "union"
KW_UNSIGNED ::= "unsigned"
KW_USING ::= "using"
KW_VIRTUAL ::= "virtual"
KW_VOID ::= "void"
KW_VOLATILE ::= "volatile"
KW_WCHAR_T ::= "wchar_t"
KW_WHILE ::= "while"

// These are alternative ways to refer to built-in operators.
ANDAND ::= "and"|"&&"
ANDEQUAL ::= "and_eq"|"&="
NECOMPARE ::= "not_eq"|"!="
OROR ::= "or"|"||"
OREQUAL ::= "or_eq"|"|="
XOREQUAL ::= "xor_eq"|"^="

ATTR_LEFT ::= "[["
ATTR_RIGHT ::= "]]"
DIVIDEEQUAL ::= "/="
DOT_STAR ::= ".*"
ELLIPSIS ::= "..."
EQCOMPARE ::= "=="
GECOMPARE ::= ">="
KW_EXPLICIT_LPAREN ::= "(explicit"
KW_NOEXCEPT_LPAREN ::= "(noexcept"
LECOMPARE ::= "<="
LSHIFT ::= "<<"
LSHIFTEQUAL ::= "<<="
MINUSEQUAL ::= "-="
MINUSMINUS ::= "--"
MODEQUAL ::= "%="
PLUSEQUAL ::= "*="
PLUSPLUS ::= "++"
POINTSAT ::= "->"
POINTSAT_STAR ::= "->*"
RSHIFT ::= ">>"
RSHIFTEQUAL ::= ">>"
SCOPE ::= "::"
SPACESHIP ::= "<=>"
TIMESEQUAL ::= "*="
SIMPLE_STRING ::= "__FILE__"|"__LINE__"
@rdb
Copy link
Member

rdb commented Mar 27, 2024

Thanks for sharing, that's pretty cool!

Is there an action point you are suggesting for us here? Is there an advantage for us to replace the right recursion with left recursion as you have done? I'm a bit out of my depth with yacc/bison stuff.

@mingodad
Copy link
Contributor Author

For LALR parser left recursion is preferable for less stack usage see here https://www.gnu.org/software/bison/manual/bison.html#Recursion and for my playground that automatically produce a parse tree left recursion produces shallow trees (easier to visualize without vertical scroll), but In some places when I've tried to replace then a lot of conflicts appeared so I only did in the ones that didn't generated conflicts for now.

After all of the latest fixes and continuing trying to parse sqlite3.c I found one syntax omission:

cppparser-nb -v -D__PANDA_CC__ -D__builtin_va_list=void* -Dwchar_t=pccwchar_t -S/usr/include -S/usr/lib/gcc/x86_64-linux-gnu/9/include sqlite3.c
Predefining __PANDA_CC__ as 
Predefining __builtin_va_list as void*
Predefining wchar_t as pccwchar_t
Reading sqlite3.c
...
 sqlite3.c:35320:24: error: syntax error, unexpected KW_VOLATILE
  static void dekkerMul2(volatile double *x, double y, double yy){
                         ^~~~~~~~
Error in parsing.

And experimenting in the playground (https://mingodad.github.io/parsertl-playground/playground/) I came with this possible fix:

--- <unnamed>
+++ <unnamed>
@@ -294,10 +294,14 @@
 
 optional_attributes :
 	%empty
-	| optional_attributes ATTR_LEFT attribute_specifiers ATTR_RIGHT
-	| optional_attributes ATTR_LEFT KW_USING name ':' /*4R*/ attribute_specifiers ATTR_RIGHT
-	| optional_attributes KW_ALIGNAS '(' /*20L*/ const_expr ')'
-	| optional_attributes KW_ALIGNAS '(' /*20L*/ type_decl ')'
+	| attributes
+	;
+
+attributes :
+	attributes ATTR_LEFT attribute_specifiers ATTR_RIGHT
+	| attributes ATTR_LEFT KW_USING name ':' /*4R*/ attribute_specifiers ATTR_RIGHT
+	| attributes KW_ALIGNAS '(' /*20L*/ const_expr ')'
+	| attributes KW_ALIGNAS '(' /*20L*/ type_decl ')'
 	;
 
 attribute_specifiers :
@@ -553,13 +557,20 @@
 	;
 
 function_parameter :
-	optional_attributes type formal_parameter_identifier maybe_initialize
-	| optional_attributes KW_CONST type formal_parameter_identifier maybe_initialize
-	| optional_attributes KW_CONST KW_REGISTER type formal_parameter_identifier maybe_initialize
-	| optional_attributes type_pack parameter_pack_identifier maybe_initialize
-	| optional_attributes KW_CONST type_pack parameter_pack_identifier maybe_initialize
-	| optional_attributes KW_CONST KW_REGISTER type_pack parameter_pack_identifier maybe_initialize
-	| optional_attributes KW_REGISTER function_parameter
+	optional_attributes type_qualifier_list type formal_parameter_identifier maybe_initialize
+	| optional_attributes type_qualifier_list type_pack parameter_pack_identifier maybe_initialize
+	| function_parameter attributes
+	;
+
+type_qualifier_list :
+    %empty
+	| type_qualifier_list type_qualifier
+	;
+
+type_qualifier :
+	KW_CONST
+	| KW_REGISTER
+	| KW_VOLATILE
 	;
 
 formal_parameter :

The above fix works on the playground and now when I looked at cppBison.yy to try it there I found that it's not using named references (it's using $0-9) and I'll try to convert it to named references first and probably propose it here.

@mingodad
Copy link
Contributor Author

Here is the first working conversion from numeric references to named references using a script and manually fixing it.
Any feedback is welcome !

cppBison-dad.yxx.zip

@rdb
Copy link
Member

rdb commented Mar 27, 2024

I appreciate the effort.

That said, it doesn't seem that this works with the bison 2.3 that ships with XCode. Are named references a more recent feature?

I am a bit reluctant to drop support for bison 2.3. I suppose we could require macOS users to install from homebrew, or have them use the pre-built file, but there have to be some compelling benefits.

@mingodad
Copy link
Contributor Author

Yes that's a known problem, named references need a newer bison 2.5 (2011-05-14).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants