1 ///////////////////////////////////////////////////////////////////////////////
3 // This file implements the syntax/syntax class constructs of Prop.
5 ///////////////////////////////////////////////////////////////////////////////
7 #include <AD/strings/charesc.h>
8 #include <AD/strings/quark.h>
9 #include <AD/automata/grammar.h>
10 #include <AD/automata/operprec.h>
11 #include <AD/automata/lalr1gen.h>
14 #include "parsegen.ph"
21 ///////////////////////////////////////////////////////////////////////////////
23 // Instantiate the parser/grammar related datatypes
25 ///////////////////////////////////////////////////////////////////////////////
26 instantiate datatype GramExp, List<GramExp>,
28 ProductionSymbol, List<ProductionSymbol>,
29 PrecRule, List<PrecRule>,
30 List< List<ProductionSymbol> >;
32 ///////////////////////////////////////////////////////////////////////////////
34 // Constructor and destructor
36 ///////////////////////////////////////////////////////////////////////////////
37 ParserCompiler:: ParserCompiler() {}
38 ParserCompiler::~ParserCompiler() {}
40 ///////////////////////////////////////////////////////////////////////////////
42 // Pretty printing methods for grammar
44 ///////////////////////////////////////////////////////////////////////////////
46 ///////////////////////////////////////////////////////////////////////////////
48 // Pretty print a production symbol
50 ///////////////////////////////////////////////////////////////////////////////
51 ostream& operator << (ostream& f, ProductionSymbol sym)
53 { TERMsym c: { f << '\'' << print_char(c) << '\''; }
54 | TOKENsym NOcons: { f << "<?>"; }
55 | TOKENsym ONEcons{ name ... }: { f << name; }
56 | NONTERMsym id: { f << id; }
57 | ACTIONsym a: { f << "{ ... }"; }
58 | TERMSTRINGsym s: { f << s; }
59 | TERMREGEXPsym re: { f << re; }
60 | PREDICATEsym e: { f << '(' << e << ')'; }
61 | INDsym _: { f << "???"; }
62 | PRECsym(ONEcons{name ...}): { f << "prec: " << name; }
63 | PRECsym NOcons: { f << "prec: ???"; }
64 | ERRORsym(): { f << '?'; }
69 ///////////////////////////////////////////////////////////////////////////////
71 // Pretty print a list of production symbols
73 ///////////////////////////////////////////////////////////////////////////////
74 ostream& operator << (ostream& f, ProductionSymbols P)
75 { for (ProductionSymbols l = P; l; l = l->#2)
76 { f << l->#1; if (l->#2) f << " "; }
80 ///////////////////////////////////////////////////////////////////////////////
84 ///////////////////////////////////////////////////////////////////////////////
85 ostream& operator << (ostream& f, BNF bnf)
87 { BNFrule(id,ty,alts):
89 if (ty != NOty) f << ' ' << ty << ' ';
91 for_each (ProductionSymbols, p, alts)
92 { f << '\t' << p << '\n'; }
98 ///////////////////////////////////////////////////////////////////////////////
100 // Pretty print a list of alternatives
102 ///////////////////////////////////////////////////////////////////////////////
103 ostream& operator << (ostream& f, BNFs rules)
104 { for_each(BNF, rule, rules) f << rule;
108 ///////////////////////////////////////////////////////////////////////////////
110 // Print a precedence rule
112 ///////////////////////////////////////////////////////////////////////////////
113 ostream& operator << (ostream& f, PrecRule r)
115 { PRECrule(assoc,pri,symbols):
117 { LEFTassoc: { f << "left: "; }
118 | RIGHTassoc: { f << "right: "; }
119 | NONassoc: { f << "nonfix: "; }
121 f << pri << ' ' << symbols << '\n';
127 ///////////////////////////////////////////////////////////////////////////////
129 // Print a list of precedence rules
131 ///////////////////////////////////////////////////////////////////////////////
132 ostream& operator << (ostream& f, List<PrecRule> rules)
133 { for_each (PrecRule, r, rules) f << r;
137 ///////////////////////////////////////////////////////////////////////////////
139 // Pretty print a grammar expression
141 ///////////////////////////////////////////////////////////////////////////////
142 ostream& operator << (ostream& f, GramExp exp)
144 { EXPgram (precs,_,rules): { f << precs << rules; }
150 ///////////////////////////////////////////////////////////////////////////////
152 // Method to crewate a syntax class
154 ///////////////////////////////////////////////////////////////////////////////
155 SyntaxClass::SyntaxClass(Id id, Inherits i, TyQual q, Decls body)
156 : ClassDefinition(SYNTAX_CLASS,id,#[],add_inherit("LR1Parser",#[],i),q,body)
158 SyntaxClass::~SyntaxClass() {}
160 ///////////////////////////////////////////////////////////////////////////////
162 // Method to generate the interface of a parser class
164 ///////////////////////////////////////////////////////////////////////////////
165 void SyntaxClass::gen_class_interface (CodeGen& C)
167 C.pr ("%-%^public:%+"
169 "%^// Parser table type definitions"
171 "%^typedef LR1Parser Super;"
172 "%^typedef Super::Offset Offset;"
173 "%^typedef Super::State State;"
174 "%^typedef Super::Rule Rule;"
175 "%^typedef Super::Symbol Symbol;"
176 "%^typedef Super::ProductionLength ProductionLength;"
177 "%^typedef Super::ShortSymbol ShortSymbol;"
178 "%^typedef Super::EquivMap EquivMap;"
179 "%^enum { INITIAL_STACK_SIZE_ = 256,"
180 "%^ MAX_STACK_SIZE_ = 8192"
184 "%^// Semantic value stack"
186 "%^union %s_semantic_stack_type * t__, * bot__;"
187 "%^int stack_size__;"
188 "%^int heap_allocated__;"
191 "%^// Constructor and parsing method"
194 "%^virtual void parse();"
195 "%^void action_driver(const Rule);"
197 "%^void adjust_stack(int);\n"
198 "%^void grow_semantic_stack();",
199 class_name, class_name
203 ///////////////////////////////////////////////////////////////////////////////
205 // Method to generate a parser given a grammar expression.
207 ///////////////////////////////////////////////////////////////////////////////
208 void ParserCompiler::gen_parser(Id id, GramExp e)
209 { // if (debug) cerr << id << ":\n" << e;
211 SyntaxClass * C = (SyntaxClass*)
212 ClassDefinition::lookup_class(ClassDefinition::SYNTAX_CLASS, id);
213 if (C) C->gen_parser(*this,e);
216 ///////////////////////////////////////////////////////////////////////////////
218 // Method to generate a parser given a grammar expression.
220 ///////////////////////////////////////////////////////////////////////////////
221 void SyntaxClass::gen_parser(CodeGen& C, GramExp e)
223 compile_grammar(C, e);
227 "%^// Constructor for parser class %s"
230 "%^ : Super(%s_base,%s_check,%s_def,%s_defact,%s_next,"
231 "%^ %s_len,%s_ncount,%s_lhs,%s_equiv,%i,%i,%i) {}\n\n",
232 id, id, id, id, id, id, id, id, id, id, id, id,
233 (int)error_symbol, (int)max_terminal_symbol,
234 (int)max_nonterminal_symbol
238 ///////////////////////////////////////////////////////////////////////////////
240 // Method to compile a grammar
242 ///////////////////////////////////////////////////////////////////////////////
243 void SyntaxClass::compile_grammar(CodeGen& C, GramExp e)
245 { EXPgram (precs,err,rules):
246 { compile_rules(C, precs, err, rules); }
248 { bug("SyntaxClass::compile_grammar"); }
252 ///////////////////////////////////////////////////////////////////////////////
254 // Collect the names of the non-terminals
255 // and count the number of productions.
257 ///////////////////////////////////////////////////////////////////////////////
258 static void preprocess_grammar
260 HashTable& nonterms_map,
261 int& number_of_productions,
262 Grammar::Terminal& max_term,
263 Grammar::NonTerminal& max_nonterm,
264 Grammar::Terminal& error_term
266 { number_of_productions = 0;
268 ////////////////////////////////////////////////////////////////////////////
269 // Compute the terminal and action encoding
270 ////////////////////////////////////////////////////////////////////////////
271 { for_each(BNF, r, rules)
273 { BNFrule(id,ty,alts):
274 { for_each (ProductionSymbols, p, alts)
275 { Bool no_action = true;
276 for_each (ProductionSymbol, s, p)
279 { TOKENsym (cons as ONEcons {
281 alg_ty = DATATYPEty({ qualifiers ...},_) ... }
283 { if ((qualifiers & QUALlexeme) == 0)
284 error("%Lconstructor %s is not a lexeme\n",name);
285 if (tag_of(cons) > max_term)
286 max_term = tag_of(cons);
288 | ACTIONsym _: { no_action = false; }
292 if (ty != NOty && no_action)
293 msg("%!%wsynthesized value missing in production: ",
294 r->loc()) << p << '\n';
301 ////////////////////////////////////////////////////////////////////////////
302 // Set the error token
303 ////////////////////////////////////////////////////////////////////////////
304 error_term = ++max_term;
305 max_nonterm = max_term + 1;
307 ////////////////////////////////////////////////////////////////////////////
308 // Compute the non-terminals encoding.
309 ////////////////////////////////////////////////////////////////////////////
310 { for_each(BNF, r, rules)
312 { BNFrule(id,_,alts):
313 { if (! nonterms_map.contains(id))
315 nonterms_map.insert(id,(HashTable::Value)max_nonterm);
317 number_of_productions += length(alts);
324 ///////////////////////////////////////////////////////////////////////////////
326 // Translate rules into grammar form.
328 ///////////////////////////////////////////////////////////////////////////////
329 static void translate_into_grammar
331 Grammar::Production productions[],
332 const HashTable& nonterm_map,
333 HashTable& action_map,
334 HashTable& inner_action_map,
336 Grammar::Action& action,
337 Grammar::Terminal error_term,
341 { int i = 0; // production number
342 action = Grammar::First_action;
343 for_each(BNF, r, rules)
345 { BNFrule(id,ty,alts):
346 { Grammar::NonTerminal A = (Grammar::NonTerminal)nonterm_map[id];
347 symbol_names[A] = id;
348 for_each (ProductionSymbols, p, alts)
350 int non_terms_or_actions = 0;
352 Grammar::Production P =
353 (Grammar::Production)mem_pool.c_alloc
354 (sizeof(Grammar::Symbol) * (length(p) + 2));
356 for (List<ProductionSymbol> L = p; L; L = L->#2)
357 { ProductionSymbol X = L->#1;
362 if (symbol_names[c] == 0)
363 symbol_names[c] = #"'" + print_char(c) + #"'";
366 { if (! nonterm_map.contains(id))
367 { error("%Lundefined non-terminal %s\n",id); }
369 { P[j] = (Grammar::NonTerminal)nonterm_map[id]; }
370 ++non_terms_or_actions;
372 | TOKENsym (cons as ONEcons { tag, name ... }):
373 { P[j] = tag_of(cons);
374 symbol_names[P[j]] = name;
376 | TOKENsym _: { P[j] = ' '; }
379 action_map.insert(HashTable::Key(action), decls);
380 line_map.insert(HashTable::Key(action),
381 HashTable::Value(X->begin_line));
383 inner_action_map.insert(HashTable::Key(action),
384 HashTable::Value(non_terms_or_actions));
386 ++non_terms_or_actions;
388 | ERRORsym(): { P[j] = error_term; }
389 | _: { bug("translate_into_grammar()"); }
393 P[j] = Grammar::END_PRODUCTION;
394 productions[i++] = P;
401 ///////////////////////////////////////////////////////////////////////////////
403 // Function to enter the precedence information
405 ///////////////////////////////////////////////////////////////////////////////
406 static void define_operator_precedence
407 (PrecRules rules, OpPrecedence& prec, const Grammar& G)
408 { for_each (PrecRule, r, rules)
410 { PRECrule(assoc,pri,symbols):
411 { OpPrecedence::Associativity a;
413 { LEFTassoc: { a = OpPrecedence::Left; }
414 | RIGHTassoc: { a = OpPrecedence::Right; }
415 | NONEassoc: { a = OpPrecedence::None; }
417 for_each(ProductionSymbol, s, symbols)
420 { prec.precedence(G.map(c),pri);
421 prec.associativity(G.map(c),a);
424 { prec.precedence(G.map(tag_of(cons)),pri);
425 prec.associativity(G.map(tag_of(cons)),a);
429 error("%Lprecedence symbol must be terminal: ") << s << '\n';
438 ///////////////////////////////////////////////////////////////////////////////
440 // Add a new reference of a non-terminal
442 ///////////////////////////////////////////////////////////////////////////////
443 static void add_use (HashTable& table, Id nonterm, int item_number)
444 { HashTable::Entry * e = table.lookup(nonterm);
446 { List<int> old_uses = (List<int>) table.value(e);
447 table.insert(nonterm,#[item_number ... old_uses]);
449 { table.insert(nonterm,#[item_number]);
453 ///////////////////////////////////////////////////////////////////////////////
455 // Generate the semantic stack definition
457 ///////////////////////////////////////////////////////////////////////////////
458 static void generate_semantic_stack
465 ////////////////////////////////////////////////////////////////////////////
466 // Mapping from nonterminal to type
467 ////////////////////////////////////////////////////////////////////////////
468 HashTable nonterm_to_ty(string_hash,string_equal);
469 HashTable nonterm_to_uses(string_hash,string_equal);
471 ////////////////////////////////////////////////////////////////////////////
472 // Generate the semantic stack definition.
473 ////////////////////////////////////////////////////////////////////////////
475 "%^// Semantic value stack for syntax class %s"
477 "%^union %s_semantic_stack_type {%+"
479 class_name, class_name);
481 ////////////////////////////////////////////////////////////////////////////
483 // First, we'll make sure that all productions with the same non-terminal
484 // have the same synthesized attribute type.
486 ////////////////////////////////////////////////////////////////////////////
487 for_each (BNF, rl, rules)
490 { HashTable::Entry * e = nonterm_to_ty.lookup(id);
492 { Ty last_ty = (Ty)nonterm_to_ty.value(e);
493 if (! ty_equal(ty,last_ty))
495 error("%Lexpecting type '%T' but found '%T'\n", last_ty, ty);
498 nonterm_to_ty.insert(id,ty);
503 ////////////////////////////////////////////////////////////////////////////
505 // Now, we found out all references of all non-terminals.
507 ////////////////////////////////////////////////////////////////////////////
510 for_each (BNF, r, rules)
512 { BNFrule(id,ty,alts):
513 { for_each (ProductionSymbols, p, alts)
516 add_use(nonterm_to_uses,id,item_number);
517 for_each (ProductionSymbol, X, p)
521 { HashTable::Entry * e = nonterm_to_ty.lookup(id);
523 { Ty this_ty = (Ty)nonterm_to_ty.value(e);
525 add_use(nonterm_to_uses,id,item_number);
536 ////////////////////////////////////////////////////////////////////////////
538 // Then we print out the type definitions for all the synthesized
541 ////////////////////////////////////////////////////////////////////////////
543 for_each (BNF, r, rules)
547 { List<int> uses = (List<int>)nonterm_to_uses[id];
550 "%^typedef %tATTRIBUTE_%i;"
552 r->begin_line, r->file_name, ty, "", i, i);
553 for (List<int> l = uses; l; l = l->#2)
554 { C.pr ("_%i", l->#1); if (l->#2) C.pr(", "); }
566 ///////////////////////////////////////////////////////////////////////////////
568 // Generate debugging tables
570 ///////////////////////////////////////////////////////////////////////////////
571 static void generate_debugging_tables
574 const LALR1Gen& parserGen,
577 const HashTable& line_map,
578 const Grammar::Action min_action,
579 Grammar::NonTerminal max_nonterm
582 "%^// Debugging tables for syntax class %s"
585 class_name, class_name);
587 ////////////////////////////////////////////////////////////////////////////
588 // Generate the mapping from rule number to source code line number.
589 ////////////////////////////////////////////////////////////////////////////
590 C.pr ("%^static const int %s_line[] =%^{%+%^", class_name);
591 { int * line_table = (int *)mem_pool.c_alloc(G.size() * sizeof(int));
592 for (Grammar::Action a = Grammar::First_action; a > min_action; a--)
593 { int r = G.rule_of(a);
595 { line_table[r] = (int)line_map[HashTable::Key(a)]; }
597 for (int r = 0; r < G.size(); r++)
598 { C.pr ("%i", line_table[r]);
599 if (r < G.size() - 1) C.pr(", ");
600 if (r % 8 == 7) C.pr ("%^");
605 ////////////////////////////////////////////////////////////////////////////
606 // Generate the mapping from equivalence class number to name.
607 ////////////////////////////////////////////////////////////////////////////
608 C.pr ("%^static const char * const %s_symbolname[] =%^{%+%^", class_name);
609 { Id * sym_map = (Id *)
610 mem_pool.c_alloc((G.max_non_terminal() + 1) * sizeof(Id));
611 for (int c = 0; c <= max_nonterm; c++)
612 if (symbol_names[c]) sym_map[G.map(c)] = symbol_names[c];
613 for (int i = 0; i <= G.max_non_terminal(); i++)
614 { C.pr ("%s", sym_map[i] ? make_quoted_string(sym_map[i]) : "\"???\"");
615 if (i < G.max_non_terminal()) C.pr (", ");
616 if (i % 8 == 7) C.pr ("%^");
621 ////////////////////////////////////////////////////////////////////////////
622 // Generate the mapping from rule number to production.
623 ////////////////////////////////////////////////////////////////////////////
624 { for (int r = 0; r < G.size(); r++)
625 { C.pr("%^static const DFATables::ShortSymbol %s_rhs_%i[] = { ",
627 int len = G.length(G.rhs(r));
628 for (int i = 0; i < len; i++)
629 { C.pr ("%i, ", (int)G.rhs(r)[i]); }
633 { C.pr ("%^static const DFATables::ShortSymbol * %s_rhs[] =%^{%+",
635 for (int r = 0; r < G.size(); r++)
636 { C.pr ("%^%s_rhs_%i", class_name, r);
637 if (r < G.size() - 1) C.pr(", ");
641 C.pr ("\n#endif\n\n");
644 ///////////////////////////////////////////////////////////////////////////////
646 // Generate parser tables and action code
648 ///////////////////////////////////////////////////////////////////////////////
649 static void generate_parser_driver
652 const LALR1Gen& parserGen,
655 int number_of_productions,
658 const HashTable& action_map,
659 const HashTable& inner_action_map,
660 const HashTable& line_map,
661 const Grammar::Action min_action,
662 Grammar::NonTerminal max_nonterm
665 ////////////////////////////////////////////////////////////////////////////
666 // Generate the parser tables.
667 ////////////////////////////////////////////////////////////////////////////
669 "%^// Encoded parser tables for syntax class %s"
672 parserGen.gen_code(C.pr(""),class_name);
673 ::generate_debugging_tables(class_name, C, parserGen, G, symbol_names,
674 line_map, min_action, max_nonterm);
675 ::generate_semantic_stack(class_name, C, rules, ty_map);
677 ////////////////////////////////////////////////////////////////////////////
678 // Generate the parser driver header.
679 ////////////////////////////////////////////////////////////////////////////
682 "%^// Parser driver for syntax class %s"
684 "%^inline void %s::action_driver(const Rule _r_)"
686 "%^%s_semantic_stack_type syn_;",
687 class_name, class_name, class_name
690 ////////////////////////////////////////////////////////////////////////////
691 // Generate the debugging function
692 ////////////////////////////////////////////////////////////////////////////
694 "%^// Tracing code for syntax class %s"
697 "%^{ cerr << \"Reducing via rule \" << _r_ << \" at line \""
698 "%^ << %s_line[_r_] << \", \""
699 "%^ << %s_symbolname[%s_lhs[_r_]] << \" <- \";"
700 "%^ for (const DFATables::ShortSymbol * _p_ = %s_rhs[_r_]; *_p_ >= 0; _p_++)"
701 "%^ cerr << %s_symbolname[*_p_] << ' ';"
705 class_name, class_name, class_name, class_name,
706 class_name, class_name, class_name, class_name, class_name
709 ////////////////////////////////////////////////////////////////////////////
710 // Generate the switch on the reduction rules.
711 ////////////////////////////////////////////////////////////////////////////
713 "%^// Actions for syntax class %s"
715 "%^t__ -= %s_ncount[_r_];"
716 "%^switch (_r_) {\n%+",
717 class_name, class_name, class_name, class_name
720 ////////////////////////////////////////////////////////////////////////////
721 // Generate the parsing actions
722 ////////////////////////////////////////////////////////////////////////////
727 for (Grammar::Action a = Grammar::First_action; a > min_action; a--)
728 { HashTable::Entry * e = inner_action_map.lookup(HashTable::Key(a));
736 C.pr ("%^case %i: {%+%&%-} break;",
737 (int)G.rule_of(a), action_map[HashTable::Key(a)]);
746 "%^if (t__ >= bot__ + stack_size__) grow_semantic_stack();"
751 ////////////////////////////////////////////////////////////////////////////
752 // Generate the parser method
753 ////////////////////////////////////////////////////////////////////////////
755 "%^// Parsing method for parser class %s"
759 "%^ %s_semantic_stack_type stack__[INITIAL_STACK_SIZE_];"
760 "%^ t__ = bot__ = stack__;"
761 "%^ stack_size__ = sizeof(stack__)/sizeof(stack__[0]) - 1;"
762 "%^ heap_allocated__ = 0;"
763 "%^ parser_prefix();"
764 "%^ LR1ParserDriver<%s,(LR1Parser::State)%i> drv;"
765 "%^ drv.driver(*this);"
766 "%^ parser_suffix();"
767 "%^ if (bot__ != stack__) delete [] bot__;"
769 class_name, class_name, class_name,
770 class_name, parserGen.final_state()
774 ///////////////////////////////////////////////////////////////////////////////
776 // Method to compile a set of production rules
778 ///////////////////////////////////////////////////////////////////////////////
779 void SyntaxClass::compile_rules
781 PrecRules precedence_rules,
782 ShiftReduceErrors expected_errors,
785 { int last_errors = errors;
786 ////////////////////////////////////////////////////////////////////////////
787 // Data structures used
788 ////////////////////////////////////////////////////////////////////////////
789 HashTable nonterm_map(string_hash, string_equal);
790 HashTable action_map(integer_hash, integer_equal);
791 HashTable inner_action_map(integer_hash, integer_equal);
792 HashTable line_map (integer_hash, integer_equal);
793 HashTable predicate_map(integer_hash, integer_equal);
794 int number_of_productions = 0;
795 Grammar::Terminal min_term = 0;
796 Grammar::Terminal max_term = 255;
797 Grammar::Terminal error_term = 255;
798 Grammar::NonTerminal max_nonterm = 255;
799 Grammar::NonTerminal start_symbol = 0;
800 Grammar::Action action = Grammar::First_action;
801 Id * symbol_names = 0;
802 Grammar::Production * productions = 0;
805 ////////////////////////////////////////////////////////////////////////////
806 // Collect the names of the non-terminals in this grammar
807 ////////////////////////////////////////////////////////////////////////////
809 (rules, nonterm_map, number_of_productions,
810 max_term, max_nonterm, error_term);
812 ////////////////////////////////////////////////////////////////////////////
813 // Translate into grammar form.
814 ////////////////////////////////////////////////////////////////////////////
815 productions = (Grammar::Production *)mem_pool.c_alloc
816 (sizeof(Grammar::Production) * number_of_productions);
817 symbol_names = (Id *)mem_pool.c_alloc(sizeof(Id) * (max_nonterm + 1));
818 ty_map = (Ty *)mem_pool.c_alloc(sizeof(Ty) * number_of_productions);
820 ::translate_into_grammar
821 (rules, productions, nonterm_map,
822 action_map, inner_action_map, line_map, action,
823 error_term, ty_map, symbol_names);
824 symbol_names[error_term] = "?";
825 error_symbol = error_term;
826 max_terminal_symbol = max_term;
827 max_nonterminal_symbol = max_nonterm;
829 if (last_errors < errors) return;
830 if (number_of_productions > 0) start_symbol = productions[0][0];
832 ////////////////////////////////////////////////////////////////////////////
833 // Create the grammar and put it into canonical form
834 ////////////////////////////////////////////////////////////////////////////
835 Grammar G0(productions, number_of_productions, min_term, max_term,
836 start_symbol, symbol_names);
837 Grammar G = G0.makeCanonical();
839 ////////////////////////////////////////////////////////////////////////////
840 // Compile the grammar into tables.
841 ////////////////////////////////////////////////////////////////////////////
843 OpPrecedence prec(G);
844 ::define_operator_precedence(precedence_rules,prec,G);
845 parserGen.compile(G,prec);
847 ////////////////////////////////////////////////////////////////////////////
848 // Print error messages
849 ////////////////////////////////////////////////////////////////////////////
850 int sr_conflicts = parserGen.shift_reduce_conflicts();
851 int rr_conflicts = parserGen.reduce_reduce_conflicts();
852 if (sr_conflicts > 0 && expected_errors < 0)
853 { msg(expected_errors == -1 ? "%L%w: %i%s%s\n" : "%L%w%i%s%s\n",
854 sr_conflicts, " shift/reduce conflicts in syntax class ",
857 if (expected_errors >= 0 && sr_conflicts != expected_errors)
858 { msg("%L%wexpecting %i shift/reduce conflicts but found %i in syntax class %s\n",
859 expected_errors, sr_conflicts, class_name);
861 if (rr_conflicts > 0)
862 { msg("%L%w%i reduce/reduce conflicts in syntax class %s\n",
863 rr_conflicts, class_name);
866 ////////////////////////////////////////////////////////////////////////////
868 ////////////////////////////////////////////////////////////////////////////
869 if (options.generate_report)
870 { ostream& log = open_logfile();
871 log << "[Syntax class " << class_name << "]\n";
872 parserGen.print_report(log, options.verbosity) << '\n';
875 ////////////////////////////////////////////////////////////////////////////
876 // Generate driver code
877 ////////////////////////////////////////////////////////////////////////////
878 ::generate_parser_driver
879 (class_name, C, parserGen, G, symbol_names, number_of_productions,
880 rules, ty_map, action_map, inner_action_map,
881 line_map, action, max_nonterm);
883 ////////////////////////////////////////////////////////////////////////////
884 // Generate the stack adjustment method
885 ////////////////////////////////////////////////////////////////////////////
886 C.pr("%^void %s::adjust_stack(int offset) { t__ += offset; }\n\n",
889 ////////////////////////////////////////////////////////////////////////////
890 // Generate the semantic stack growing method
891 ////////////////////////////////////////////////////////////////////////////
893 "%^void %s::grow_semantic_stack()\n"
895 "%^int N = (stack_size__ + 1) * 2;"
896 "%^%s_semantic_stack_type * S = new %s_semantic_stack_type [N];"
897 "%^if (N >= LR1Parser::SEMANTIC_STACK_SIZE) "
898 "%^ error_report(\"Warning: semantic stack overflow\");"
899 "%^memcpy(S, bot__, sizeof(%s_semantic_stack_type) * (stack_size__ + 1));"
900 "%^if (heap_allocated__) delete [] bot__;"
901 "%^t__ = S + (t__ - bot__);"
903 "%^stack_size__ = N - 1;"
904 "%^heap_allocated__ = 1;"
906 class_name, class_name, class_name, class_name );