tendra
tendra copied to clipboard
Bad/wrong BNF output by 'sid'
Testing the sid
parser generator output language bnf
we can see that it's outputting every rule separated by '|' even for sequences
, looking through the code and using the bnf-lang
as base I created a ebnf-lang
and could get a better output to use at https://www.bottlecaps.de/rr/ui to view a railroad diagram for the grammar see the patch bellow, for sure it can be made better with the help of the community.
Here is an example of sid/src/examples/mcalc/infix.sid
for the bnf-lang
and for the ebnf-lang
:
bnf-lang:
sid -l bnf infix.sid infix.bnf
cat infix.bnf
<infix-expressions> ::= <newline>
| <infix-expressions> <expression>
| <43>
| <infix-expressions>
<expression> ::= <expression::add-expr>
<expression::add-expr> ::= <expression::mul-expr>
| <46>
<expression::mul-expr> ::= <expression::un-expr>
| <50>
<expression::un-expr> ::= <add>
| <expression::un-expr> <sub>
| <expression::un-expr> <expression::prim-expr>
<expression::prim-expr> ::= <lparen>
| <expression>
| <rparen> <number>
<50> ::= <div>
| <expression::un-expr>
| <38>
| <50> <mod>
| <expression::un-expr>
| <39>
| <50> <mul>
| <expression::un-expr>
| <50>
<38> ::=
<39> ::=
<46> ::= <add>
| <expression::mul-expr>
| <46> <sub>
| <expression::mul-expr>
| <46>
<43> ::= <newline>
ebnf-lang:
sid -l ebnf infix.sid infix.ebnf
cat infix.ebnf
infix_expressions ::= newline infix_expressions
| expression R43 infix_expressions
expression ::= expression__add_expr
expression__add_expr ::= expression__mul_expr R46
expression__mul_expr ::= expression__un_expr R50
expression__un_expr ::= add expression__un_expr
| sub expression__un_expr
| expression__prim_expr
expression__prim_expr ::= lparen expression rparen
| number
R50 ::= div expression__un_expr R38 R50
| mod expression__un_expr R39 R50
| mul expression__un_expr R50
R38 ::=
R39 ::=
R46 ::= add expression__mul_expr R46
| sub expression__mul_expr R46
R43 ::= newline
And here ebnf
with no optimizations:
sid -l ebnf -n infix.sid infix.ebnf
cat infix.ebnf
infix_expressions ::=
| newline infix_expressions
| expression R43 infix_expressions
expression ::= expression__add_expr
expression__add_expr ::= expression__mul_expr
| expression__add_expr add expression__mul_expr
| expression__add_expr sub expression__mul_expr
expression__mul_expr ::= expression__un_expr
| expression__mul_expr mul expression__un_expr
| expression__mul_expr div expression__un_expr R38
| expression__mul_expr mod expression__un_expr R39
expression__un_expr ::= expression__prim_expr
| add expression__un_expr
| sub expression__un_expr
expression__prim_expr ::= number
| lparen expression rparen
R38 ::=
R39 ::=
R43 ::= newline
Author: mingodad <[email protected]> 2021-06-17 20:00:04
Committer: mingodad <[email protected]> 2021-06-17 20:00:04
Parent: fc85a510fc0bf5fa0ffa7c55289eab943b787b92 (IRC migration.)
Child: 0000000000000000000000000000000000000000 (Local uncommitted changes, not checked in to index)
Branch: dad-ebnf
Follows:
Precedes:
Add ebnf output
------------------------------- sid/src/Makefile -------------------------------
index f697c27dc..c8b2c1b56 100644
@@ -7,6 +7,7 @@ PARTS+= src/shared
PARTS+= src/exds
PARTS+= src/adt
PARTS+= src/lang-bnf
+PARTS+= src/lang-ebnf
PARTS+= src/lang-c
PARTS+= src/lang-test
PARTS+= src/rules
-------------------------- sid/src/lang-ebnf/Makefile --------------------------
new file mode 100644
index 000000000..d21389428
@@ -0,0 +1,13 @@
+# $Id$
+
+.include "Makefile.inc"
+
+
+SRCS+= ebnf-main.c
+SRCS+= ebnf-output.c
+SRCS+= ebnf-out-info.c
+
+.include <tendra.obj.mk>
+
+.include <tendra.partial.mk>
+
------------------------ sid/src/lang-ebnf/Makefile.inc ------------------------
new file mode 100644
index 000000000..eebeb4b15
@@ -0,0 +1,9 @@
+# generic Makefile.inc
+
+.if defined(_BASEDIR_RELATIVE)
+_BASEDIR_RELATIVE := ${_BASEDIR_RELATIVE}/..
+.else
+_BASEDIR_RELATIVE = ..
+.endif
+
+.include "../Makefile.inc"
------------------------ sid/src/lang-ebnf/ebnf-main.c ------------------------
new file mode 100644
index 000000000..7fc3f540d
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2002-2011, The TenDRA Project.
+ * Copyright 1997, United Kingdom Secretary of State for Defence.
+ *
+ * See doc/copyright/ for the full copyright terms.
+ */
+
+/*
+ * ebnf-main.c - EBNF language entry points.
+ */
+
+#include <string.h>
+
+#include <shared/bool.h>
+#include <shared/check.h>
+#include <shared/error.h>
+
+#include <exds/dalloc.h>
+#include <exds/cstring-list.h>
+
+#include "ebnf-main.h"
+#include "ebnf-out-info.h"
+#include "ebnf-output.h"
+
+#include "../lang.h"
+#include "../output.h"
+
+static void *
+main_init_ebnf(OutputInfoT *out_info, CStringListT *options)
+{
+ EBNFOutputInfoT *ebnf_out_info;
+ CStringListEntryT *entry;
+
+ ebnf_out_info = ALLOCATE(EBNFOutputInfoT);
+ ebnf_out_info_init(ebnf_out_info, out_info);
+
+ for (entry = cstring_list_head(options); entry;
+ entry = cstring_list_entry_deallocate(entry)) {
+ error(ERR_FATAL, "language '%s' doesn't understand option '%s'"
+ "ebnf", cstring_list_entry_string(entry));
+ }
+
+ return ebnf_out_info;
+}
+
+static void
+main_output_ebnf(void *gclosure, GrammarT *grammar)
+{
+ EBNFOutputInfoT *ebnf_out_info = gclosure;
+
+ out_info_set_current_ostream(ebnf_out_info_info(ebnf_out_info), 0);
+ ebnf_output_parser(ebnf_out_info, grammar);
+}
+
+struct LangListT ebnf_language_list = {
+ "ebnf", 1, 1, main_init_ebnf, NULL, main_output_ebnf
+};
------------------------ sid/src/lang-ebnf/ebnf-main.h ------------------------
new file mode 100644
index 000000000..fdf9fecbf
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2002-2011, The TenDRA Project.
+ *
+ * See doc/copyright/ for the full copyright terms.
+ */
+
+/*
+ * ebnf-main.c - EBNF language entry points.
+ */
+
+#ifndef H_EBNF_MAIN
+#define H_EBNF_MAIN
+
+extern struct LangListT ebnf_language_list;
+
+#endif /* H_EBNF_MAIN */
+
---------------------- sid/src/lang-ebnf/ebnf-out-info.c ----------------------
new file mode 100644
index 000000000..7325616b4
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008-2011, The TenDRA Project.
+ *
+ * See doc/copyright/ for the full copyright terms.
+ */
+
+#include <shared/bool.h>
+#include <shared/check.h>
+
+#include <exds/ostream.h>
+
+#include "ebnf-out-info.h"
+#include "../output.h"
+
+OutputInfoT *
+ebnf_out_info_info(EBNFOutputInfoT *info)
+{
+ return info->info;
+}
+
+OStreamT *
+ebnf_out_info_ostream(EBNFOutputInfoT *info)
+{
+ return out_info_get_current_ostream(info->info);
+}
+
+void
+ebnf_out_info_init(EBNFOutputInfoT *info, OutputInfoT *out_info)
+{
+ info->info = out_info;
+}
+
---------------------- sid/src/lang-ebnf/ebnf-out-info.h ----------------------
new file mode 100644
index 000000000..3a4b8f275
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008-2011, The TenDRA Project.
+ *
+ * See doc/copyright/ for the full copyright terms.
+ */
+
+#ifndef H_EBNF_OUT_INFO
+#define H_EBNF_OUT_INFO
+
+#include <exds/ostream.h>
+
+#include "../output.h"
+
+typedef struct EBNFOutputInfoT {
+ OutputInfoT *info;
+} EBNFOutputInfoT;
+
+OutputInfoT *ebnf_out_info_info(EBNFOutputInfoT *info);
+OStreamT *ebnf_out_info_ostream(EBNFOutputInfoT *info);
+void ebnf_out_info_init(EBNFOutputInfoT *, OutputInfoT *);
+
+#endif /* !defined (H_EBNF_OUT_INFO) */
+
----------------------- sid/src/lang-ebnf/ebnf-output.c -----------------------
new file mode 100644
index 000000000..e9a15a3ba
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2008-2011, The TenDRA Project.
+ *
+ * See doc/copyright/ for the full copyright terms.
+ */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <shared/bool.h>
+#include <shared/check.h>
+
+#include <exds/dstring.h>
+
+#include "ebnf-output.h"
+#include "ebnf-out-info.h"
+#include "../grammar.h"
+#include "../adt/entry-list.h"
+#include "../adt/rule.h"
+#include "../adt/key.h"
+
+static void
+output_ebnf_key(EBNFOutputInfoT *info, KeyT *key)
+{
+ OStreamT *ostream = ebnf_out_info_ostream(info);
+ size_t idx;
+
+ //write_char(ostream, '<');
+ //write_key(ostream, key);
+ //write_char(ostream, '>');
+ switch (key->type) EXHAUSTIVE {
+ case KT_STRING:
+ //write_nstring(ostream, &key->string);
+
+ for (idx = 0; idx < key->string.length; ++idx) {
+ char ch = key->string.contents[idx];
+ switch(ch) {
+ case ':':
+ case ' ':
+ case '-': ch = '_';
+ }
+ write_char(ostream, ch);
+ }
+ break;
+
+ case KT_NUMERIC:
+ //write_unsigned(ostream, key->number);
+ IGNORE fprintf(ostream->file, "R%u", key->number);
+ //OSTREAM_WRITE_ERROR_CHECK(ostream);
+ break;
+ }
+}
+
+static int
+ebnf_output_item(EBNFOutputInfoT *info, ItemT *item, int i)
+{
+ OStreamT *ostream = ebnf_out_info_ostream(info);
+ EntryT *entry = item_entry(item);
+
+ switch (item_type(item)) {
+ case ET_RULE:
+ case ET_BASIC:
+ if (i != 0) {
+ write_newline(ostream);
+ write_tab(ostream);
+ write_cstring(ostream, "| ");
+ }
+
+ output_ebnf_key(info, entry_key(entry));
+ return 1;
+
+ default:
+ /* Other entries are irrelevant to EBNF */
+ return 0;
+ }
+}
+
+static void
+ebnf_output_alt(EBNFOutputInfoT *info, AltT *alt, int i)
+{
+ OStreamT *ostream = ebnf_out_info_ostream(info);
+
+ ItemT *item;
+
+ for (item = alt_item_head(alt); item; item = item_next(item)) {
+ if (!ebnf_output_item(info, item, i)) {
+ continue;
+ }
+
+ write_char(ostream, ' ');
+ i = 0;
+ }
+}
+
+static void
+ebnf_output_rule(EBNFOutputInfoT *info, RuleT *rule)
+{
+ OStreamT *ostream = ebnf_out_info_ostream(info);
+ KeyT *key = entry_key(rule_entry(rule));
+
+ AltT *alt;
+ int i = 0;
+
+ output_ebnf_key(info, key);
+ write_cstring(ostream, " ::= ");
+
+ for (alt = rule->alt_head; alt; alt = alt_next(alt)) {
+ ebnf_output_alt(info, alt, i);
+ i++;
+ }
+
+ if (rule_has_empty_alt(rule)) {
+ write_newline(ostream);
+ write_tab(ostream);
+ //write_cstring(ostream, "| \"\"");
+ write_cstring(ostream, "|");
+ }
+
+ write_newline(ostream);
+ write_newline(ostream);
+}
+
+static void
+ebnf_output_entry(EntryT *entry, void *gclosure)
+{
+ EBNFOutputInfoT *info = gclosure;
+
+ if (!entry_is_rule(entry)) {
+ return;
+ }
+
+ ebnf_output_rule(info, entry_get_rule(entry));
+}
+
+extern void
+ebnf_output_parser(EBNFOutputInfoT *info, GrammarT *grammar)
+{
+ TableT *table = grammar_table(grammar);
+ EntryListT *entry_list = grammar_entry_list(grammar);
+
+ table_untrace(table);
+ entry_list_iter_table(entry_list, false, ebnf_output_entry, info);
+}
+
----------------------- sid/src/lang-ebnf/ebnf-output.h -----------------------
new file mode 100644
index 000000000..62f79d057
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2008-2011, The TenDRA Project.
+ *
+ * See doc/copyright/ for the full copyright terms.
+ */
+
+#ifndef H_EBNF_OUTPUT
+#define H_EBNF_OUTPUT
+
+#include "ebnf-out-info.h"
+#include "../grammar.h"
+
+extern void ebnf_output_parser(EBNFOutputInfoT *info, GrammarT *);
+
+#endif /* !defined (H_EBNF_OUTPUT) */
+
-------------------------------- sid/src/main.c --------------------------------
index 13f6276cb..ad2c99697 100644
@@ -78,12 +78,13 @@
#include "lang-c/c-main.h"
#include "lang-test/test-main.h"
#include "lang-bnf/bnf-main.h"
+#include "lang-ebnf/ebnf-main.h"
#define USAGE "\
usage:[option ...] in-file ... out-file ...\n\
where option is one of:\n"
#define PROGNAME "sid"
-#define LANGUAGES "ansi-c, pre-ansi-c, test, bnf"
+#define LANGUAGES "ansi-c, pre-ansi-c, test, bnf, ebnf"
#define VERSION "version 1.12 (" LANGUAGES ")"
#define RELEASE "tendra.org"
@@ -104,6 +105,7 @@ main_handle_phase_all(bool enable)
static bool main_did_one_off = false;
static bool main_did_other = false;
+static bool no_optmization = false;
static OutputInfoT *main_info_closure;
@@ -136,7 +138,7 @@ static PhaseListT main_phase_list[] = {
TODO: permit unused functions (e.g. main_input_test) to be NULL
*/
-static LangListT *main_language_list[6];
+static LangListT *main_language_list[7];
/*
main_langauge points into main_language_list to the language that
@@ -200,6 +202,17 @@ main_handle_factor_limit(char *option, ArgUsageT *usage, void *gclosure,
rule_set_factor_limit(limit);
}
+static void
+main_handle_no_optmization(char *option, ArgUsageT *usage, void *gclosure)
+{
+
+ UNUSED(option);
+ UNUSED(usage);
+ UNUSED(gclosure);
+ no_optmization = true;
+ main_did_one_off = true;
+}
+
static void
main_handle_inlining(char *option, ArgUsageT *usage, void *gclosure,
char *inline_str)
@@ -317,6 +330,9 @@ static EStringDataT main_description_strings[] = {
} }, { {
"description of switch",
" OPTION\n\tPass OPTION to language specific option parser."
+ } }, { {
+ "description of no-optmization",
+ " OPTION\n\tDisable grammar optmizations."
} }, { {
"description of version",
"\n\tDisplay the version number on the standard error."
@@ -354,6 +370,10 @@ static ArgListT main_arglist[] = {
"switch", 's', AT_FOLLOWING,
(ArgProcP) main_handle_switch, NULL,
{ "description of switch" }
+ }, {
+ "no-optmization", 'n', AT_EMPTY,
+ (ArgProcP) main_handle_no_optmization, NULL,
+ { "description of no-optmization" }
}, {
"version", 'v', AT_EMPTY,
(ArgProcP) main_handle_version, NULL,
@@ -483,7 +503,7 @@ main_1(OutputInfoT *out_info, OStreamT *dstream)
/* The internal representation (`grammar') is now complete. */
/* Optimizations (see `grammar.h' for details): */
- {
+ if(!no_optmization) {
main_dump_grammar(dstream, &grammar, "Original grammar:");
grammar_remove_left_recursion(&grammar);
@@ -532,6 +552,7 @@ main(int argc, char **argv)
main_language_list[3] = &c_language_list_pre_iso;
main_language_list[4] = &test_language_list;
main_language_list[5] = &bnf_language_list;
+ main_language_list[6] = &ebnf_language_list;
/* Default to ANSI C. May be overridden by the `-l' flag. */
main_language = main_language_list[0];
And here is the tdfc2/src/cpp/syntax/syntax.sid
ebnf
output that can be viewed at https://www.bottlecaps.de/rr/ui , copy the EBNF
bellow and paste it at https://www.bottlecaps.de/rr/ui in the tab Edit Grammar
then switch to the tab View Diagram
.
translation_unit ::= eof
| linkage_specification declaration_seq_opt eof
| template_declaration declaration_seq_opt eof
| R1255 declaration_seq_opt eof
| R1256 declaration_seq_opt eof
| decl_specifier R920 R1253 declaration_seq_opt eof
linkage_specification ::= extern string_literal R1067
string_literal ::= string_exp
| wstring_exp
R1067 ::= linkage_specification
| open_brace declaration_seq_opt close_brace
| template_declaration
| R1255
| declaration_other
| decl_specifier R920 R1253
open_brace ::= open_brace_1
declaration_seq_opt ::= linkage_specification declaration_seq_opt
| template_declaration declaration_seq_opt
| R1255 declaration_seq_opt
| R1256 declaration_seq_opt
| decl_specifier R920 R1253 declaration_seq_opt
|
template_declaration ::= export_opt template declaration
export_opt ::= export
declaration ::= linkage_specification
| template_declaration
| R1255
| declaration_other
| decl_specifier R920 R1253
R1255 ::= semicolon
| declarator R1078
declarator ::= declarator_aux
declarator_aux ::= direct_declarator
| ptr_operator declarator_aux
direct_declarator ::= open_round declarator_aux close_round R1178
| declarator_id R1178
R1178 ::= declarator_tail R1178
declarator_tail ::= open_round R950
| weak open_round parameter_tail
| open_square R956 close_square
R950 ::= parameter_tail
parameter_tail ::= parameter_declaration_clause close_round cv_qualifier_seq_opt exception_specification_opt
parameter_declaration_clause ::= parameter_declaration_list
parameter_declaration_list ::= ellipsis
| parameter_declaration R979
parameter_declaration ::= decl_specifier_seq parameter_declarator_opt R975
decl_specifier_seq ::= decl_specifier R913
decl_specifier ::= type_specifier
| R910
type_specifier ::= enum R1326
| typename any_nested_name_opt any_class_name
| class_key R1325
| cv_qualifier
| simple_type_specifier
R1326 ::= any_nested_name_opt any_class_name
| R872 open_brace R873 close_brace
any_nested_name_opt ::= any_nested_name
any_nested_name ::= colon_colon
| nonempty_nested_name
nonempty_nested_name ::= full_name
| nested_name
any_class_name ::= template_type
| any_identifier
any_identifier ::= identifier
| namespace_name
| statement_name
| type_name
R872 ::= any_nested_name_opt any_class_name
R873 ::= enumerator_list
|
enumerator_list ::= enumerator_definition R870
enumerator_definition ::= any_identifier member_specifier_opt
member_specifier_opt ::= assign constant_expression
constant_expression ::= conditional_expression
conditional_expression ::= logical_or_expression R1263
logical_or_expression ::= logical_and_expression R1193
logical_and_expression ::= inclusive_or_expression R1197
inclusive_or_expression ::= exclusive_or_expression R1201
exclusive_or_expression ::= and_expression R1205
and_expression ::= maxmin_expression R1209
maxmin_expression ::= equality_expression R1213
equality_expression ::= relational_expression R1217
relational_expression ::= shift_expression R1221
shift_expression ::= additive_expression R1225
additive_expression ::= multiplicative_expression R1229
multiplicative_expression ::= pm_expression R1233
pm_expression ::= cast_expression R1237
cast_expression ::= alignof sizeof_expression
| colon_colon R1285
| complex_exp R1241
| complex_type open_round expression_list_opt close_round R1241
| const_cast cast_operand R1241
| discard cast_expression
| dynamic_cast cast_operand R1241
| ellipsis_exp R1241
| full_name R1268
| lit cast_expression
| minus_minus cast_expression
| nested_name R1267
| open_round R1287
| plus_plus cast_expression
| reinterpret_cast cast_operand R1241
| sizeof sizeof_expression
| star cast_expression
| static_cast cast_operand R1241
| this R1241
| typeid typeid_expression R1241
| vtable typeid_expression R1241
| and cast_expression
| base_type_specifier open_round expression_list_opt close_round R1241
| literal R1241
| not cast_expression
| unqualified_id R1241
| unqualified_type open_round expression_list_opt close_round R1241
| R1431
| unary_operator cast_expression
sizeof_expression ::= R596
R596 ::= alignof sizeof_expression
| colon_colon R1285
| complex_exp R1241
| complex_type open_round expression_list_opt close_round R1241
| const_cast cast_operand R1241
| dynamic_cast cast_operand R1241
| ellipsis_exp R1241
| full_name R1268
| minus_minus cast_expression
| nested_name R1267
| open_round R1430
| plus_plus cast_expression
| reinterpret_cast cast_operand R1241
| sizeof sizeof_expression
| star cast_expression
| static_cast cast_operand R1241
| this R1241
| typeid typeid_expression R1241
| vtable typeid_expression R1241
| and cast_expression
| base_type_specifier open_round expression_list_opt close_round R1241
| literal R1241
| not cast_expression
| unqualified_id R1241
| unqualified_type open_round expression_list_opt close_round R1241
| R1431
| unary_operator cast_expression
R1285 ::= R1269
| R1431
R1269 ::= any_type_name open_round expression_list_opt close_round R1241
| template_opt nested_id R1241
any_type_name ::= template_type
| type_name
expression_list_opt ::= expression_list
expression_list ::= assignment_expression R501
assignment_expression ::= logical_or_expression R1265
| throw_expression
R1265 ::= assign assignment_expression
| R1263
| assignment_operator assignment_expression
R1263 ::= question expression colon assignment_expression
expression ::= assignment_expression R1290
| flow_expression comma_expression_tail
| inset_flow_expression comma_expression_tail
R1290 ::= comma comma_expression_tail
comma_expression_tail ::= assignment_expression R1291
| flow_expression comma_expression_tail
| inset_flow_expression comma_expression_tail
R1291 ::= comma comma_expression_tail
flow_expression ::= set open_round expression close_round
| unused open_round expression close_round
inset_flow_expression ::= inset_start R1292
R1292 ::= set expression inset_end
| unused expression inset_end
assignment_operator ::= div_eq
| lshift_eq
| minus_eq
| plus_eq
| rem_eq
| rshift_eq
| star_eq
| and_eq
| or_eq
| xor_eq
and_eq ::= and_eq_1
or_eq ::= or_eq_1
xor_eq ::= xor_eq_1
throw_expression ::= throw R639
R639 ::= assignment_expression
| type_id
type_id ::= type_specifier_seq abstract_declarator_opt
type_specifier_seq ::= type_specifier R880
R880 ::= type_specifier_seq
abstract_declarator_opt ::= abstract_declarator_aux
abstract_declarator_aux ::= direct_abstract_declarator
| ptr_operator R1383
direct_abstract_declarator ::= open_round R1384
| weak open_round parameter_tail R1140
| open_square R956 close_square R1140
R1384 ::= abstract_declarator_aux close_round R1140
| parameter_tail R1140
R1140 ::= abstract_declarator_tail R1140
abstract_declarator_tail ::= open_round parameter_tail
| weak open_round parameter_tail
| open_square R956 close_square
open_square ::= open_square_1
R956 ::= constant_expression
close_square ::= close_square_1
ptr_operator ::= full_name_star cv_qualifier_seq_opt
| nested_name_star cv_qualifier_seq_opt
| star cv_qualifier_seq_opt
| and cv_qualifier_seq_opt
cv_qualifier_seq_opt ::= cv_qualifier_seq
cv_qualifier_seq ::= cv_qualifier R789
cv_qualifier ::= const
| volatile
R789 ::= cv_qualifier_seq
and ::= and_1
R1383 ::= abstract_declarator_aux
R501 ::= comma expression_list
R1241 ::= minus_minus R1241
| open_round expression_list_opt close_round R1241
| plus_plus R1241
| open_square expression close_square R1241
| arrow template_opt field_id_expression R1241
| dot template_opt field_id_expression R1241
template_opt ::=
| template
field_id_expression ::= colon_colon R1314
| full_name R1318
| nested_name R1316
| base_type_specifier colon_colon compl pseudo_destr_suffix
| compl pseudo_destr_suffix
| nested_id
| unqualified_type R1313
R1314 ::= any_type_name R1399
| R1395
R1399 ::= colon_colon compl pseudo_destr_suffix
compl ::= compl_1
pseudo_destr_suffix ::= any_class_name
| base_type_specifier
base_type_specifier ::= bool
| bottom
| char
| double
| float
| int
| long
| ptrdiff_t
| short
| signed
| size_t
| unsigned
| void
| wchar_t
R1395 ::= template_opt nested_id
| compl pseudo_destr_suffix
nested_id ::= destructor_name
| identifier
| namespace_name
| template_id
| operator_id
operator_id ::= operator R460
R460 ::= operator_name
| type_specifier R888 conversion_declarator_opt
operator_name ::= delete R1322
| new R1321
| open_round close_round_x
| question colon_x
| open_square close_square_x
| R1320
R1322 ::=
| open_square close_square_x
close_square_x ::= close_square
R1321 ::=
| open_square close_square_x
close_round_x ::= close_round
colon_x ::= colon
R1320 ::= R454
| R455
R454 ::= abs
| arrow
| arrow_star
| assign
| comma
| div
| div_eq
| eq
| greater
| greater_eq
| less
| less_eq
| lshift
| lshift_eq
| max
| min
| minus
| minus_eq
| minus_minus
| plus
| plus_eq
| plus_plus
| rem
| rem_eq
| rshift
| rshift_eq
| star
| star_eq
| and
| and_eq
| compl
| logical_and
| logical_or
| not
| not_eq
| or
| or_eq
| xor
| xor_eq
logical_and ::= logical_and_1
logical_or ::= logical_or_1
not ::= not_1
not_eq ::= not_eq_1
or ::= or_1
xor ::= xor_1
R455 ::= alignof
| colon
| colon_colon
| dot
| dot_star
| sizeof
| typeid
| vtable
R888 ::=
| type_specifier R888
conversion_declarator_opt ::=
| ptr_operator conversion_declarator_opt
R1318 ::= any_type_name R1406
| template_opt nested_id
| compl pseudo_destr_suffix
R1406 ::= colon_colon compl pseudo_destr_suffix
R1316 ::= any_type_name R1403
| template_opt nested_id
| compl pseudo_destr_suffix
R1403 ::= colon_colon compl pseudo_destr_suffix
unqualified_type ::= any_type_name
R1313 ::= colon_colon compl pseudo_destr_suffix
R1431 ::= new new_place_and_type new_initialiser_opt
| delete_operator cast_expression
new_place_and_type ::= open_round R574
| new_type_id
R574 ::= expression_list close_round R575
| type_id close_round
R575 ::= open_round type_id close_round
| new_type_id
new_type_id ::= type_specifier_seq new_declarator_opt
new_declarator_opt ::= direct_new_declarator
| ptr_operator new_declarator_opt
direct_new_declarator ::= open_square expression close_square R1150
R1150 ::= open_square constant_expression close_square R1150
new_initialiser_opt ::= open_round expression_list_opt close_round
delete_operator ::= delete R1432
R1432 ::= open_square R1433
R1433 ::= close_square
| expression close_square
cast_operand ::= less type_id greater open_round expression close_round
R1268 ::= any_type_name open_round expression_list_opt close_round R1241
| template_opt nested_id R1241
R1267 ::= any_type_name open_round expression_list_opt close_round R1241
| template_opt nested_id R1241
R1430 ::= expression close_round R1241
| type_id close_round
typeid_expression ::= open_round R558
R558 ::= expression close_round
| type_id close_round
literal ::= boolean_literal
| character_literal
| floating_literal
| integer_literal
| string_literal
boolean_literal ::= false
| true
character_literal ::= char_exp
| wchar_exp
floating_literal ::= floating_exp
integer_literal ::= integer_exp
unqualified_id ::= destructor_name
| identifier
| namespace_name
| template_id
| operator_id
unary_operator ::= abs
| minus
| plus
| compl
R1287 ::= expression close_round R1241
| type_id close_round cast_expression
R1237 ::= arrow_star cast_expression R1237
| dot_star cast_expression R1237
R1233 ::= div pm_expression R1233
| rem pm_expression R1233
| star pm_expression R1233
R1229 ::= minus multiplicative_expression R1229
| plus multiplicative_expression R1229
R1225 ::= lshift additive_expression R1225
| rshift additive_expression R1225
R1221 ::= relational_operator shift_expression R1221
relational_operator ::= greater
| greater_eq
| less
| less_eq
R1217 ::= equality_operator relational_expression R1217
equality_operator ::= eq
| not_eq
R1213 ::= maxmin_operator equality_expression R1213
maxmin_operator ::= max
| min
R1209 ::= and maxmin_expression R1209
R1205 ::= xor and_expression R1205
R1201 ::= or exclusive_or_expression R1201
R1197 ::= logical_and inclusive_or_expression R1197
R1193 ::= logical_or logical_and_expression R1193
R870 ::= comma R1390
|
R1390 ::= comma enumerator_list
| enumerator_list
close_brace ::= close_brace_1
class_key ::= class
| struct
| union
R1325 ::= any_nested_name_opt any_class_name
| R872 base_clause_opt open_brace member_specification_opt close_brace
base_clause_opt ::= colon R1327
R1327 ::= base_specifier_list
base_specifier_list ::= base_specifier R849
base_specifier ::= R846 any_nested_name_opt any_class_name
R846 ::= virtual R1329
| access_specifier R1328
R1329 ::= access_specifier
access_specifier ::= private
| protected
| public
R1328 ::= virtual
R849 ::= comma base_specifier_list
|
member_specification_opt ::= access_specifier colon member_specification_opt
| template_member_decl member_specification_opt
| member_declarator R1095 member_specification_opt
| R1341 member_specification_opt
| semicolon member_specification_opt
| decl_specifier R920 R1340 member_specification_opt
|
template_member_decl ::= export_opt template member_declaration
member_declaration ::= template_member_decl
| member_declarator R1095
| using_declaration
| semicolon
| decl_specifier R920 R1340
member_declarator ::= colon_colon R1347 R1178 member_specifier_opt
| destructor_name R1178 member_specifier_opt
| full_name R1346 R1178 member_specifier_opt
| identifier R1366
| namespace_name R1366
| nested_name R1345 R1178 member_specifier_opt
| open_round declarator_aux close_round R1178 member_specifier_opt
| statement_name R1366
| template_id R1178 member_specifier_opt
| template_type R1178 member_specifier_opt
| type_name R1369
| operator_id R1178 member_specifier_opt
| ptr_operator declarator_aux member_specifier_opt
| colon constant_expression
R1347 ::= statement_name
| any_type_name
| template_opt nested_id
R1346 ::= statement_name
| any_type_name
| template_opt nested_id
R1366 ::= colon constant_expression
| R1178 member_specifier_opt
R1345 ::= statement_name
| any_type_name
| template_opt nested_id
R1369 ::= R1178 member_specifier_opt
| colon constant_expression
R1095 ::= comma member_declarator_list semicolon
| semicolon
member_declarator_list ::= member_declarator R1091
R1091 ::= comma member_declarator_list
|
using_declaration ::= using R1258
R1258 ::= typename any_nested_name_opt any_class_name semicolon_x
| declarator_id semicolon_x
semicolon_x ::= semicolon
declarator_id ::= colon_colon R1347
| full_name R1346
| nested_name R1345
| statement_name
| unqualified_id
| unqualified_type
R920 ::=
| decl_specifier R920
R1340 ::= semicolon
| member_declarator R1095
R1341 ::= member_cond
| using_declaration
member_cond ::= member_cond_head R839 hash_endif
member_cond_head ::= hash_if member_cond_body R1168
member_cond_body ::= open_brace member_specification_opt close_brace
R1168 ::= hash_elif member_cond_body R1168
R839 ::= hash_else member_cond_body
|
simple_type_specifier ::= complex_type
| any_qualified_type
| base_type_specifier
| unqualified_type
any_qualified_type ::= full_qualified_type
| qualified_type
| top_qualified_type
full_qualified_type ::= full_name any_type_name
qualified_type ::= nested_name any_type_name
top_qualified_type ::= colon_colon any_type_name
R910 ::= friend
| typedef
| function_specifier
| storage_class_specifier
function_specifier ::= explicit
| inline
| overload
| virtual
storage_class_specifier ::= auto
| extern
| mutable
| register
| static
R913 ::= decl_specifier_seq
parameter_declarator_opt ::= open_round R1372
| weak open_round parameter_tail R1162
| open_square R956 close_square R1162
| ptr_operator parameter_declarator_aux_opt
| declarator_id R1162
R1372 ::= open_round R1372 close_round R1162
| weak open_round parameter_tail R1162 close_round R1162
| open_square R956 close_square R1162 close_round R1162
| ptr_operator parameter_declarator_aux_opt close_round R1162
| parameter_tail R1162
| declarator_id R1162 close_round R1162
R1162 ::= abstract_declarator_tail R1162
parameter_declarator_aux_opt ::= open_round R1372
| weak open_round parameter_tail R1162
| open_square R956 close_square R1162
| ptr_operator parameter_declarator_aux_opt
| declarator_id R1162
R975 ::= assign R976
R976 ::= initialiser_expression
initialiser_expression ::= assignment_expression
R979 ::= comma parameter_declaration_list
| ellipsis
exception_specification_opt ::= throw open_round R1109 close_round
R1109 ::= ellipsis
| type_id_list
type_id_list ::= type_id R1108
R1108 ::= comma R1385
R1385 ::= type_id_list
R1078 ::= assign initialiser_clause R1079 semicolon
| R1079 semicolon
| function_definition_body
| initialiser_exp_list close_round R1079 semicolon
initialiser_clause ::= initialiser_expression
| open_brace R1004 close_brace
R1004 ::= initialiser_list
initialiser_list ::= initialiser_clause R1003
R1003 ::= comma R1004
R1079 ::= comma init_declarator_list
|
init_declarator_list ::= init_declarator R1013
init_declarator ::= declarator initialiser_opt
initialiser_opt ::= assign initialiser_clause
| initialiser_exp_list close_round
initialiser_exp_list ::= initialiser_expression R1006
R1006 ::= comma initialiser_exp_list
R1013 ::= comma init_declarator_list
|
function_definition_body ::= R1028
R1028 ::= function_body
| function_try_block
function_body ::= ctor_initialiser_opt open_brace statement_seq_opt close_brace
ctor_initialiser_opt ::= colon R1023
R1023 ::= mem_initialiser_list
mem_initialiser_list ::= mem_initialiser R1021
mem_initialiser ::= open_round expression_list_opt close_round
| any_nested_name_opt any_class_name open_round expression_list_opt close_round
R1021 ::= comma mem_initialiser_list
|
statement_seq_opt ::= alignof sizeof_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| colon_colon R1476 statement_seq_opt
| complex_exp R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| complex_stmt statement_seq_opt
| complex_type open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| const_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| destructor_name R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| discard cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| dynamic_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| ellipsis_exp R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| full_name R1475 statement_seq_opt
| identifier R1471 statement_seq_opt
| inset_start R1440 statement_seq_opt
| lit cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| minus_minus cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| namespace_name R1471 statement_seq_opt
| nested_name R1474 statement_seq_opt
| open_round R1287 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| plus_plus cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| reinterpret_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| semicolon statement_seq_opt
| sizeof sizeof_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| star cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| statement_name R1473 statement_seq_opt
| static_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| template_id R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| template_type open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| this R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| type_name R1469 statement_seq_opt
| typeid typeid_expression R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| vtable typeid_expression R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| and cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| base_type_specifier open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| compound_statement statement_seq_opt
| control_statement statement_seq_opt
| fall_check R1441 statement_seq_opt
| flow_expression R1437 semicolon statement_seq_opt
| iteration_statement statement_seq_opt
| jump_statement statement_seq_opt
| literal R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| not cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| operator_id R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| selection_statement statement_seq_opt
| throw_expression R1290 semicolon statement_seq_opt
| try_block statement_seq_opt
| R1431 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| unary_operator cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon statement_seq_opt
| declaration_nonempty statement_seq_opt
R1476 ::= statement_name
| R1285 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
R1475 ::= statement_name
| R1268 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
R1471 ::= R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| colon statement
statement ::= alignof sizeof_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| colon_colon R1476
| complex_exp R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| complex_stmt
| complex_type open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| const_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| destructor_name R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| discard cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| dynamic_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| ellipsis_exp R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| full_name R1475
| identifier R1471
| inset_start R1440
| lit cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| minus_minus cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| namespace_name R1471
| nested_name R1474
| open_round R1287 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| plus_plus cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| reinterpret_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| semicolon
| sizeof sizeof_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| star cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| statement_name R1473
| static_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| template_id R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| template_type open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| this R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| type_name R1469
| typeid typeid_expression R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| vtable typeid_expression R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| and cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| base_type_specifier open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| compound_statement
| control_statement
| fall_check R1441
| flow_expression R1437 semicolon
| iteration_statement
| jump_statement
| literal R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| not cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| operator_id R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| selection_statement
| throw_expression R1290 semicolon
| try_block
| R1431 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| unary_operator cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| declaration_nonempty
R1440 ::= set expression R1600
| unused expression R1600
R1600 ::= inset_end comma_expression_tail semicolon
| semicolon inset_end
R1474 ::= statement_name
| R1267 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
R1473 ::=
| colon statement
R1469 ::= open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| colon statement
compound_statement ::= open_brace statement_seq_opt close_brace
control_statement ::= reachable statement
| unreachable statement
fall_check ::= fall R1604
|
R1604 ::= semicolon
R1441 ::= case constant_expression colon statement
| default colon statement
R1437 ::= comma_expression_tail
iteration_statement ::= do scoped_statement while open_round expression close_round semicolon_x
| for open_round for_init_statement for_cond_statement for_end_statement close_round scoped_statement
| while open_round condition close_round scoped_statement
scoped_statement ::= alignof sizeof_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| colon_colon R1476
| complex_exp R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| complex_stmt
| complex_type open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| const_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| destructor_name R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| discard cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| dynamic_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| ellipsis_exp R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| full_name R1475
| identifier R1471
| inset_start R1440
| lit cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| minus_minus cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| namespace_name R1471
| nested_name R1474
| open_round R1287 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| plus_plus cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| reinterpret_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| semicolon
| sizeof sizeof_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| star cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| statement_name R1473
| static_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| template_id R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| template_type open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| this R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| type_name R1469
| typeid typeid_expression R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| vtable typeid_expression R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| and cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| base_type_specifier open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| control_statement
| fall_check R1441
| flow_expression R1437 semicolon
| iteration_statement
| jump_statement
| literal R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| not cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| open_brace statement_seq_opt close_brace
| operator_id R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| selection_statement
| throw_expression R1290 semicolon
| try_block
| R1431 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| unary_operator cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| declaration_nonempty
jump_statement ::= break semicolon_x
| continue semicolon_x
| goto jump_label semicolon_x
| return R756 semicolon_x
jump_label ::= case constant_expression
| default
| any_identifier
R756 ::= expression
selection_statement ::= if open_round_x condition close_round scoped_statement R720
| switch open_round condition close_round R724 scoped_statement
| target_condition
open_round_x ::= open_round
condition ::= expression
| condition_declarator assign initialiser_expression
condition_declarator ::= type_specifier R888 declarator
R720 ::= else scoped_statement
R724 ::= exhaustive
target_condition ::= target_condition_head R703 hash_endif
target_condition_head ::= hash_if compound_statement R1189
R1189 ::= hash_elif compound_statement R1189
R703 ::= hash_else compound_statement
try_block ::= try compound_statement handler_seq_opt
handler_seq_opt ::= handler handler_seq_opt
|
handler ::= catch open_round exception_declaration close_round open_brace statement_seq_opt close_brace
exception_declaration ::= ellipsis_aux
| type_specifier R888 parameter_declarator_opt
ellipsis_aux ::= ellipsis
| ellipsis_exp
declaration_nonempty ::= linkage_specification
| template_declaration
| declarator R1078
| declaration_other
| decl_specifier R920 R1253
declaration_other ::= namespace R1259
| using R1260
| asm_definition
R1259 ::= any_identifier R1434
| open_brace declaration_seq_opt close_brace
R1434 ::= assign any_nested_name_opt any_class_name semicolon_x
| open_brace declaration_seq_opt close_brace
R1260 ::= namespace any_nested_name_opt any_class_name semicolon_x
| R1258
asm_definition ::= asm open_round string_literal R501 close_round semicolon_x
R1253 ::= semicolon
| declarator R1078
for_init_statement ::= expression_statement
| declaration_basic
expression_statement ::= inset_start R1440
| semicolon
| assignment_expression R1290 semicolon
| flow_expression R1437 semicolon
declaration_basic ::= declarator R1078
| decl_specifier R920 R1253
for_cond_statement ::= semicolon
| expression semicolon
| condition_declarator assign initialiser_expression semicolon
for_end_statement ::= expression
function_try_block ::= try function_body handler_seq_opt
R1256 ::= declaration_cond
| declaration_other
declaration_cond ::= hash_pragma
| declaration_cond_head R1034 hash_endif
declaration_cond_head ::= hash_if declaration_cond_body R1146
declaration_cond_body ::= open_brace declaration_seq_opt close_brace
R1146 ::= hash_elif declaration_cond_body R1146
R1034 ::= hash_else declaration_cond_body
|
expression_entry ::= assignment_expression
function_definition_entry ::= function_definition_body
declaration_entry ::= declarator R1078
| decl_specifier R920 R1253
id_entry ::= any_qualified_id
any_qualified_id ::= colon_colon R1609
| full_name R1608
| nested_name R1607
| statement_name
| unqualified_id
| unqualified_type
R1609 ::= statement_name
| any_type_name
| template_opt nested_id
R1608 ::= statement_name
| any_type_name
| template_opt nested_id
R1607 ::= statement_name
| any_type_name
| template_opt nested_id
type_id_entry ::= token_type_id
token_type_id ::= type_specifier_seq abstract_declarator_opt
member_type_id ::= type_specifier_seq R987
R987 ::= rem constant_expression
| abstract_declarator_opt
parameter_entry ::= parameter_declaration
statement_entry ::= alignof sizeof_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| colon_colon R1476
| complex_exp R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| complex_stmt
| complex_type open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| const_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| destructor_name R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| discard cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| dynamic_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| ellipsis_exp R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| full_name R1475
| identifier R1471
| inset_start R1440
| lit cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| minus_minus cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| namespace_name R1471
| nested_name R1474
| open_round R1287 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| plus_plus cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| reinterpret_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| semicolon
| sizeof sizeof_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| star cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| statement_name R1473
| static_cast cast_operand R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| template_id R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| template_type open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| this R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| type_name R1469
| typeid typeid_expression R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| vtable typeid_expression R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| and cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| base_type_specifier open_round expression_list_opt close_round R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| compound_statement
| control_statement
| fall_check R1441
| flow_expression R1437 semicolon
| iteration_statement
| jump_statement
| literal R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| not cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| operator_id R1241 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| selection_statement
| throw_expression R1290 semicolon
| try_block
| R1431 R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| unary_operator cast_expression R1237 R1233 R1229 R1225 R1221 R1217 R1213 R1209 R1205 R1201 R1197 R1193 R1265 R1290 semicolon
| declaration_nonempty
initialiser_entry ::= initialiser_clause
hash_if_expression ::= constant_expression
template_type_param ::= template class template_param_name R1122
| R1120 template_param_name R1121
template_param_name ::= any_identifier
R1122 ::= assign any_qualified_id
R1120 ::= class
| typename
R1121 ::= assign token_type_id
constant_offset ::= member_designator R1133
member_designator ::= field_id_expression
R1133 ::= designator_list
designator_list ::= designator R1152
designator ::= dot member_designator
| open_square constant_expression close_square
R1152 ::= designator_list
I did some changes on top of the previous changes trying to improve the EBNF output:
Author: mingodad <[email protected]> 2021-06-18 14:05:59
Committer: mingodad <[email protected]> 2021-06-18 14:05:59
Parent: e17347b9c5a79574252911c66713c974af403bf0 (Add ebnf output)
Child: 0000000000000000000000000000000000000000 (Local uncommitted changes, not checked in to index)
Branch: dad-ebnf
Follows:
Precedes:
A bit better EBNF output but still not fine
----------------------- sid/src/lang-ebnf/ebnf-output.c -----------------------
index e9a15a3ba..572cedd88 100644
@@ -36,8 +36,7 @@ output_ebnf_key(EBNFOutputInfoT *info, KeyT *key)
char ch = key->string.contents[idx];
switch(ch) {
case ':':
- case ' ':
- case '-': ch = '_';
+ case ' ': ch = '_';
}
write_char(ostream, ch);
}
@@ -75,21 +74,60 @@ ebnf_output_item(EBNFOutputInfoT *info, ItemT *item, int i)
}
}
-static void
+static int
+ebnf_rule_has_rules(RuleT *rule)
+{
+ AltT *alt;
+ ItemT *item;
+ for (alt = rule->alt_head; alt; alt = alt_next(alt)) {
+ for (item = alt_item_head(alt); item; item = item_next(item)) {
+ switch(item->entry->type) {
+ case ET_RULE: case ET_BASIC: return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+ebnf_rule_has_rename(RuleT *rule)
+{
+ AltT *alt;
+ ItemT *item;
+ for (alt = rule->alt_head; alt; alt = alt_next(alt)) {
+ for (item = alt_item_head(alt); item; item = item_next(item)) {
+ switch(item->entry->type) {
+ case ET_RENAME: return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
ebnf_output_alt(EBNFOutputInfoT *info, AltT *alt, int i)
{
OStreamT *ostream = ebnf_out_info_ostream(info);
ItemT *item;
+ int rc = 0;
for (item = alt_item_head(alt); item; item = item_next(item)) {
+ if(item->type == ET_RULE && ebnf_rule_has_rules(item->entry->u.rule) == 0) continue;
+
if (!ebnf_output_item(info, item, i)) {
continue;
}
-
+ if(item->type == ET_RULE && item->entry->key.type == KT_NUMERIC && ebnf_rule_has_rename(item->entry->u.rule)) {
+ write_char(ostream, '?');
+ }
+ ++rc;
write_char(ostream, ' ');
i = 0;
}
+ return rc;
}
static void
@@ -105,8 +143,7 @@ ebnf_output_rule(EBNFOutputInfoT *info, RuleT *rule)
write_cstring(ostream, " ::= ");
for (alt = rule->alt_head; alt; alt = alt_next(alt)) {
- ebnf_output_alt(info, alt, i);
- i++;
+ if(ebnf_output_alt(info, alt, i)) i++;
}
if (rule_has_empty_alt(rule)) {
@@ -128,6 +165,9 @@ ebnf_output_entry(EntryT *entry, void *gclosure)
if (!entry_is_rule(entry)) {
return;
}
+ if(ebnf_rule_has_rules(entry_get_rule(entry)) == 0) {
+ return;
+ }
ebnf_output_rule(info, entry_get_rule(entry));
}
Hi, thank you for this. At the time I wrote it, I'd only intended the BNF output to be approximate, for humans rather than for machines to parse. I'd be happy to merge this if you want to make a PR!