tendra icon indicating copy to clipboard operation
tendra copied to clipboard

Bad/wrong BNF output by 'sid'

Open mingodad opened this issue 3 years ago • 3 comments

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];

mingodad avatar Jun 17 '21 18:06 mingodad

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 

mingodad avatar Jun 17 '21 18:06 mingodad

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));
 }

mingodad avatar Jun 18 '21 12:06 mingodad

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!

katef avatar Jun 18 '21 16:06 katef