📄 reader.c
字号:
| The previous action turns out the be a mid-rule action. Attach it || to the current rule, i.e., create a dummy symbol, attach it this || mid-rule action, and append this dummy nonterminal to the current || rule. |`-------------------------------------------------------------------*/voidgrammar_midrule_action (void){ /* Since the action was written out with this rule's number, we must give the new rule this number by inserting the new rule before it. */ /* Make a DUMMY nonterminal, whose location is that of the midrule action. Create the MIDRULE. */ location dummy_location = current_rule->action_location; symbol *dummy = dummy_symbol_get (dummy_location); symbol_list *midrule = symbol_list_new (dummy, dummy_location); /* Make a new rule, whose body is empty, before the current one, so that the action just read can belong to it. */ ++nrules; ++nritems; /* Attach its location and actions to that of the DUMMY. */ midrule->location = dummy_location; midrule->action = current_rule->action; midrule->action_location = dummy_location; current_rule->action = NULL; if (previous_rule_end) previous_rule_end->next = midrule; else grammar = midrule; /* End the dummy's rule. */ previous_rule_end = symbol_list_new (NULL, dummy_location); previous_rule_end->next = current_rule; midrule->next = previous_rule_end; /* Insert the dummy nonterminal replacing the midrule action into the current rule. */ grammar_current_rule_symbol_append (dummy, dummy_location);}/* Set the precedence symbol of the current rule to PRECSYM. */voidgrammar_current_rule_prec_set (symbol *precsym, location loc){ if (current_rule->ruleprec) complain_at (loc, _("only one %s allowed per rule"), "%prec"); current_rule->ruleprec = precsym;}/* Attach dynamic precedence DPREC to the current rule. */voidgrammar_current_rule_dprec_set (int dprec, location loc){ if (! glr_parser) warn_at (loc, _("%s affects only GLR parsers"), "%dprec"); if (dprec <= 0) complain_at (loc, _("%s must be followed by positive number"), "%dprec"); else if (current_rule->dprec != 0) complain_at (loc, _("only one %s allowed per rule"), "%dprec"); current_rule->dprec = dprec;}/* Attach a merge function NAME with argument type TYPE to current rule. */voidgrammar_current_rule_merge_set (uniqstr name, location loc){ if (! glr_parser) warn_at (loc, _("%s affects only GLR parsers"), "%merge"); if (current_rule->merger != 0) complain_at (loc, _("only one %s allowed per rule"), "%merge"); current_rule->merger = get_merge_function (name, current_rule->sym->type_name, loc);}/* Attach SYM to the current rule. If needed, move the previous action as a mid-rule action. */voidgrammar_current_rule_symbol_append (symbol *sym, location loc){ if (current_rule->action) grammar_midrule_action (); ++nritems; grammar_symbol_append (sym, loc);}/* Attach an ACTION to the current rule. If needed, move the previous action as a mid-rule action. */voidgrammar_current_rule_action_append (const char *action, location loc){ if (current_rule->action) grammar_midrule_action (); current_rule->action = action; current_rule->action_location = loc;}/*---------------------------------------------------------------.| Convert the rules into the representation using RRHS, RLHS and || RITEM. |`---------------------------------------------------------------*/static voidpackgram (void){ unsigned int itemno = 0; rule_number ruleno = 0; symbol_list *p = grammar; ritem = xnmalloc (nritems, sizeof *ritem); rules = xnmalloc (nrules, sizeof *rules); while (p) { symbol *ruleprec = p->ruleprec; rules[ruleno].user_number = ruleno; rules[ruleno].number = ruleno; rules[ruleno].lhs = p->sym; rules[ruleno].rhs = ritem + itemno; rules[ruleno].prec = NULL; rules[ruleno].dprec = p->dprec; rules[ruleno].merger = p->merger; rules[ruleno].precsym = NULL; rules[ruleno].location = p->location; rules[ruleno].useful = true; rules[ruleno].action = p->action; rules[ruleno].action_location = p->action_location; p = p->next; while (p && p->sym) { /* item_number = symbol_number. But the former needs to contain more: negative rule numbers. */ ritem[itemno++] = symbol_number_as_item_number (p->sym->number); /* A rule gets by default the precedence and associativity of the last token in it. */ if (p->sym->class == token_sym && default_prec) rules[ruleno].prec = p->sym; if (p) p = p->next; } /* If this rule has a %prec, the specified symbol's precedence replaces the default. */ if (ruleprec) { rules[ruleno].precsym = ruleprec; rules[ruleno].prec = ruleprec; } ritem[itemno++] = rule_number_as_item_number (ruleno); ++ruleno; if (p) p = p->next; } if (itemno != nritems) abort (); if (trace_flag & trace_sets) ritem_print (stderr);}/*------------------------------------------------------------------.| Read in the grammar specification and record it in the format || described in gram.h. All actions are copied into ACTION_OBSTACK, || in each case forming the body of a C function (YYACTION) which || contains a switch statement to decide which action to execute. |`------------------------------------------------------------------*/voidreader (void){ /* Initialize the symbol table. */ symbols_new (); /* Construct the accept symbol. */ accept = symbol_get ("$accept", empty_location); accept->class = nterm_sym; accept->number = nvars++; /* Construct the error token */ errtoken = symbol_get ("error", empty_location); errtoken->class = token_sym; errtoken->number = ntokens++; /* Construct a token that represents all undefined literal tokens. It is always token number 2. */ undeftoken = symbol_get ("$undefined", empty_location); undeftoken->class = token_sym; undeftoken->number = ntokens++; /* Initialize the obstacks. */ obstack_init (&pre_prologue_obstack); obstack_init (&post_prologue_obstack); finput = xfopen (grammar_file, "r"); gram_in = finput; gram__flex_debug = trace_flag & trace_scan; gram_debug = trace_flag & trace_parse; scanner_initialize (); gram_parse (); /* If something went wrong during the parsing, don't try to continue. */ if (complaint_issued) return; /* Grammar has been read. Do some checking */ if (nrules == 0) fatal (_("no rules in the input grammar")); /* Report any undefined symbols and consider them nonterminals. */ symbols_check_defined (); /* If the user did not define her ENDTOKEN, do it now. */ if (!endtoken) { endtoken = symbol_get ("$end", empty_location); endtoken->class = token_sym; endtoken->number = 0; /* Value specified by POSIX. */ endtoken->user_token_number = 0; } /* Insert the initial rule, which line is that of the first rule (not that of the start symbol): accept: %start EOF. */ { symbol_list *p = symbol_list_new (accept, empty_location); p->location = grammar->location; p->next = symbol_list_new (startsymbol, empty_location); p->next->next = symbol_list_new (endtoken, empty_location); p->next->next->next = symbol_list_new (NULL, empty_location); p->next->next->next->next = grammar; nrules += 1; nritems += 3; grammar = p; } if (! (nsyms <= SYMBOL_NUMBER_MAXIMUM && nsyms == ntokens + nvars)) abort (); xfclose (finput); /* Assign the symbols their symbol numbers. Write #defines for the token symbols into FDEFINES if requested. */ symbols_pack (); /* Convert the grammar into the format described in gram.h. */ packgram (); /* The grammar as a symbol_list is no longer needed. */ LIST_FREE (symbol_list, grammar);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -