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 & operator << (& 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 | POSNONTERMsym i: { f << i; }
58 | ACTIONsym a: { f << "{ ... }"; }
59 | TERMSTRINGsym s: { f << s; }
60 | TERMREGEXPsym re: { f << re; }
61 | PREDICATEsym e: { f << '(' << e << ')'; }
62 | PRECsym(ONEcons{name ...}): { f << "prec: " << name; }
63 | PRECsym NOcons: { f << "prec: ???"; }
64 | ERRORsym(): { f << '?'; }
65 | SPECIALsym _: { f << "???"; }
70 ///////////////////////////////////////////////////////////////////////////////
72 // Pretty print a list of production symbols
74 ///////////////////////////////////////////////////////////////////////////////
75 & operator << (& f, ProductionSymbols P)
76 { for (ProductionSymbols l = P; l; l = l->#2)
77 { f << l->#1; if (l->#2) f << " "; }
81 ///////////////////////////////////////////////////////////////////////////////
85 ///////////////////////////////////////////////////////////////////////////////
86 & operator << (& f, BNF bnf)
88 { BNFrule(id,ty,alts):
90 if (ty != NOty) f << ' ' << ty << ' ';
92 for_each (ProductionSymbols, p, alts)
93 { f << '\t' << p << '\n'; }
99 ///////////////////////////////////////////////////////////////////////////////
101 // Pretty print a list of alternatives
103 ///////////////////////////////////////////////////////////////////////////////
104 & operator << (& f, BNFs rules)
105 { for_each(BNF, rule, rules) f << rule;
109 ///////////////////////////////////////////////////////////////////////////////
111 // Print a precedence rule
113 ///////////////////////////////////////////////////////////////////////////////
114 & operator << (& f, PrecRule r)
116 { PRECrule(assoc,pri,symbols):
118 { LEFTassoc: { f << "left: "; }
119 | RIGHTassoc: { f << "right: "; }
120 | NONassoc: { f << "nonfix: "; }
122 f << pri << ' ' << symbols << '\n';
128 ///////////////////////////////////////////////////////////////////////////////
130 // Print a list of precedence rules
132 ///////////////////////////////////////////////////////////////////////////////
133 & operator << (& f, List<PrecRule> rules)
134 { for_each (PrecRule, r, rules) f << r;
138 ///////////////////////////////////////////////////////////////////////////////
140 // Pretty print a grammar expression
142 ///////////////////////////////////////////////////////////////////////////////
143 & operator << (& f, GramExp exp)
145 { EXPgram (precs,_,rules): { f << precs << rules; }
151 ///////////////////////////////////////////////////////////////////////////////
153 // Method to create a syntax class
155 ///////////////////////////////////////////////////////////////////////////////
156 SyntaxClass::SyntaxClass
157 (CLASS_TYPE ct, Id id, Inherits i, TyQual q, Decls body)
158 : ClassDefinition(ct,id,#[],add_inherit("LR1Parser",#[],i),q,body),
159 production_rules(#[]),
160 precedence_rules(#[]),
161 G(0), parserGen(0), prec(0),
162 nonterm_map(string_hash, string_equal),
163 action_map(integer_hash, integer_equal),
164 inner_action_map(integer_hash, integer_equal),
165 line_map (integer_hash, integer_equal),
166 predicate_map(integer_hash, integer_equal)
169 SyntaxClass::~SyntaxClass() {}
171 ///////////////////////////////////////////////////////////////////////////////
173 // Method to generate the interface of a parser class
175 ///////////////////////////////////////////////////////////////////////////////
176 void SyntaxClass::gen_class_interface (CodeGen& C)
180 "%^// Parser table type definitions"
182 "%^typedef LR1Parser Super;"
183 "%^typedef Super::Offset Offset;"
184 "%^typedef Super::State State;"
185 "%^typedef Super::Rule Rule;"
186 "%^typedef Super::Symbol Symbol;"
187 "%^typedef Super::ProductionLength ProductionLength;"
188 "%^typedef Super::ShortSymbol ShortSymbol;"
189 "%^typedef Super::EquivMap EquivMap;"
190 "%^enum { INITIAL_STACK_SIZE_ = 256,"
191 "%^ MAX_STACK_SIZE_ = 8192"
195 "%^// Semantic value stack"
197 "%^union %s_semantic_stack_type * t__, * bot__;"
198 "%^int stack_size__;"
199 "%^int heap_allocated__;"
202 "%^// Constructor and parsing method"
205 "%^virtual void parse();"
206 "%^void action_driver(const Rule);"
208 "%^void adjust_stack(int);\n"
209 "%^void grow_semantic_stack();",
210 class_name, class_name
214 ///////////////////////////////////////////////////////////////////////////////
216 // Method to generate a parser given a grammar expression.
218 ///////////////////////////////////////////////////////////////////////////////
219 void ParserCompiler::gen_parser(Id id, GramExp e)
220 { // if (debug) cerr << id << ":\n" << e;
222 SyntaxClass * C = (SyntaxClass*)
223 ClassDefinition::lookup_class(ClassDefinition::SYNTAX_CLASS, id);
224 if (C) C->gen_parser(*this,e);
227 ///////////////////////////////////////////////////////////////////////////////
229 // Method to generate a parser given a grammar expression.
231 ///////////////////////////////////////////////////////////////////////////////
232 void SyntaxClass::gen_parser(CodeGen& C, GramExp e)
235 compile_grammar(C, e);
239 ///////////////////////////////////////////////////////////////////////////////
241 // Method to compile a grammar
243 ///////////////////////////////////////////////////////////////////////////////
244 void SyntaxClass::compile_grammar(CodeGen& C, GramExp e)
246 { EXPgram (precs,err,rules):
247 { compile_rules(C, precs, err, rules);
250 { bug("SyntaxClass::compile_grammar"); }
254 ///////////////////////////////////////////////////////////////////////////////
256 // Collect the names of the non-terminals
257 // and count the number of productions.
259 ///////////////////////////////////////////////////////////////////////////////
260 void SyntaxClass::preprocess_grammar ()
261 { number_of_productions = 0;
263 ////////////////////////////////////////////////////////////////////////////
264 // Compute the terminal and action encoding
265 ////////////////////////////////////////////////////////////////////////////
266 { for_each(BNF, r, production_rules)
268 { BNFrule(id,ty,alts):
269 { for_each (ProductionSymbols, p, alts)
270 { Bool no_action = true;
271 for_each (ProductionSymbol, s, p)
274 { TOKENsym (cons as ONEcons {
276 alg_ty = DATATYPEty({ qualifiers ...},_) ... }
278 { if ((qualifiers & QUALlexeme) == 0)
279 error("%Lconstructor %s is not a lexeme\n",name);
280 if (tag_of(cons) > max_term)
281 max_term = tag_of(cons);
283 | ACTIONsym _: { no_action = false; }
287 if (ty != NOty && no_action)
288 msg("%!%wmissing synthesized value in production: %s %T:",
289 r->loc(), id, ty) << p << '\n';
296 ////////////////////////////////////////////////////////////////////////////
297 // Set the error token
298 ////////////////////////////////////////////////////////////////////////////
299 error_term = ++max_term;
300 max_nonterm = max_term + 1;
302 ////////////////////////////////////////////////////////////////////////////
303 // Compute the non-terminals encoding.
304 ////////////////////////////////////////////////////////////////////////////
305 { for_each(BNF, r, production_rules)
307 { BNFrule(id,_,alts):
308 { if (! nonterm_map.contains(id))
310 nonterm_map.insert(id,(HashTable::Value)max_nonterm);
312 number_of_productions += length(alts);
319 ///////////////////////////////////////////////////////////////////////////////
321 // Translate rules into grammar form.
323 ///////////////////////////////////////////////////////////////////////////////
324 void SyntaxClass::translate_into_grammar ()
325 { int i = 0; // production number
326 min_action = Grammar::First_action;
327 for_each(BNF, r, production_rules)
329 { BNFrule(id,ty,alts):
330 { Grammar::NonTerminal A = (Grammar::NonTerminal)nonterm_map[id];
331 symbol_names[A] = id;
332 for_each (ProductionSymbols, p, alts)
334 int non_terms_or_actions = 0;
336 Grammar::Production P =
337 (Grammar::Production)mem_pool.c_alloc
338 (sizeof(Grammar::Symbol) * (length(p) + 2));
340 for (List<ProductionSymbol> L = p; L; L = L->#2)
341 { ProductionSymbol X = L->#1;
346 if (symbol_names[c] == 0)
347 symbol_names[c] = #"'" + print_char(c) + #"'";
350 { if (! nonterm_map.contains(id))
351 { error("%Lundefined non-terminal %s\n",id); }
353 { P[j] = (Grammar::NonTerminal)nonterm_map[id]; }
354 ++non_terms_or_actions;
356 | TOKENsym (cons as ONEcons { tag, name ... }):
357 { P[j] = tag_of(cons);
358 symbol_names[P[j]] = name;
360 | TOKENsym _: { P[j] = ' '; }
363 action_map.insert(HashTable::Key(min_action), decls);
364 line_map.insert(HashTable::Key(min_action),
365 HashTable::Value(X->begin_line));
367 inner_action_map.insert(HashTable::Key(min_action),
368 HashTable::Value(non_terms_or_actions));
370 ++non_terms_or_actions;
372 | ERRORsym(): { P[j] = error_term; }
373 | _: { bug("translate_into_grammar()"); }
377 P[j] = Grammar::END_PRODUCTION;
378 productions[i++] = P;
385 ///////////////////////////////////////////////////////////////////////////////
387 // Method to enter the precedence information
389 ///////////////////////////////////////////////////////////////////////////////
390 void SyntaxClass::define_operator_precedence ()
391 { for_each (PrecRule, r, precedence_rules)
393 { PRECrule(assoc,pri,symbols):
394 { OpPrecedence::Associativity a;
396 { LEFTassoc: { a = OpPrecedence::Left; }
397 | RIGHTassoc: { a = OpPrecedence::Right; }
398 | NONEassoc: { a = OpPrecedence::None; }
400 for_each(ProductionSymbol, s, symbols)
403 { prec->precedence(G->map(c),pri);
404 prec->associativity(G->map(c),a);
407 { prec->precedence(G->map(tag_of(cons)),pri);
408 prec->associativity(G->map(tag_of(cons)),a);
412 error("%Lprecedence symbol must be a terminal: ")
422 ///////////////////////////////////////////////////////////////////////////////
424 // Add a new reference of a non-terminal
426 ///////////////////////////////////////////////////////////////////////////////
427 static void add_use (HashTable& table, Id nonterm, int item_number)
428 { HashTable::Entry * e = table.lookup(nonterm);
430 { List<int> old_uses = (List<int>) table.value(e);
431 table.insert(nonterm,#[item_number ... old_uses]);
433 { table.insert(nonterm,#[item_number]);
437 ///////////////////////////////////////////////////////////////////////////////
439 // Generate the semantic stack definition
441 ///////////////////////////////////////////////////////////////////////////////
442 void SyntaxClass::generate_semantic_stack_definition (CodeGen& C)
444 ////////////////////////////////////////////////////////////////////////////
445 // Mapping from nonterminal to type
446 ////////////////////////////////////////////////////////////////////////////
447 HashTable nonterm_to_ty(string_hash,string_equal);
448 HashTable nonterm_to_uses(string_hash,string_equal);
450 ////////////////////////////////////////////////////////////////////////////
451 // Generate the semantic stack definition.
452 ////////////////////////////////////////////////////////////////////////////
454 "%^// Semantic value stack for syntax class %s"
456 "%^union %s_semantic_stack_type {%+"
458 class_name, class_name);
460 ////////////////////////////////////////////////////////////////////////////
462 // First, we'll make sure that all productions with the same non-terminal
463 // have the same synthesized attribute type.
465 ////////////////////////////////////////////////////////////////////////////
466 for_each (BNF, rl, production_rules)
469 { HashTable::Entry * e = nonterm_to_ty.lookup(id);
471 { Ty last_ty = (Ty)nonterm_to_ty.value(e);
472 if (! ty_equal(ty,last_ty))
474 error("%Lexpecting type '%T' but found '%T'\n", last_ty, ty);
477 nonterm_to_ty.insert(id,ty);
482 ////////////////////////////////////////////////////////////////////////////
484 // Now, we found out all references of all non-terminals.
486 ////////////////////////////////////////////////////////////////////////////
489 for_each (BNF, r, production_rules)
491 { BNFrule(id,ty,alts):
492 { for_each (ProductionSymbols, p, alts)
495 add_use(nonterm_to_uses,id,item_number);
496 for_each (ProductionSymbol, X, p)
500 { HashTable::Entry * e = nonterm_to_ty.lookup(id);
502 { Ty this_ty = (Ty)nonterm_to_ty.value(e);
504 add_use(nonterm_to_uses,id,item_number);
515 ////////////////////////////////////////////////////////////////////////////
517 // Then we print out the type definitions for all the synthesized
520 ////////////////////////////////////////////////////////////////////////////
522 for_each (BNF, r, production_rules)
526 { List<int> uses = (List<int>)nonterm_to_uses[id];
529 "%^typedef %tATTRIBUTE_%i;"
531 r->begin_line, r->file_name, ty, "", i, i);
532 for (List<int> l = uses; l; l = l->#2)
533 { C.pr ("_%i", l->#1); if (l->#2) C.pr(", "); }
545 ///////////////////////////////////////////////////////////////////////////////
547 // Generate debugging tables
549 ///////////////////////////////////////////////////////////////////////////////
550 void SyntaxClass::generate_debugging_tables (CodeGen& C)
552 "%^// Debugging tables for syntax class %s"
555 class_name, class_name);
557 ////////////////////////////////////////////////////////////////////////////
558 // Generate the mapping from rule number to source code line number.
559 ////////////////////////////////////////////////////////////////////////////
560 C.pr ("%^static const int %s_line[] =%^{%+%^", class_name);
561 { int * line_table = (int *)mem_pool.c_alloc(G->size() * sizeof(int));
562 for (Grammar::Action a = Grammar::First_action; a > min_action; a--)
563 { int r = G->rule_of(a);
565 { line_table[r] = (int)line_map[HashTable::Key(a)]; }
567 for (int r = 0; r < G->size(); r++)
568 { C.pr ("%i", line_table[r]);
569 if (r < G->size() - 1) C.pr(", ");
570 if (r % 8 == 7) C.pr ("%^");
575 ////////////////////////////////////////////////////////////////////////////
576 // Generate the mapping from equivalence class number to name.
577 ////////////////////////////////////////////////////////////////////////////
578 C.pr ("%^static const char * const %s_symbolname[] =%^{%+%^", class_name);
579 { Id * sym_map = (Id *)
580 mem_pool.c_alloc((G->max_non_terminal() + 1) * sizeof(Id));
581 for (int c = 0; c <= max_nonterm; c++)
582 if (symbol_names[c]) sym_map[G->map(c)] = symbol_names[c];
583 for (int i = 0; i <= G->max_non_terminal(); i++)
584 { C.pr ("%s", sym_map[i] ? make_quoted_string(sym_map[i]) : "\"???\"");
585 if (i < G->max_non_terminal()) C.pr (", ");
586 if (i % 8 == 7) C.pr ("%^");
591 ////////////////////////////////////////////////////////////////////////////
592 // Generate the mapping from rule number to production.
593 ////////////////////////////////////////////////////////////////////////////
594 { for (int r = 0; r < G->size(); r++)
595 { C.pr("%^static const DFATables::ShortSymbol %s_rhs_%i[] = { ",
597 int len = G->length(G->rhs(r));
598 for (int i = 0; i < len; i++)
599 { C.pr ("%i, ", (int)G->rhs(r)[i]); }
603 { C.pr ("%^static const DFATables::ShortSymbol * %s_rhs[] =%^{%+",
605 for (int r = 0; r < G->size(); r++)
606 { C.pr ("%^%s_rhs_%i", class_name, r);
607 if (r < G->size() - 1) C.pr(", ");
611 C.pr ("\n#endif\n\n");
614 ///////////////////////////////////////////////////////////////////////////////
616 // Generate the parser tables
618 ///////////////////////////////////////////////////////////////////////////////
619 void SyntaxClass::generate_parser_tables (CodeGen& C)
621 ////////////////////////////////////////////////////////////////////////////
622 // Generate the parser tables.
623 ////////////////////////////////////////////////////////////////////////////
625 "%^// Encoded parser tables for syntax class %s"
628 parserGen->gen_code(C.pr(""),class_name);
631 void SyntaxClass::generate_action_driver(CodeGen& C)
633 ////////////////////////////////////////////////////////////////////////////
635 // Generate the parser driver header.
637 ////////////////////////////////////////////////////////////////////////////
640 "%^// Parser driver for syntax class %s"
642 "%^inline void %s::action_driver(const Rule _r_)"
644 "%^%s_semantic_stack_type syn_;",
645 class_name, class_name, class_name
648 ////////////////////////////////////////////////////////////////////////////
649 // Generate the debugging function
650 ////////////////////////////////////////////////////////////////////////////
652 "%^// Tracing code for syntax class %s"
655 "%^{ cerr << \"Reducing via rule \" << _r_ << \" at line \""
656 "%^ << %s_line[_r_] << \", \""
657 "%^ << %s_symbolname[%s_lhs[_r_]] << \" <- \";"
658 "%^ for (const DFATables::ShortSymbol * _p_ = %s_rhs[_r_]; *_p_ >= 0; _p_++)"
659 "%^ cerr << %s_symbolname[*_p_] << ' ';"
663 class_name, class_name, class_name, class_name,
664 class_name, class_name, class_name, class_name, class_name
667 generate_semantic_actions(C);
672 ///////////////////////////////////////////////////////////////////////////////
674 // Generate the parse method
676 ///////////////////////////////////////////////////////////////////////////////
677 void SyntaxClass::generate_parse_method(CodeGen& C)
680 "%^// Parsing method for parser class %s"
684 "%^ %s_semantic_stack_type stack__[INITIAL_STACK_SIZE_];"
685 "%^ t__ = bot__ = stack__;"
686 "%^ stack_size__ = sizeof(stack__)/sizeof(stack__[0]) - 1;"
687 "%^ heap_allocated__ = 0;"
688 "%^ parser_prefix();"
689 "%^ LR1ParserDriver<%s,(LR1Parser::State)%i> drv;"
690 "%^ drv.driver(*this);"
691 "%^ parser_suffix();"
692 "%^ if (bot__ != stack__) delete [] bot__;"
694 class_name, class_name, class_name,
695 class_name, (int)parserGen->final_state()
699 ///////////////////////////////////////////////////////////////////////////////
701 // Method to generate the semantic actions
703 ///////////////////////////////////////////////////////////////////////////////
704 void SyntaxClass::generate_semantic_actions(CodeGen& C)
706 ////////////////////////////////////////////////////////////////////////////
707 // Generate the switch on the reduction rules.
708 ////////////////////////////////////////////////////////////////////////////
710 "%^// Actions for syntax class %s"
712 "%^t__ -= %s_ncount[_r_];"
713 "%^switch (_r_) {\n%+",
714 class_name, class_name, class_name, class_name
717 ////////////////////////////////////////////////////////////////////////////
718 // Generate the parsing actions
719 ////////////////////////////////////////////////////////////////////////////
724 for (Grammar::Action a = Grammar::First_action; a > min_action; a--)
725 { HashTable::Entry * e = inner_action_map.lookup(HashTable::Key(a));
733 C.pr ("%^case %i: {%+%&%-} break;",
734 (int)G->rule_of(a), action_map[HashTable::Key(a)]);
743 "%^if (t__ >= bot__ + stack_size__) grow_semantic_stack();"
748 ///////////////////////////////////////////////////////////////////////////////
750 // Method to initialize the data structures
752 ///////////////////////////////////////////////////////////////////////////////
753 void SyntaxClass::initialize()
755 number_of_productions = 0;
761 min_action = Grammar::First_action;
770 ///////////////////////////////////////////////////////////////////////////////
772 // Method to cleanup all the data structures
774 ///////////////////////////////////////////////////////////////////////////////
775 void SyntaxClass::cleanup()
779 inner_action_map.clear();
781 predicate_map.clear();
790 ///////////////////////////////////////////////////////////////////////////////
792 // Method to compile a set of production rules
794 ///////////////////////////////////////////////////////////////////////////////
795 void SyntaxClass::compile_rules
797 PrecRules prec_rules,
798 ShiftReduceErrors expected_errors,
801 { int last_errors = errors;
803 ////////////////////////////////////////////////////////////////////////////
805 // Initialize all the data structures used
807 ////////////////////////////////////////////////////////////////////////////
808 production_rules = p_rules;
809 precedence_rules = prec_rules;
811 ////////////////////////////////////////////////////////////////////////////
813 // Collect the names of the non-terminals in this grammar
815 ////////////////////////////////////////////////////////////////////////////
816 preprocess_grammar();
818 ////////////////////////////////////////////////////////////////////////////
820 // Translate into grammar form.
822 ////////////////////////////////////////////////////////////////////////////
823 productions = (Grammar::Production *)mem_pool.c_alloc
824 (sizeof(Grammar::Production) * number_of_productions);
825 symbol_names = (Id *)mem_pool.c_alloc(sizeof(Id) * (max_nonterm + 1));
826 ty_map = (Ty *)mem_pool.c_alloc(sizeof(Ty) * number_of_productions);
827 translate_into_grammar();
828 symbol_names[error_term] = "?";
829 if (last_errors < errors) return;
830 if (number_of_productions > 0)
831 start_symbol = productions[0][0];
833 ////////////////////////////////////////////////////////////////////////////
834 // Create the grammar and put it into canonical form
835 ////////////////////////////////////////////////////////////////////////////
836 Grammar G0(productions, number_of_productions, min_term, max_term,
837 start_symbol, symbol_names);
838 G = new Grammar(G0.makeCanonical());
840 ////////////////////////////////////////////////////////////////////////////
841 // Compile the grammar into tables.
842 ////////////////////////////////////////////////////////////////////////////
843 parserGen = new LALR1Gen;
844 prec = new OpPrecedence (*G);
845 define_operator_precedence();
846 parserGen->compile(*G,*prec);
848 ////////////////////////////////////////////////////////////////////////////
852 ////////////////////////////////////////////////////////////////////////////
853 process_parser_errors(expected_errors);
855 ////////////////////////////////////////////////////////////////////////////
859 ////////////////////////////////////////////////////////////////////////////
860 if (options.generate_report)
861 { std::ostream& log = open_logfile();
862 log << "[Syntax class " << class_name << "]\n";
863 parserGen->print_report(log, options.verbosity) << '\n';
866 gen_class_implementation(C,#[],EXTERNAL_INSTANTIATION);
869 ////////////////////////////////////////////////////////////////////////////
871 // Method to generate the implementation of the parser class.
873 ////////////////////////////////////////////////////////////////////////////
874 void SyntaxClass::gen_class_implementation(CodeGen& C, Tys tys, DefKind k)
876 generate_parser_tables(C); // encoded tables
877 generate_debugging_tables(C); // auxiliary tables for debugging
878 generate_semantic_stack_definition(C); // semantic stack definition
879 generate_action_driver(C); // the action driver
880 generate_parse_method(C); // the main parse method
881 generate_semantic_stack_adjustment(C); // how to adjust the stack
882 generate_semantic_stack_growth(C); // how to grow the stack
883 gen_class_constructor(C,tys,k); // constructor of this class
886 ////////////////////////////////////////////////////////////////////////////
888 // Method to process parser errors
890 ////////////////////////////////////////////////////////////////////////////
891 void SyntaxClass::process_parser_errors(ShiftReduceErrors expected_errors)
893 int sr_conflicts = parserGen->shift_reduce_conflicts();
894 int rr_conflicts = parserGen->reduce_reduce_conflicts();
896 if (sr_conflicts > 0 && expected_errors < 0)
897 { msg(expected_errors == -1 ? "%Lwarning: %i%s%s\n" : "%L%w%i%s%s\n",
898 sr_conflicts, " shift/reduce conflicts in syntax class ",
902 if (expected_errors >= 0 && sr_conflicts != expected_errors)
903 { msg("%L%wexpecting %i shift/reduce conflicts but found %i"
904 " in syntax class %s\n",
905 expected_errors, sr_conflicts, class_name);
908 if (rr_conflicts > 0)
909 { msg("%L%w%i reduce/reduce conflicts in syntax class %s\n",
910 rr_conflicts, class_name);
914 //////////////////////////////////////////////////////////////////////////////
916 // Generate the semantic stack growing method
918 //////////////////////////////////////////////////////////////////////////////
919 void SyntaxClass::generate_semantic_stack_growth(CodeGen& C)
922 "%^void %s::grow_semantic_stack()\n"
924 "%^int N = (stack_size__ + 1) * 2;"
925 "%^%s_semantic_stack_type * S = new %s_semantic_stack_type [N];"
926 "%^if (N >= LR1Parser::SEMANTIC_STACK_SIZE) "
927 "%^ error_report(\"Warning: semantic stack overflow\");"
928 "%^memcpy(S, bot__, sizeof(%s_semantic_stack_type) * (stack_size__ + 1));"
929 "%^if (heap_allocated__) delete [] bot__;"
930 "%^t__ = S + (t__ - bot__);"
932 "%^stack_size__ = N - 1;"
933 "%^heap_allocated__ = 1;"
935 class_name, class_name, class_name, class_name );
938 //////////////////////////////////////////////////////////////////////////////
940 // Method to generate the stack adjustment method
942 //////////////////////////////////////////////////////////////////////////////
943 void SyntaxClass::generate_semantic_stack_adjustment(CodeGen& C)
945 C.pr("%^void %s::adjust_stack(int offset) { t__ += offset; }\n\n",
949 //////////////////////////////////////////////////////////////////////////////
951 // Method to generate the class constructor that initializes all
952 // the parser tables.
954 //////////////////////////////////////////////////////////////////////////////
955 void SyntaxClass::gen_class_constructor_initializers(CodeGen& C,Tys,DefKind)
958 C.pr("%^ : Super(%s_base,%s_check,%s_def,%s_defact,%s_next,"
959 "%^ %s_len,%s_ncount,%s_lhs,%s_equiv,%i,%i,%i)",
960 id, id, id, id, id, id, id, id, id,
961 (int)error_term, (int)max_term, (int)max_nonterm