From affac6132ae6ee354e1497e456b5c81a0c84334f Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Thu, 22 Dec 2005 11:40:05 +0000 Subject: [PATCH] Warn about unused values. * src/symlist.h, src/symlist.c (symbol_list, symbol_list_new): Add a `used' member. (symbol_list_n_get, symbol_list_n_used_set): New. (symbol_list_n_type_name_get): Use symbol_list_n_get. * src/scan-gram.l (handle_action_dollar): Flag used symbols. * src/reader.c (grammar_current_rule_check): Check that values are used. * src/symtab.c (symbol_print): Accept 0. * tests/existing.at: Remove the type information. Empty the actions. Remove useless actions (beware of mid-rule actions: perl -000 -pi -e 's/s*{}(?=[ns]*[|;])//g'). * tests/actions.at (Exotic Dollars): Use unused values. * tests/calc.at: Likewise. * tests/glr-regression.at (No users destructors if stack 0 deleted): Likewise. * src/gram.c (rule_useful_p, rule_never_reduced_p): Use rule_useful_p. --- ChangeLog | 23 + NEWS | 18 + src/gram.c | 7 +- src/reader.c | 77 +- src/reader.h | 3 + src/scan-gram.l | 8 +- src/symlist.c | 69 +- src/symlist.h | 24 +- src/symtab.c | 13 +- tests/actions.at | 2 + tests/calc.at | 3 +- tests/existing.at | 1636 +++++---------------------------------- tests/glr-regression.at | 9 +- 13 files changed, 382 insertions(+), 1510 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3be972e5..468d548c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2005-12-22 Akim Demaille + + Warn about unused values. + * src/symlist.h, src/symlist.c (symbol_list, symbol_list_new): Add + a `used' member. + (symbol_list_n_get, symbol_list_n_used_set): New. + (symbol_list_n_type_name_get): Use symbol_list_n_get. + * src/scan-gram.l (handle_action_dollar): Flag used symbols. + * src/reader.c (grammar_current_rule_check): Check that values are + used. + * src/symtab.c (symbol_print): Accept 0. + * tests/existing.at: Remove the type information. + Empty the actions. + Remove useless actions (beware of mid-rule actions: perl -000 + -pi -e 's/\s*\{\}(?=[\n\s]*[|;])//g'). + * tests/actions.at (Exotic Dollars): Use unused values. + * tests/calc.at: Likewise. + * tests/glr-regression.at (No users destructors if stack 0 deleted): + Likewise. + + * src/gram.c (rule_useful_p, rule_never_reduced_p): Use + rule_useful_p. + 2005-12-21 Paul Eggert Undo 2005-12-01 tentative license wording change. The wording is diff --git a/NEWS b/NEWS index 22d182fa..94e9cc17 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,24 @@ Bison News Changes in version 2.1a: +* New warning: unused values + Typed right-hand side symbols whose value are not used are reported. + For instance + + exp: exp "?" exp ":" exp { $$ = $1 + $3; } + | exp "+" exp + ; + + will trigger a warning about $5 of the first rule, and $3 in the + second ($1 is copied to $$ by the default rule). To avoid this + warning, let Bison believe the value is used, e.g. + + exp: exp "?" exp ":" exp { $$ = $1 + $3; $5; } + | exp "+" exp { $$ = $1; $3; } + + This helps catching lost values and memory leaks: if a value is + ignored, its associated memory will never be reclaimed. + * %destructor vs. YYABORT, YYACCEPT, and YYERROR. Destructors are now called when user code invokes YYABORT, YYACCEPT, and YYERROR, for all objects on the stack, other than objects diff --git a/src/gram.c b/src/gram.c index cff87d7c..d6857369 100644 --- a/src/gram.c +++ b/src/gram.c @@ -65,7 +65,7 @@ rule_useful_p (rule *r) bool rule_useless_p (rule *r) { - return r->number >= nrules; + return !rule_useful_p (r); } @@ -77,7 +77,7 @@ rule_useless_p (rule *r) bool rule_never_reduced_p (rule *r) { - return !r->useful && r->number < nrules; + return !r->useful && rule_useful_p (r); } @@ -317,8 +317,7 @@ grammar_rules_never_reduced_report (const char *message) if (!rules[r].useful) { location_print (stderr, rules[r].location); - fprintf (stderr, ": %s: %s: ", - _("warning"), message); + fprintf (stderr, ": %s: %s: ", _("warning"), message); rule_print (&rules[r], stderr); } } diff --git a/src/reader.c b/src/reader.c index fed446ad..b55b0fa9 100644 --- a/src/reader.c +++ b/src/reader.c @@ -40,7 +40,7 @@ static symbol_list *grammar = NULL; static bool start_flag = false; merger_list *merge_functions; -/* Has %union been seen? */ +/* Was %union seen? */ bool typed = false; /* Should rules have a default precedence? */ @@ -104,7 +104,7 @@ get_merge_function (uniqstr name, uniqstr type, location loc) type = uniqstr_new (""); head.next = merge_functions; - for (syms = &head, n = 1; syms->next != NULL; syms = syms->next, n += 1) + for (syms = &head, n = 1; syms->next; syms = syms->next, n += 1) if (UNIQSTR_EQ (name, syms->next->name)) break; if (syms->next == NULL) @@ -128,11 +128,8 @@ get_merge_function (uniqstr name, uniqstr type, location loc) void free_merger_functions (void) { - merger_list *L0; - if (! glr_parser) - return; - L0 = merge_functions; - while (L0 != NULL) + merger_list *L0 = merge_functions; + while (L0) { merger_list *L1 = L0->next; free (L0); @@ -150,13 +147,6 @@ free_merger_functions (void) | | | All actions are copied out, labelled by the rule number they apply | | to. | -| | -| Bison used to allow some %directives in the rules sections, but | -| this is no longer consider appropriate: (i) the documented grammar | -| doesn't claim it, (ii), it would promote bad style, (iii), error | -| recovery for %directives consists in skipping the junk until a `%' | -| is seen and helrp synchronizing. This scheme is definitely wrong | -| in the rules section. | `-------------------------------------------------------------------*/ /* The (currently) last symbol of GRAMMAR. */ @@ -206,7 +196,6 @@ grammar_rule_begin (symbol *lhs, location loc) current_rule = grammar_end; /* Mark the rule's lhs as a nonterminal if not already so. */ - if (lhs->class == unknown_sym) { lhs->class = nterm_sym; @@ -217,39 +206,55 @@ grammar_rule_begin (symbol *lhs, location loc) complain_at (loc, _("rule given for %s, which is a token"), lhs->tag); } -/* Check that the last rule (CURRENT_RULE) is properly defined. For - instance, there should be no type clash on the default action. */ + +/*------------------------------------------------------------------. +| Check that the last rule (CURRENT_RULE) is properly defined. For | +| instance, there should be no type clash on the default action. | +`------------------------------------------------------------------*/ static void grammar_current_rule_check (void) { symbol *lhs = current_rule->sym; char const *lhs_type = lhs->type_name; - symbol *first_rhs = current_rule->next->sym; - /* If there is an action, then there is nothing we can do: the user - is allowed to shoot herself in the foot. */ - if (current_rule->action) - return; + /* Type check. - /* Don't worry about the default action if $$ is untyped, since $$'s - value can't be used. */ - if (! lhs_type) - return; + If there is an action, then there is nothing we can do: the user + is allowed to shoot herself in the foot. - /* If $$ is being set in default way, report if any type mismatch. */ - if (first_rhs) + Don't worry about the default action if $$ is untyped, since $$'s + value can't be used. */ + if (!current_rule->action && lhs_type) { - const char *rhs_type = first_rhs->type_name ? first_rhs->type_name : ""; - if (!UNIQSTR_EQ (lhs_type, rhs_type)) + symbol *first_rhs = current_rule->next->sym; + /* If $$ is being set in default way, report if any type mismatch. */ + if (first_rhs) + { + const char *rhs_type = + first_rhs->type_name ? first_rhs->type_name : ""; + if (!UNIQSTR_EQ (lhs_type, rhs_type)) + warn_at (current_rule->location, + _("type clash on default action: <%s> != <%s>"), + lhs_type, rhs_type); + } + /* Warn if there is no default for $$ but we need one. */ + else warn_at (current_rule->location, - _("type clash on default action: <%s> != <%s>"), - lhs_type, rhs_type); + _("empty rule for typed nonterminal, and no action")); + } + + /* Check that all the symbol values are used. */ + if (typed) + { + symbol_list *l = current_rule; + int n = 1; + for (l = current_rule->next; l && l->sym; l = l->next, ++n) + /* The default action `uses' $1. */ + if (! (!current_rule->action && n == 1) + && l->sym->type_name && !l->used) + warn_at (current_rule->location, _("unused value: $%d"), n); } - /* Warn if there is no default for $$ but we need one. */ - else - warn_at (current_rule->location, - _("empty rule for typed nonterminal, and no action")); } diff --git a/src/reader.h b/src/reader.h index c47a16eb..ad1ad819 100644 --- a/src/reader.h +++ b/src/reader.h @@ -77,7 +77,10 @@ void free_merger_functions (void); extern merger_list *merge_functions; +/* Was %union seen? */ extern bool typed; + +/* Should rules have a default precedence? */ extern bool default_prec; #endif /* !READER_H_ */ diff --git a/src/scan-gram.l b/src/scan-gram.l index 3c7d37c4..471d7b91 100644 --- a/src/scan-gram.l +++ b/src/scan-gram.l @@ -825,9 +825,9 @@ handle_action_dollar (char *text, location loc) if (INT_MIN <= num && num <= rule_length && ! get_errno ()) { int n = num; - if (1-n > max_left_semantic_context) - max_left_semantic_context = 1-n; - if (!type_name && n > 0) + if (max_left_semantic_context < 1 - n) + max_left_semantic_context = 1 - n; + if (!type_name && 0 < n) type_name = symbol_list_n_type_name_get (current_rule, loc, n); if (!type_name && typed) complain_at (loc, _("$%d of `%s' has no declared type"), @@ -837,6 +837,8 @@ handle_action_dollar (char *text, location loc) obstack_fgrow3 (&obstack_for_string, "]b4_rhs_value(%d, %d, [%s])[", rule_length, n, type_name); + if (typed) + symbol_list_n_used_set (current_rule, n, true); } else complain_at (loc, _("integer out of range: %s"), quote (text)); diff --git a/src/symlist.c b/src/symlist.c index 7c3ebff6..ed42ce1e 100644 --- a/src/symlist.c +++ b/src/symlist.c @@ -34,13 +34,19 @@ symbol_list * symbol_list_new (symbol *sym, location loc) { symbol_list *res = xmalloc (sizeof *res); - res->next = NULL; + res->sym = sym; res->location = loc; + res->action = NULL; + res->used = false; + res->ruleprec = NULL; res->dprec = 0; res->merger = 0; + + res->next = NULL; + return res; } @@ -56,7 +62,7 @@ symbol_list_print (symbol_list *l, FILE *f) { symbol_print (l->sym, f); if (l && l->sym) - fputc (' ', f); + fprintf (f, ", "); } } @@ -90,43 +96,64 @@ symbol_list_free (symbol_list *list) `--------------------*/ unsigned int -symbol_list_length (symbol_list *list) +symbol_list_length (symbol_list *l) { int res = 0; - for (/* Nothing. */; list; list = list->next) + for (/* Nothing. */; l; l = l->next) ++res; return res; } +/*--------------------------------. +| Get symbol N in symbol list L. | +`--------------------------------*/ + +symbol_list * +symbol_list_n_get (symbol_list *l, int n) +{ + int i; + + if (n < 0) + return NULL; + + for (i = 0; i < n; ++i) + { + l = l->next; + if (l == NULL || l->sym == NULL) + return NULL; + } + + return l; +} + + /*--------------------------------------------------------------. | Get the data type (alternative in the union) of the value for | -| symbol N in symbol list RP. | +| symbol N in symbol list L. | `--------------------------------------------------------------*/ uniqstr -symbol_list_n_type_name_get (symbol_list *rp, location loc, int n) +symbol_list_n_type_name_get (symbol_list *l, location loc, int n) { - int i; - - if (n < 0) + l = symbol_list_n_get (l, n); + if (!l) { complain_at (loc, _("invalid $ value: $%d"), n); return NULL; } + return l->sym->type_name; +} - i = 0; - while (i < n) - { - rp = rp->next; - if (rp == NULL || rp->sym == NULL) - { - complain_at (loc, _("invalid $ value: $%d"), n); - return NULL; - } - ++i; - } +/*----------------------------------------. +| The symbol N in symbol list L is USED. | +`----------------------------------------*/ - return rp->sym->type_name; +void +symbol_list_n_used_set (symbol_list *l, int n, bool used) +{ + l = symbol_list_n_get (l, n); + if (l) + l->used = used; } diff --git a/src/symlist.h b/src/symlist.h index e4714f6c..ccd6110b 100644 --- a/src/symlist.h +++ b/src/symlist.h @@ -25,9 +25,10 @@ # include "location.h" # include "symtab.h" +/* A list of symbols, used during the parsing to store the rules. */ typedef struct symbol_list { - struct symbol_list *next; + /* The symbol. */ symbol *sym; location location; @@ -35,9 +36,16 @@ typedef struct symbol_list const char *action; location action_location; + /* Whether this symbol's value is used in the current action. */ + bool used; + + /* Precedence/associativity. */ symbol *ruleprec; int dprec; int merger; + + /* The list. */ + struct symbol_list *next; } symbol_list; @@ -48,18 +56,24 @@ symbol_list *symbol_list_new (symbol *sym, location loc); void symbol_list_print (symbol_list *l, FILE *f); /* Prepend SYM at LOC to the LIST. */ -symbol_list *symbol_list_prepend (symbol_list *list, +symbol_list *symbol_list_prepend (symbol_list *l, symbol *sym, location loc); /* Free the LIST, but not the symbols it contains. */ -void symbol_list_free (symbol_list *list); +void symbol_list_free (symbol_list *l); /* Return its length. */ -unsigned int symbol_list_length (symbol_list *list); +unsigned int symbol_list_length (symbol_list *l); + +/* Get symbol N in symbol list L. */ +symbol_list *symbol_list_n_get (symbol_list *l, int n); /* Get the data type (alternative in the union) of the value for symbol N in rule RULE. */ -uniqstr symbol_list_n_type_name_get (symbol_list *rp, location loc, int n); +uniqstr symbol_list_n_type_name_get (symbol_list *l, location loc, int n); + +/* The symbol N in symbol list L is USED. */ +void symbol_list_n_used_set (symbol_list *l, int n, bool used); #endif /* !SYMLIST_H_ */ diff --git a/src/symtab.c b/src/symtab.c index 634ddfa0..bf231628 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -85,10 +85,15 @@ symbol_new (uniqstr tag, location loc) void symbol_print (symbol *s, FILE *f) { - fprintf (f, "\"%s\"", s->tag); - SYMBOL_ATTR_PRINT (type_name); - SYMBOL_ATTR_PRINT (destructor); - SYMBOL_ATTR_PRINT (printer); + if (s) + { + fprintf (f, "\"%s\"", s->tag); + SYMBOL_ATTR_PRINT (type_name); + SYMBOL_ATTR_PRINT (destructor); + SYMBOL_ATTR_PRINT (printer); + } + else + fprintf (f, ""); } #undef SYMBOL_ATTR_PRINT diff --git a/tests/actions.at b/tests/actions.at index 3b4d05d5..33b9a4f7 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -98,6 +98,7 @@ AT_DATA_GRAMMAR([[input.y]], static int yylex (void); # define YYDEBUG 1 # define YYERROR_VERBOSE 1 +# define USE(Var) %} %union @@ -112,6 +113,7 @@ AT_DATA_GRAMMAR([[input.y]], exp: a_1 a_2 { $$ = 3; } { $$ = $3 + 1; } a_5 sum_of_the_five_previous_values { + USE (($1, $2, $5)); printf ("%d\n", $6); } ; diff --git a/tests/calc.at b/tests/calc.at index 316f71ad..81297bc4 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -54,6 +54,7 @@ AT_LALR1_CC_IF( # define alarm(seconds) /* empty */ #endif #include +#define USE(Var) /* Exercise pre-prologue dependency to %union. */ typedef int semantic_value; @@ -109,7 +110,7 @@ input: line: '\n' -| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1;])[ } +| exp '\n' { ]AT_PARAM_IF([*result = global_result = $1], [USE ($1)])[; } ; exp: diff --git a/tests/existing.at b/tests/existing.at index 27ba3123..b2626622 100644 --- a/tests/existing.at +++ b/tests/existing.at @@ -1,6 +1,6 @@ # Exercising Bison on actual grammars. -*- Autotest -*- -# Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004 +# Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify @@ -113,7 +113,6 @@ function_body | l_brace r_brace opt_semi opt_nls ; - pattern : exp | exp ',' exp @@ -325,11 +324,11 @@ variable ; l_brace - : '{' opt_nls - ; + : '{' opt_nls + ; r_brace - : '}' opt_nls + : '}' opt_nls ; r_paren @@ -358,7 +357,6 @@ AT_CHECK([[bison --verbose --defines input.y]]) AT_CLEANUP - ## ----------------- ## ## GNU Cim Grammar. ## ## ----------------- ## @@ -371,15 +369,7 @@ AT_SETUP([GNU Cim Grammar]) # It reported 80 SR && 99 RR conflicts instead of 78/10!!! AT_DATA([[input.y]], -[[%union { - long int token; - long int ival; - long int arrdim; - double rval; - char *ident; - char *tval; - char stat_decl; - } +[[%union {} %token HACTIVATE HAFTER /*HAND*/ HARRAY HAT @@ -410,18 +400,13 @@ AT_DATA([[input.y]], HADD HSUB HMUL HDIV HINTDIV HEXP HDOTDOTDOT -%token HIDENTIFIER -%token HBOOLEANKONST HINTEGERKONST HCHARACTERKONST -%token HREALKONST -%token HTEXTKONST +%token HIDENTIFIER +%token HBOOLEANKONST HINTEGERKONST HCHARACTERKONST +%token HREALKONST +%token HTEXTKONST -%type EXT_IDENT -%type DECLSTATEMENT MODULSTATEMENT MBEE_DECLSTMS MBEE_DECLSTMSU -%type MODULS -%type EXPRESSION_SIMP MBEE_ARG_R_PT -%type BAUND_PAIR_LIST -%right HASSIGN +%right HASSIGN %left HORELSE %left HANDTHEN %left HEQV @@ -431,13 +416,13 @@ AT_DATA([[input.y]], %left HNOT -%left HVALRELOPERATOR HREFRELOPERATOR HOBJRELOPERATOR +%left HVALRELOPERATOR HREFRELOPERATOR HOBJRELOPERATOR %left HCONC -%left HTERMOPERATOR -%left UNEAR -%left HFACTOROPERATOR +%left HTERMOPERATOR +%left UNEAR +%left HFACTOROPERATOR %left HPRIMARYOPERATOR %left HQUA @@ -447,55 +432,40 @@ AT_DATA([[input.y]], %start MAIN_MODULE %% /* GRAMATIKK FOR PROGRAM MODULES */ -MAIN_MODULE : { categ=CLOCAL; mout(MBLOCK); - beginBlock(KBLOKK);separat_comp=FALSE;} - MODULS { endBlock(NULL,CCNO); mout(MENDBLOCK);} +MAIN_MODULE : {} + MODULS | error HSTATEMENTSEPARATOR MBEE_DECLSTMS ; EXT_DECLARATION : HEXTERNAL MBEE_TYPE HPROCEDURE - { MBEENEWBLOCK(); - kind=KPROC;} + {} EXT_LIST | HEXTERNAL HIDENTIFIER HPROCEDURE - { MBEENEWBLOCK(); - type=TNOTY; - kind=KPROC; - if($2==Ckind)categ=CCPROC;else - yerror (1); - ysensitive=sensitive; - sensitive=ON;} - HIDENTIFIER { $$=$5; - sensitive=ysensitive;} + {} + HIDENTIFIER {} EXTERNAL_KIND_ITEM - { categ=CLOCAL;} | HEXTERNAL HCLASS - { MBEENEWBLOCK(); - kind=KCLASS;} + {} EXT_LIST ; EXTERNAL_KIND_ITEM: EXT_IDENT HOBJRELOPERATOR - { if($2!=HIS)yerror (2);} + {} MBEE_TYPE HPROCEDURE HIDENTIFIER - { regDecl($6, type, KPROC, CCPROC); - beginBlock(kind);} + {} HEADING EMPTY_BLOCK - { categ=CLOCAL; - endBlock($1==NULL?$0:tag($1),CCCPROC);} + {} /* | EXT_IDENT - { if($1!=NULL)yerror (3); - regDecl($0, type, kind, categ);} + {} MBEE_REST_EXT_LIST - { endBlock(NULL,CCNO);} ; MBEE_REST_EXT_LIST: /* EMPTY | HPAREXPSEPARATOR EXT_KIND_LIST @@ -505,8 +475,7 @@ EXT_KIND_LIST : EXT_KIND_ITEM ; EXT_KIND_ITEM : HIDENTIFIER EXT_IDENT - { if($2!=NULL)yerror (3); - regDecl($1, type, kind, categ);}*/ + {}*/ ; EMPTY_BLOCK : /*EMPT*/ | HBEGIN HEND @@ -516,31 +485,28 @@ EXT_LIST : EXT_ITEM ; EXT_ITEM : HIDENTIFIER EXT_IDENT - { lesinn_external_spec($1,$2, kind);} ; -EXT_IDENT : /* EMPTY */ { $$=NULL;} - | HVALRELOPERATOR { if($1!=HEQ)yerror (9); - external=TRUE;} - HTEXTKONST { $$=$3;external=FALSE;} +EXT_IDENT : /* EMPTY */ + | HVALRELOPERATOR {} + HTEXTKONST ; /* GRAMATIKK FOR TYPER */ -NO_TYPE : /*EMPT*/ { type=TNOTY;} +NO_TYPE : /*EMPT*/ ; MBEE_TYPE : NO_TYPE | TYPE ; TYPE : HREF HBEGPAR HIDENTIFIER - { prefquantident=$3; - type=TREF;} + {} HENDPAR - | HTEXT { type=TTEXT;} - | HBOOLEAN { type=TBOOL;} - | HCHARACTER { type=TCHAR;} - | HSHORT HINTEGER { type=TSHORT;} - | HINTEGER { type=TINTG;} - | HREAL { type=TREAL;} - | HLONG HREAL { type=TLONG;} + | HTEXT + | HBOOLEAN + | HCHARACTER + | HSHORT HINTEGER + | HINTEGER + | HREAL + | HLONG HREAL ; /* GRAMATIKK FOR DEL AV SETNINGER */ @@ -548,304 +514,169 @@ MBEE_ELSE_PART : /*EMPT*/ /* | HELSE HIF EXPRESSION - HTHEN { mout(MELSE); - mout(MIF); - OBSBLOCK();} - BLOCK { MBEEENDBLOCK();} - MBEE_ELSE_PART { mout(MENDIF);}*/ - | HELSE { OBSBLOCK(); mout(MELSE);} - BLOCK { MBEEENDBLOCK();} + HTHEN {} + BLOCK {} + MBEE_ELSE_PART {}*/ + | HELSE {} + BLOCK ; -FOR_LIST : FOR_LIST_ELEMENT { mout(MENDSEP); - mout(MLISTSEP);} +FOR_LIST : FOR_LIST_ELEMENT | FOR_LIST_ELEMENT HPAREXPSEPARATOR - FOR_LIST { mout(MLISTSEP);} + FOR_LIST ; FOR_LIST_ELEMENT: EXPRESSION MBEE_F_L_EL_R_PT ; MBEE_F_L_EL_R_PT: /*EMPT*/ | HWHILE - EXPRESSION { mout(MFORWHILE);} + EXPRESSION | HSTEP EXPRESSION HUNTIL - EXPRESSION { mout(MUNTIL); - mout(MSTEP);} + EXPRESSION ; GOTO : HGO HTO | HGOTO ; CONN_STATE_R_PT : WHEN_CLAUSE_LIST - | HDO { beginBlock(KCON); mout(MDO); - OBSBLOCK(); } - BLOCK { endBlock(NULL,CCNO); - MBEEENDBLOCK(); mout(MENDDO);} + | HDO {} + BLOCK ; WHEN_CLAUSE_LIST: HWHEN HIDENTIFIER - HDO { beginBlock(KCON); mout(MIDENTIFIER); - OBSBLOCK(); moutId($2); - mout(MWHEN);} - BLOCK { endBlock(NULL,CCNO); - MBEEENDBLOCK(); mout(MENDWHEN);} + HDO {} + BLOCK | WHEN_CLAUSE_LIST HWHEN HIDENTIFIER - HDO { beginBlock(KCON); mout(MIDENTIFIER); - OBSBLOCK(); moutId($3); - mout(MWHEN);} - BLOCK { endBlock(NULL,CCNO); - MBEEENDBLOCK(); mout(MENDWHEN);} + HDO {} + BLOCK ; MBEE_OTWI_CLAUS : /*EMPT*/ - | HOTHERWISE {OBSBLOCK(); mout(MOTHERWISE);} + | HOTHERWISE {} - BLOCK {MBEEENDBLOCK();mout(MENDOTHERWISE);} + BLOCK ; -ACTIVATOR : HACTIVATE { mout(MBOOLEANKONST); - moutIval(FALSE);} - | HREACTIVATE { mout(MBOOLEANKONST); - moutIval(TRUE);} +ACTIVATOR : HACTIVATE + | HREACTIVATE ; -SCHEDULE : /*EMPT*/ { mout(MCHARACTERKONST); - moutIval(DIRECT); - mout(MINTEGERKONST); - moutIval(0); - mout(MNONE); - mout(MBOOLEANKONST); - moutIval(FALSE);} - | ATDELAY EXPRESSION { mout(MNONE);} +SCHEDULE : /*EMPT*/ + | ATDELAY EXPRESSION {} PRIOR - | BEFOREAFTER { mout(MINTEGERKONST); - moutIval(0);} - EXPRESSION { mout(MBOOLEANKONST); - moutIval(FALSE);} + | BEFOREAFTER {} + EXPRESSION ; -ATDELAY : HAT { mout(MCHARACTERKONST); - moutIval(AT);} - | HDELAY { mout(MCHARACTERKONST); - moutIval(DELAYS);} +ATDELAY : HAT + | HDELAY ; -BEFOREAFTER : HBEFORE { mout(MCHARACTERKONST); - moutIval(BEFORE);} - | HAFTER { mout(MCHARACTERKONST); - moutIval(AFTER);} +BEFOREAFTER : HBEFORE + | HAFTER ; -PRIOR : /*EMPT*/ { mout(MBOOLEANKONST); - moutIval(FALSE);} - | HPRIOR { mout(MBOOLEANKONST); - moutIval(TRUE);} +PRIOR : /*EMPT*/ + | HPRIOR ; /* GRAMATIKK FOR SETNINGER OG DEKLARASJONER */ MODULSTATEMENT : HWHILE EXPRESSION - HDO { STOPOBSBLOCK(); mout(MWHILE); - OBSBLOCK();} - BLOCK { MBEEENDBLOCK(); mout(MENDWHILE); - $$=STATEMENT;} + HDO {} + BLOCK | HIF EXPRESSION - HTHEN { STOPOBSBLOCK(); mout(MIF); - OBSBLOCK();} - BLOCK { MBEEENDBLOCK();} - MBEE_ELSE_PART { mout(MENDIF); - $$=STATEMENT;} + HTHEN {} + BLOCK {} + MBEE_ELSE_PART | HFOR HIDENTIFIER - HASSIGN { STOPOBSBLOCK(); mout(MIDENTIFIER); - moutId($2);} + HASSIGN {} FOR_LIST - HDO { beginBlock(KFOR); - if($3==HASSIGNVALUE) mout(MFOR); - else mout(MFORR); - OBSBLOCK(); mout(MFORDO);} - BLOCK { MBEEENDBLOCK(); - endBlock(NULL,CCNO); mout(MENDFOR); - $$=STATEMENT;} + HDO {} + BLOCK | GOTO - EXPRESSION { mout(MGOTO); - STOPOBSBLOCK(); $$=STATEMENT;} + EXPRESSION | HINSPECT - EXPRESSION { mout(MINSPECT); - STOPOBSBLOCK(); - beginBlock(KINSP);} + EXPRESSION {} CONN_STATE_R_PT - { endBlock(NULL,CCNO);} - MBEE_OTWI_CLAUS { mout(MENDINSPECT); - $$=STATEMENT;} - | HINNER { STOPOBSBLOCK(); mout(MINNER); - regInner(); $$=STATEMENT;} + {} + MBEE_OTWI_CLAUS + | HINNER | HIDENTIFIER HLABELSEPARATOR - { STOPOBSBLOCK(); - regDecl($1, TLABEL, KSIMPLE, categ); mout(MLABEL); - moutId($1); - mout(MENDLABEL);} - DECLSTATEMENT { if($4<=DECLARATION) - { yerror (27); - $$=DECLARATION;} - else $$=$4;} + {} + DECLSTATEMENT | EXPRESSION_SIMP HBEGIN - { $$=$1; } + {} IMPORT_SPEC_MODULE - { mout(MPRBLOCK); - prefquantident=$1; - beginBlock(KPRBLK);} + {} MBEE_DECLSTMS - HEND { endBlock(NULL,CCNO); mout(MENDPRBLOCK); - $$=STATEMENT;} + HEND | EXPRESSION_SIMP HBEGIN error HSTATEMENTSEPARATOR - MBEE_DECLSTMS HEND { $$=STATEMENT; - endBlock(NULL,CCNO); mout(MENDPRBLOCK);} + MBEE_DECLSTMS HEND | EXPRESSION_SIMP HBEGIN error HEND - { $$=STATEMENT; - endBlock(NULL,CCNO); mout(MENDPRBLOCK);} - | EXPRESSION_SIMP - { STOPOBSBLOCK(); $$=STATEMENT; - mout(MENDASSIGN);} | ACTIVATOR EXPRESSION SCHEDULE - { $$=STATEMENT; - mout(MENDSEP); - mout(MARGUMENTSEP); - mout(MARGUMENTSEP); - mout(MARGUMENTSEP); - mout(MARGUMENTSEP); - mout(MARGUMENTSEP); - mout(MARGUMENTSEP); - mout(MARGUMENT); - moutId(activateid); - mout(MENDASSIGN);} | HBEGIN - { STOPOBSBLOCK(); - OBSBLOCK();} + {} MBEE_DECLSTMS - HEND { MBEEENDBLOCK(); $$=STATEMENT;} + HEND | MBEE_TYPE HPROCEDURE HIDENTIFIER - { MBEENEWBLOCK(); mout(MPROCEDURE); - regDecl($3, type, KPROC, categ); - beginBlock(KPROC);} - HEADING BLOCK { endBlock(NULL,CCNO); $$=DECLARATION; - mout(MENDPROCEDURE);} + {} + HEADING BLOCK | HIDENTIFIER HCLASS NO_TYPE - { $$=$1; } + {} IMPORT_SPEC_MODULE HIDENTIFIER - { prefquantident=$1; - mout(MCLASS); - regDecl($6, TNOTY, KCLASS, categ); - beginBlock(KCLASS);} + {} HEADING - BLOCK { endBlock(NULL,CCNO); $$=DECLARATION; - mout(MENDCLASS);} + BLOCK | HCLASS NO_TYPE HIDENTIFIER - { prefquantident=0; - MBEENEWBLOCK(); mout(MCLASS); - regDecl($3, TNOTY, KCLASS, categ); - beginBlock(KCLASS);} + {} HEADING - BLOCK { endBlock(NULL,CCNO); $$=DECLARATION; - mout(MENDCLASS);} - | EXT_DECLARATION { $$=EXTDECLARATION;} - | /*EMPT*/{ STOPOBSBLOCK(); $$=EMPTYSTATEMENT;} + BLOCK + | EXT_DECLARATION + | /*EMPT*/ ; -IMPORT_SPEC_MODULE: { MBEENEWBLOCK(); - kind=KCLASS; - if($0==simsetident && - findDecl(simsetident,cblock,FALSE)==NULL) - lesinn_external_spec(simsetident, - SIMSETATRFILE, kind); - if($0==simulationident && findDecl( - simulationident,cblock,FALSE)==NULL) - lesinn_external_spec(simulationident, - SIMULATIONATRFILE, kind); - if(($0==fileident && findDecl( - fileident,cblock,FALSE)==NULL) || - ($0==outfileident && findDecl( - outfileident,cblock,FALSE)==NULL) || - ($0==infileident && findDecl( - infileident,cblock,FALSE)==NULL) || - ($0==directfileident && findDecl( - directfileident,cblock,FALSE)==NULL) || - ($0==printfileident && findDecl( - printfileident,cblock,FALSE)==NULL) || - ($0==bytefileident && findDecl( - bytefileident,cblock,FALSE)==NULL) || - ($0==inbytefileident && findDecl( - inbytefileident,cblock,FALSE)==NULL) || - ($0==outbytefileident && findDecl( - outbytefileident,cblock,FALSE)==NULL) || - ($0==directbytefileident && findDecl( - directbytefileident,cblock,FALSE)==NULL)) - lesinn_external_spec(fileident, - FILEATRFILE, kind);} +IMPORT_SPEC_MODULE: ; DECLSTATEMENT : MODULSTATEMENT | TYPE HIDENTIFIER MBEE_CONSTANT HPAREXPSEPARATOR - { MBEENEWBLOCK(); - kind=KSIMPLE; - regDecl($2, type, KSIMPLE, categ); - categ=CLOCAL;} - IDENTIFIER_LISTC { $$=DECLARATION;} + {} + IDENTIFIER_LISTC | TYPE HIDENTIFIER MBEE_CONSTANT - { MBEENEWBLOCK(); - regDecl($2, type, KSIMPLE, categ); - categ=CLOCAL; $$=DECLARATION;} | MBEE_TYPE - HARRAY { MBEENEWBLOCK(); - kind=KARRAY;} - ARR_SEGMENT_LIST { $$=DECLARATION;} + HARRAY {} + ARR_SEGMENT_LIST | HSWITCH HIDENTIFIER - HASSIGN { MBEENEWBLOCK(); mout(MIDENTIFIER); - moutId($2); - regDecl($2, TLABEL, KARRAY, categ);} - SWITCH_LIST { $$=DECLARATION; - mout(MSWITCH); - mout(MENDSWITCH);} + HASSIGN {} + SWITCH_LIST ; -BLOCK : DECLSTATEMENT { if($1<=DECLARATION)yerror (29);} +BLOCK : DECLSTATEMENT | HBEGIN MBEE_DECLSTMS HEND | HBEGIN error HSTATEMENTSEPARATOR MBEE_DECLSTMS HEND | HBEGIN error HEND ; -MBEE_DECLSTMS : MBEE_DECLSTMSU { if($1<=DECLARATION)yerror (28); - $$=$1;} +MBEE_DECLSTMS : MBEE_DECLSTMSU ; -MBEE_DECLSTMSU : DECLSTATEMENT { $$=$1;} +MBEE_DECLSTMSU : DECLSTATEMENT | MBEE_DECLSTMSU HSTATEMENTSEPARATOR - DECLSTATEMENT { if($1>=STATEMENT && $3<=DECLARATION) - yerror (26); - $$=$3;} + DECLSTATEMENT ; -MODULS : MODULSTATEMENT { if($1==DECLARATION) - {separat_comp=TRUE;gettimestamp();} - $$=$1;} +MODULS : MODULSTATEMENT | MODULS HSTATEMENTSEPARATOR MODULSTATEMENT - { if($1>=STATEMENT && $3<=DECLARATION) - yerror (26);else - if($1>=STATEMENT - && $3!=EMPTYSTATEMENT)yerror (25); - if(separat_comp && $3==STATEMENT) - yerror (25); - if($3==DECLARATION && !separat_comp) - {separat_comp=TRUE;gettimestamp();} - $$=$3;} ; /* GRAMATIKK FOR DEL AV DEKLARASJONER */ ARR_SEGMENT_LIST: ARR_SEGMENT @@ -855,47 +686,35 @@ ARR_SEGMENT_LIST: ARR_SEGMENT ; ARR_SEGMENT : ARRAY_SEGMENT HBEGPAR - BAUND_PAIR_LIST HENDPAR { mout(MARRAY); - mout(MENDARRAY); - setArrayDim($3);} + BAUND_PAIR_LIST HENDPAR ; -ARRAY_SEGMENT : ARRAY_SEGMENT_EL { mout(MENDSEP); - mout(MARRAYSEP);} +ARRAY_SEGMENT : ARRAY_SEGMENT_EL {} | ARRAY_SEGMENT_EL HPAREXPSEPARATOR - ARRAY_SEGMENT { mout(MARRAYSEP);} + ARRAY_SEGMENT ; -ARRAY_SEGMENT_EL: HIDENTIFIER { mout(MIDENTIFIER); - moutId($1); - regDecl($1, type, kind, categ); - if(lastArray==NULL) - lastArray=cblock->lastparloc;} +ARRAY_SEGMENT_EL: HIDENTIFIER ; -BAUND_PAIR_LIST : BAUND_PAIR { mout(MENDSEP); - mout(MBOUNDSEP); - $$=1;} +BAUND_PAIR_LIST : BAUND_PAIR | BAUND_PAIR HPAREXPSEPARATOR - BAUND_PAIR_LIST { mout(MBOUNDSEP); - $$=$3+1;} + BAUND_PAIR_LIST ; BAUND_PAIR : EXPRESSION HLABELSEPARATOR - EXPRESSION { mout(MBOUNDPARSEP);} + EXPRESSION ; -SWITCH_LIST : EXPRESSION { mout(MENDSEP); - mout(MSWITCHSEP);} +SWITCH_LIST : EXPRESSION | EXPRESSION HPAREXPSEPARATOR - SWITCH_LIST { mout(MSWITCHSEP);} + SWITCH_LIST ; -HEADING : MBEE_FMAL_PAR_P HSTATEMENTSEPARATOR { kind=KNOKD;} - MBEE_MODE_PART { categ=CSPEC;} - MBEE_SPEC_PART { kind=KNOKD;} - MBEE_PROT_PART { categ=CVIRT;} +HEADING : MBEE_FMAL_PAR_P HSTATEMENTSEPARATOR {} + MBEE_MODE_PART {} + MBEE_SPEC_PART {} + MBEE_PROT_PART {} MBEE_VIRT_PART - { categ=CLOCAL;} ; MBEE_FMAL_PAR_P : /*EMPT*/ | FMAL_PAR_PART @@ -906,10 +725,10 @@ FMAL_PAR_PART : HBEGPAR NO_TYPE MBEE_LISTV : /*EMPT*/ | LISTV ; -LISTV : HIDENTIFIER { regDecl($1, type, KNOKD, CDEFLT);} - | FPP_CATEG HDOTDOTDOT { regDecl(varargsid, TVARARGS, KNOKD, categ);} - | HIDENTIFIER { regDecl($1, type, KNOKD, CDEFLT);} - HPAREXPSEPARATOR LISTV {} +LISTV : HIDENTIFIER + | FPP_CATEG HDOTDOTDOT + | HIDENTIFIER {} + HPAREXPSEPARATOR LISTV | FPP_SPEC | FPP_SPEC HPAREXPSEPARATOR LISTV @@ -920,36 +739,28 @@ FPP_HEADING : HBEGPAR NO_TYPE FPP_MBEE_LISTV : /*EMPT*/ | FPP_LISTV ; -FPP_LISTV : FPP_CATEG HDOTDOTDOT { regDecl(varargsid, TVARARGS, KNOKD, categ);} +FPP_LISTV : FPP_CATEG HDOTDOTDOT | FPP_SPEC | FPP_SPEC HPAREXPSEPARATOR LISTV ; FPP_SPEC : FPP_CATEG SPECIFIER HIDENTIFIER - { regDecl($3, type, kind, categ);} | FPP_CATEG FPP_PROC_DECL_IN_SPEC ; FPP_CATEG : HNAME HLABELSEPARATOR - { categ=CNAME;} | HVALUE HLABELSEPARATOR - { categ=CVALUE;} | HVAR HLABELSEPARATOR - { categ=CVAR;} - | /*EMPT*/ { categ=CDEFLT;} + | /*EMPT*/ ; FPP_PROC_DECL_IN_SPEC: MBEE_TYPE HPROCEDURE HIDENTIFIER - { $$=categ; - regDecl($3, type, KPROC, categ); - beginBlock(KPROC);} - FPP_HEADING - { categ=$4; /* M} settes tilbake*/} - { endBlock(NULL,CCNO);} + {} + FPP_HEADING {} { /* Yes, two "final" actions. */ } ; -IDENTIFIER_LISTV: HIDENTIFIER { regDecl($1, type, kind, categ);} - | HDOTDOTDOT { regDecl(varargsid, TVARARGS, kind, categ);} - | HIDENTIFIER { regDecl($1, type, kind, categ);} - HPAREXPSEPARATOR IDENTIFIER_LISTV {} +IDENTIFIER_LISTV: HIDENTIFIER + | HDOTDOTDOT + | HIDENTIFIER {} + HPAREXPSEPARATOR IDENTIFIER_LISTV ; MBEE_MODE_PART : /*EMPT*/ | MODE_PART @@ -970,15 +781,15 @@ MODE_PART : NAME_PART | VALUE_PART VAR_PART NAME_PART | VALUE_PART NAME_PART VAR_PART ; -NAME_PART : HNAME { categ=CNAME;} +NAME_PART : HNAME {} IDENTIFIER_LISTV HSTATEMENTSEPARATOR ; -VAR_PART : HVAR { categ=CVAR;} +VAR_PART : HVAR {} IDENTIFIER_LISTV HSTATEMENTSEPARATOR ; -VALUE_PART : HVALUE { categ=CVALUE;} +VALUE_PART : HVALUE {} IDENTIFIER_LISTV HSTATEMENTSEPARATOR ; MBEE_SPEC_PART : /*EMPT*/ @@ -989,32 +800,25 @@ SPEC_PART : ONE_SPEC ; ONE_SPEC : SPECIFIER IDENTIFIER_LIST HSTATEMENTSEPARATOR | NO_TYPE HPROCEDURE HIDENTIFIER HOBJRELOPERATOR - { if($4!=HIS) yerror (8);} + {} PROC_DECL_IN_SPEC HSTATEMENTSEPARATOR | FPP_PROC_DECL_IN_SPEC HSTATEMENTSEPARATOR | MBEE_TYPE HPROCEDURE HIDENTIFIER HSTATEMENTSEPARATOR - { yerror (45);} | MBEE_TYPE HPROCEDURE HIDENTIFIER HPAREXPSEPARATOR IDENTIFIER_LIST HSTATEMENTSEPARATOR - { yerror (45);} ; -SPECIFIER : TYPE { kind=KSIMPLE;} +SPECIFIER : TYPE | MBEE_TYPE - HARRAY { kind=KARRAY;} - | HLABEL { type=TLABEL; - kind=KSIMPLE;} - | HSWITCH { type=TLABEL; - kind=KARRAY;} + HARRAY + | HLABEL + | HSWITCH ; PROC_DECL_IN_SPEC: MBEE_TYPE HPROCEDURE HIDENTIFIER - { $$=categ; - regDecl($3, type, KPROC, categ); - beginBlock(KPROC);} + {} HEADING - { categ=$4; /* M} settes tilbake*/} + {} MBEE_BEGIN_END - { endBlock(NULL,CCNO);} ; MBEE_BEGIN_END : /* EMPTY */ | HBEGIN HEND @@ -1027,12 +831,12 @@ PROTECTION_PART : PROT_SPECIFIER IDENTIFIER_LIST | PROTECTION_PART PROT_SPECIFIER IDENTIFIER_LIST HSTATEMENTSEPARATOR ; -PROT_SPECIFIER : HHIDDEN { categ=CHIDEN;} - | HPROTECTED { categ=CPROT;} +PROT_SPECIFIER : HHIDDEN + | HPROTECTED | HHIDDEN - HPROTECTED { categ=CHIPRO;} + HPROTECTED | HPROTECTED - HHIDDEN { categ=CHIPRO;} + HHIDDEN ; MBEE_VIRT_PART : /*EMPT*/ | VIRTUAL_PART @@ -1041,150 +845,109 @@ VIRTUAL_PART : HVIRTUAL HLABELSEPARATOR MBEE_SPEC_PART ; -IDENTIFIER_LIST : HIDENTIFIER { regDecl($1, type, kind, categ);} +IDENTIFIER_LIST : HIDENTIFIER | IDENTIFIER_LIST HPAREXPSEPARATOR - HIDENTIFIER { regDecl($3, type, kind, categ);} + HIDENTIFIER ; IDENTIFIER_LISTC: HIDENTIFIER - MBEE_CONSTANT { regDecl($1, type, kind, categ); - categ=CLOCAL;} + MBEE_CONSTANT | IDENTIFIER_LISTC HPAREXPSEPARATOR HIDENTIFIER - MBEE_CONSTANT { regDecl($3, type, kind, categ); - categ=CLOCAL;} + MBEE_CONSTANT ; MBEE_CONSTANT : /* EMPTY */ | HVALRELOPERATOR - { MBEENEWBLOCK(); - if($1!=HEQ) yerror (8); - if(type==TREF)yerror (7); - categ=CCONSTU; - mout(MIDENTIFIER); - moutId($0);} - EXPRESSION { mout(MASSIGN); - mout(MCONST);} + {} + EXPRESSION ; /* GRAMATIKK FOR UTTRYKK */ -EXPRESSION : EXPRESSION_SIMP {} +EXPRESSION : EXPRESSION_SIMP | HIF EXPRESSION HTHEN EXPRESSION HELSE - EXPRESSION { mout(MELSEE); - mout(MIFE);} + EXPRESSION ; EXPRESSION_SIMP : EXPRESSION_SIMP HASSIGN - EXPRESSION { if($2==HASSIGNREF)mout(MASSIGNR); - else mout(MASSIGN);$$=NULL;} + EXPRESSION | EXPRESSION_SIMP HCONC - EXPRESSION_SIMP { mout(MCONC);$$=NULL;} + EXPRESSION_SIMP | EXPRESSION_SIMP HOR HELSE EXPRESSION_SIMP - %prec HORELSE { mout(MORELSEE);$$=NULL;} + %prec HORELSE | EXPRESSION_SIMP HAND HTHEN EXPRESSION_SIMP - %prec HANDTHEN { mout(MANDTHENE);$$=NULL;} + %prec HANDTHEN | EXPRESSION_SIMP - HEQV EXPRESSION_SIMP { mout(MEQV);$$=NULL;} + HEQV EXPRESSION_SIMP | EXPRESSION_SIMP - HIMP EXPRESSION_SIMP { mout(MIMP);$$=NULL;} + HIMP EXPRESSION_SIMP | EXPRESSION_SIMP - HOR EXPRESSION_SIMP { mout(MOR);$$=NULL;} + HOR EXPRESSION_SIMP | EXPRESSION_SIMP - HAND EXPRESSION_SIMP { mout(MAND);$$=NULL;} - | HNOT EXPRESSION_SIMP { mout(MNOT);$$=NULL;} + HAND EXPRESSION_SIMP + | HNOT EXPRESSION_SIMP | EXPRESSION_SIMP HVALRELOPERATOR EXPRESSION_SIMP - { switch($2) - { case HEQ: mout(MEQ);break; - case HNE: mout(MNE);break; - case HLT: mout(MLT);break; - case HLE: mout(MLE);break; - case HGT: mout(MGT);break; - case HGE: mout(MGE);break; - }$$=NULL;} | EXPRESSION_SIMP HREFRELOPERATOR EXPRESSION_SIMP - { if($2==HNER) mout(MNER); - else mout(MEQR);$$=NULL;} | EXPRESSION_SIMP HOBJRELOPERATOR EXPRESSION_SIMP - { if($2==HIS) mout(MIS); - else mout(MINS);$$=NULL;} | HTERMOPERATOR EXPRESSION_SIMP %prec UNEAR - { if($1==HADD) mout(MUADD); - else mout(MUSUB);$$=NULL;} | EXPRESSION_SIMP HTERMOPERATOR EXPRESSION_SIMP - { if($2==HADD) mout(MADD); - else mout(MSUB);$$=NULL;} | EXPRESSION_SIMP HFACTOROPERATOR EXPRESSION_SIMP - { if($2==HMUL) mout(MMUL); else - if($2==HDIV) mout(MDIV); - else mout(MINTDIV);$$=NULL;} | EXPRESSION_SIMP HPRIMARYOPERATOR - EXPRESSION_SIMP { mout(MPRIMARY);$$=NULL;} + EXPRESSION_SIMP | HBEGPAR - EXPRESSION HENDPAR { mout(MNOOP);$$=NULL;} - | HTEXTKONST { mout(MTEXTKONST); - moutTval($1);$$=NULL;} - | HCHARACTERKONST { mout(MCHARACTERKONST); - moutIval($1);$$=NULL;} - | HREALKONST { mout(MREALKONST); - moutRval($1);$$=NULL;} - | HINTEGERKONST { mout(MINTEGERKONST); - moutIval($1);$$=NULL;} - | HBOOLEANKONST { mout(MBOOLEANKONST); - moutIval($1);$$=NULL;} - | HNONE { mout(MNONE);$$=NULL;} + EXPRESSION HENDPAR + | HTEXTKONST + | HCHARACTERKONST + | HREALKONST + | HINTEGERKONST + | HBOOLEANKONST + | HNONE | HIDENTIFIER - { $$=$1;} - MBEE_ARG_R_PT {} - | HTHIS HIDENTIFIER { mout(MTHIS); - moutId($2);$$=NULL;} + {} + MBEE_ARG_R_PT + | HTHIS HIDENTIFIER | HNEW HIDENTIFIER - ARG_R_PT { mout(MNEWARG); - moutId($2);$$=NULL;} + ARG_R_PT | EXPRESSION_SIMP HDOT - EXPRESSION_SIMP { mout(MDOT);$$=NULL;} + EXPRESSION_SIMP | EXPRESSION_SIMP - HQUA HIDENTIFIER { mout(MQUA); - moutId($3);$$=NULL;} + HQUA HIDENTIFIER ; -ARG_R_PT : /*EMPTY*/ { mout(MENDSEP);} +ARG_R_PT : /*EMPTY*/ | HBEGPAR ARGUMENT_LIST HENDPAR ; -MBEE_ARG_R_PT : /*EMPTY*/ { mout(MIDENTIFIER); - moutId($0); - $$=$0;} +MBEE_ARG_R_PT : /*EMPTY*/ | HBEGPAR - ARGUMENT_LIST HENDPAR { mout(MARGUMENT); - moutId($0);} + ARGUMENT_LIST HENDPAR ; -ARGUMENT_LIST : EXPRESSION { mout(MENDSEP); - mout(MARGUMENTSEP);} +ARGUMENT_LIST : EXPRESSION | EXPRESSION HPAREXPSEPARATOR - ARGUMENT_LIST { mout(MARGUMENTSEP);} + ARGUMENT_LIST ; %% ]]) @@ -1210,7 +973,6 @@ State 427 conflicts: 9 shift/reduce, 2 reduce/reduce AT_CLEANUP - ## ----------------- ## ## GNU pic Grammar. ## ## ----------------- ## @@ -1222,32 +984,15 @@ AT_SETUP([GNU pic Grammar]) # Bison once reported shift/reduce conflicts that it shouldn't have. AT_DATA([[input.y]], -[[%union { - char *str; - int n; - double x; - struct { double x, y; } pair; - struct { double x; char *body; } if_data; - struct { char *str; const char *filename; int lineno; } lstr; - struct { double *v; int nv; int maxv; } dv; - struct { double val; int is_multiplicative; } by; - place pl; - object *obj; - corner crn; - path *pth; - object_spec *spec; - saved_state *pstate; - graphics_state state; - object_type obtype; -} - -%token LABEL -%token VARIABLE -%token NUMBER -%token TEXT -%token COMMAND_LINE -%token DELIMITED -%token ORDINAL +[[%union {} + +%token LABEL +%token VARIABLE +%token NUMBER +%token TEXT +%token COMMAND_LINE +%token DELIMITED +%token ORDINAL %token TH %token LEFT_ARROW_HEAD %token RIGHT_ARROW_HEAD @@ -1406,44 +1151,20 @@ works */ %right '!' %right '^' -%type expr any_expr text_expr -%type optional_by -%type expr_pair position_not_place -%type simple_if -%type nth_primitive -%type corner -%type path label_path relative_path -%type place label element element_list middle_element_list -%type object_spec -%type position -%type object_type -%type optional_ordinal_last ordinal -%type until -%type sprintf_args -%type text print_args print_arg - %% top: optional_separator | element_list - { - if (olist.head) - print_picture(olist.head); - } ; - element_list: optional_separator middle_element_list optional_separator - { $$ = $2; } ; middle_element_list: element - { $$ = $1; } | middle_element_list separator element - { $$ = $1; } ; optional_separator: @@ -1458,844 +1179,191 @@ separator: placeless_element: VARIABLE '=' any_expr - { - define_variable($1, $3); - a_delete $1; - } | VARIABLE ':' '=' any_expr - { - place *p = lookup_label($1); - if (!p) { - lex_error("variable `%1' not defined", $1); - YYABORT; - } - p->obj = 0; - p->x = $4; - p->y = 0.0; - a_delete $1; - } | UP - { current_direction = UP_DIRECTION; } | DOWN - { current_direction = DOWN_DIRECTION; } | LEFT - { current_direction = LEFT_DIRECTION; } | RIGHT - { current_direction = RIGHT_DIRECTION; } | COMMAND_LINE - { - olist.append(make_command_object($1.str, $1.filename, - $1.lineno)); - } | COMMAND print_args - { - olist.append(make_command_object($2.str, $2.filename, - $2.lineno)); - } | PRINT print_args - { - fprintf(stderr, "%s\n", $2.str); - a_delete $2.str; - fflush(stderr); - } | SH - { delim_flag = 1; } + {} DELIMITED - { - delim_flag = 0; - if (safer_flag) - lex_error("unsafe to run command `%1'", $3); - else - system($3); - a_delete $3; - } | COPY TEXT - { - if (yychar < 0) - do_lookahead(); - do_copy($2.str); - // do not delete the filename - } | COPY TEXT THRU - { delim_flag = 2; } + {} DELIMITED - { delim_flag = 0; } + {} until - { - if (yychar < 0) - do_lookahead(); - copy_file_thru($2.str, $5, $7); - // do not delete the filename - a_delete $5; - a_delete $7; - } | COPY THRU - { delim_flag = 2; } + {} DELIMITED - { delim_flag = 0; } + {} until - { - if (yychar < 0) - do_lookahead(); - copy_rest_thru($4, $6); - a_delete $4; - a_delete $6; - } | FOR VARIABLE '=' expr TO expr optional_by DO - { delim_flag = 1; } + {} DELIMITED - { - delim_flag = 0; - if (yychar < 0) - do_lookahead(); - do_for($2, $4, $6, $7.is_multiplicative, $7.val, $10); - } | simple_if - { - if (yychar < 0) - do_lookahead(); - if ($1.x != 0.0) - push_body($1.body); - a_delete $1.body; - } | simple_if ELSE - { delim_flag = 1; } + {} DELIMITED - { - delim_flag = 0; - if (yychar < 0) - do_lookahead(); - if ($1.x != 0.0) - push_body($1.body); - else - push_body($4); - a_delete $1.body; - a_delete $4; - } | reset_variables | RESET - { define_variable("scale", 1.0); } ; reset_variables: RESET VARIABLE - { - reset($2); - a_delete $2; - } | reset_variables VARIABLE - { - reset($2); - a_delete $2; - } | reset_variables ',' VARIABLE - { - reset($3); - a_delete $3; - } ; print_args: print_arg - { $$ = $1; } | print_args print_arg - { - $$.str = new char[strlen($1.str) + strlen($2.str) + 1]; - strcpy($$.str, $1.str); - strcat($$.str, $2.str); - a_delete $1.str; - a_delete $2.str; - if ($1.filename) { - $$.filename = $1.filename; - $$.lineno = $1.lineno; - } - else if ($2.filename) { - $$.filename = $2.filename; - $$.lineno = $2.lineno; - } - } ; print_arg: expr %prec ',' - { - $$.str = new char[GDIGITS + 1]; - sprintf($$.str, "%g", $1); - $$.filename = 0; - $$.lineno = 0; - } | text - { $$ = $1; } | position %prec ',' - { - $$.str = new char[GDIGITS + 2 + GDIGITS + 1]; - sprintf($$.str, "%g, %g", $1.x, $1.y); - $$.filename = 0; - $$.lineno = 0; - } ; simple_if: IF any_expr THEN - { delim_flag = 1; } + {} DELIMITED - { - delim_flag = 0; - $$.x = $2; - $$.body = $5; - } ; until: /* empty */ - { $$ = 0; } | UNTIL TEXT - { $$ = $2.str; } ; any_expr: expr - { $$ = $1; } | text_expr - { $$ = $1; } ; text_expr: text EQUALEQUAL text - { - $$ = strcmp($1.str, $3.str) == 0; - a_delete $1.str; - a_delete $3.str; - } | text NOTEQUAL text - { - $$ = strcmp($1.str, $3.str) != 0; - a_delete $1.str; - a_delete $3.str; - } | text_expr ANDAND text_expr - { $$ = ($1 != 0.0 && $3 != 0.0); } | text_expr ANDAND expr - { $$ = ($1 != 0.0 && $3 != 0.0); } | expr ANDAND text_expr - { $$ = ($1 != 0.0 && $3 != 0.0); } | text_expr OROR text_expr - { $$ = ($1 != 0.0 || $3 != 0.0); } | text_expr OROR expr - { $$ = ($1 != 0.0 || $3 != 0.0); } | expr OROR text_expr - { $$ = ($1 != 0.0 || $3 != 0.0); } | '!' text_expr - { $$ = ($2 == 0.0); } ; - optional_by: /* empty */ - { - $$.val = 1.0; - $$.is_multiplicative = 0; - } | BY expr - { - $$.val = $2; - $$.is_multiplicative = 0; - } | BY '*' expr - { - $$.val = $3; - $$.is_multiplicative = 1; - } ; element: object_spec - { - $$.obj = $1->make_object(¤t_position, - ¤t_direction); - if ($$.obj == 0) - YYABORT; - delete $1; - if ($$.obj) - olist.append($$.obj); - else { - $$.x = current_position.x; - $$.y = current_position.y; - } - } | LABEL ':' optional_separator element - { - $$ = $4; - define_label($1, & $$); - a_delete $1; - } | LABEL ':' optional_separator position_not_place - { - $$.obj = 0; - $$.x = $4.x; - $$.y = $4.y; - define_label($1, & $$); - a_delete $1; - } | LABEL ':' optional_separator place - { - $$ = $4; - define_label($1, & $$); - a_delete $1; - } - | '{' - { - $$.x = current_position.x; - $$.y = current_position.y; - $$.dir = current_direction; - } - element_list '}' - { - current_position.x = $2.x; - current_position.y = $2.y; - current_direction = $2.dir; - } + | '{}' + {} optional_element - { - $$ = $3; - } | placeless_element - { - $$.obj = 0; - $$.x = current_position.x; - $$.y = current_position.y; - } ; optional_element: /* empty */ - {} | element - {} ; object_spec: BOX - { $$ = new object_spec(BOX_OBJECT); } | CIRCLE - { $$ = new object_spec(CIRCLE_OBJECT); } | ELLIPSE - { $$ = new object_spec(ELLIPSE_OBJECT); } | ARC - { - $$ = new object_spec(ARC_OBJECT); - $$->dir = current_direction; - } | LINE - { - $$ = new object_spec(LINE_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } | ARROW - { - $$ = new object_spec(ARROW_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } | MOVE - { - $$ = new object_spec(MOVE_OBJECT); - lookup_variable("moveht", & $$->segment_height); - lookup_variable("movewid", & $$->segment_width); - $$->dir = current_direction; - } | SPLINE - { - $$ = new object_spec(SPLINE_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } | text %prec TEXT - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item($1.str, $1.filename, $1.lineno); - } | PLOT expr - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item(format_number(0, $2), 0, -1); - } | PLOT expr text - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item(format_number($3.str, $2), - $3.filename, $3.lineno); - a_delete $3.str; - } | '[' - { - saved_state *p = new saved_state; - $$ = p; - p->x = current_position.x; - p->y = current_position.y; - p->dir = current_direction; - p->tbl = current_table; - p->prev = current_saved_state; - current_position.x = 0.0; - current_position.y = 0.0; - current_table = new PTABLE(place); - current_saved_state = p; - olist.append(make_mark_object()); - } + {} element_list ']' - { - current_position.x = $2->x; - current_position.y = $2->y; - current_direction = $2->dir; - $$ = new object_spec(BLOCK_OBJECT); - olist.wrap_up_block(& $$->oblist); - $$->tbl = current_table; - current_table = $2->tbl; - current_saved_state = $2->prev; - delete $2; - } | object_spec HEIGHT expr - { - $$ = $1; - $$->height = $3; - $$->flags |= HAS_HEIGHT; - } | object_spec RADIUS expr - { - $$ = $1; - $$->radius = $3; - $$->flags |= HAS_RADIUS; - } | object_spec WIDTH expr - { - $$ = $1; - $$->width = $3; - $$->flags |= HAS_WIDTH; - } | object_spec DIAMETER expr - { - $$ = $1; - $$->radius = $3/2.0; - $$->flags |= HAS_RADIUS; - } | object_spec expr %prec HEIGHT - { - $$ = $1; - $$->flags |= HAS_SEGMENT; - switch ($$->dir) { - case UP_DIRECTION: - $$->segment_pos.y += $2; - break; - case DOWN_DIRECTION: - $$->segment_pos.y -= $2; - break; - case RIGHT_DIRECTION: - $$->segment_pos.x += $2; - break; - case LEFT_DIRECTION: - $$->segment_pos.x -= $2; - break; - } - } | object_spec UP - { - $$ = $1; - $$->dir = UP_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y += $$->segment_height; - } | object_spec UP expr - { - $$ = $1; - $$->dir = UP_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y += $3; - } | object_spec DOWN - { - $$ = $1; - $$->dir = DOWN_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y -= $$->segment_height; - } | object_spec DOWN expr - { - $$ = $1; - $$->dir = DOWN_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y -= $3; - } | object_spec RIGHT - { - $$ = $1; - $$->dir = RIGHT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $$->segment_width; - } | object_spec RIGHT expr - { - $$ = $1; - $$->dir = RIGHT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $3; - } | object_spec LEFT - { - $$ = $1; - $$->dir = LEFT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x -= $$->segment_width; - } | object_spec LEFT expr - { - $$ = $1; - $$->dir = LEFT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x -= $3; - } | object_spec FROM position - { - $$ = $1; - $$->flags |= HAS_FROM; - $$->from.x = $3.x; - $$->from.y = $3.y; - } | object_spec TO position - { - $$ = $1; - if ($$->flags & HAS_SEGMENT) - $$->segment_list = new segment($$->segment_pos, - $$->segment_is_absolute, - $$->segment_list); - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x = $3.x; - $$->segment_pos.y = $3.y; - $$->segment_is_absolute = 1; - $$->flags |= HAS_TO; - $$->to.x = $3.x; - $$->to.y = $3.y; - } | object_spec AT position - { - $$ = $1; - $$->flags |= HAS_AT; - $$->at.x = $3.x; - $$->at.y = $3.y; - if ($$->type != ARC_OBJECT) { - $$->flags |= HAS_FROM; - $$->from.x = $3.x; - $$->from.y = $3.y; - } - } | object_spec WITH path - { - $$ = $1; - $$->flags |= HAS_WITH; - $$->with = $3; - } | object_spec WITH position %prec ',' - { - $$ = $1; - $$->flags |= HAS_WITH; - position pos; - pos.x = $3.x; - pos.y = $3.y; - $$->with = new path(pos); - } | object_spec BY expr_pair - { - $$ = $1; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $3.x; - $$->segment_pos.y += $3.y; - } | object_spec THEN - { - $$ = $1; - if ($$->flags & HAS_SEGMENT) { - $$->segment_list = new segment($$->segment_pos, - $$->segment_is_absolute, - $$->segment_list); - $$->flags &= ~HAS_SEGMENT; - $$->segment_pos.x = $$->segment_pos.y = 0.0; - $$->segment_is_absolute = 0; - } - } | object_spec SOLID - { - $$ = $1; // nothing - } | object_spec DOTTED - { - $$ = $1; - $$->flags |= IS_DOTTED; - lookup_variable("dashwid", & $$->dash_width); - } | object_spec DOTTED expr - { - $$ = $1; - $$->flags |= IS_DOTTED; - $$->dash_width = $3; - } | object_spec DASHED - { - $$ = $1; - $$->flags |= IS_DASHED; - lookup_variable("dashwid", & $$->dash_width); - } | object_spec DASHED expr - { - $$ = $1; - $$->flags |= IS_DASHED; - $$->dash_width = $3; - } | object_spec FILL - { - $$ = $1; - $$->flags |= IS_DEFAULT_FILLED; - } | object_spec FILL expr - { - $$ = $1; - $$->flags |= IS_FILLED; - $$->fill = $3; - } | object_spec SHADED text - { - $$ = $1; - $$->flags |= (IS_SHADED | IS_FILLED); - $$->shaded = new char[strlen($3.str)+1]; - strcpy($$->shaded, $3.str); - } | object_spec COLORED text - { - $$ = $1; - $$->flags |= (IS_SHADED | IS_OUTLINED | IS_FILLED); - $$->shaded = new char[strlen($3.str)+1]; - strcpy($$->shaded, $3.str); - $$->outlined = new char[strlen($3.str)+1]; - strcpy($$->outlined, $3.str); - } | object_spec OUTLINED text - { - $$ = $1; - $$->flags |= IS_OUTLINED; - $$->outlined = new char[strlen($3.str)+1]; - strcpy($$->outlined, $3.str); - } | object_spec CHOP - { - $$ = $1; - // line chop chop means line chop 0 chop 0 - if ($$->flags & IS_DEFAULT_CHOPPED) { - $$->flags |= IS_CHOPPED; - $$->flags &= ~IS_DEFAULT_CHOPPED; - $$->start_chop = $$->end_chop = 0.0; - } - else if ($$->flags & IS_CHOPPED) { - $$->end_chop = 0.0; - } - else { - $$->flags |= IS_DEFAULT_CHOPPED; - } - } | object_spec CHOP expr - { - $$ = $1; - if ($$->flags & IS_DEFAULT_CHOPPED) { - $$->flags |= IS_CHOPPED; - $$->flags &= ~IS_DEFAULT_CHOPPED; - $$->start_chop = 0.0; - $$->end_chop = $3; - } - else if ($$->flags & IS_CHOPPED) { - $$->end_chop = $3; - } - else { - $$->start_chop = $$->end_chop = $3; - $$->flags |= IS_CHOPPED; - } - } | object_spec SAME - { - $$ = $1; - $$->flags |= IS_SAME; - } | object_spec INVISIBLE - { - $$ = $1; - $$->flags |= IS_INVISIBLE; - } | object_spec LEFT_ARROW_HEAD - { - $$ = $1; - $$->flags |= HAS_LEFT_ARROW_HEAD; - } | object_spec RIGHT_ARROW_HEAD - { - $$ = $1; - $$->flags |= HAS_RIGHT_ARROW_HEAD; - } | object_spec DOUBLE_ARROW_HEAD - { - $$ = $1; - $$->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD); - } | object_spec CW - { - $$ = $1; - $$->flags |= IS_CLOCKWISE; - } | object_spec CCW - { - $$ = $1; - $$->flags &= ~IS_CLOCKWISE; - } | object_spec text %prec TEXT - { - $$ = $1; - text_item **p; - for (p = & $$->text; *p; p = &(*p)->next) - ; - *p = new text_item($2.str, $2.filename, $2.lineno); - } | object_spec LJUST - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.h = LEFT_ADJUST; - } - } | object_spec RJUST - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.h = RIGHT_ADJUST; - } - } | object_spec ABOVE - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.v = ABOVE_ADJUST; - } - } | object_spec BELOW - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.v = BELOW_ADJUST; - } - } | object_spec THICKNESS expr - { - $$ = $1; - $$->flags |= HAS_THICKNESS; - $$->thickness = $3; - } | object_spec ALIGNED - { - $$ = $1; - $$->flags |= IS_ALIGNED; - } ; text: TEXT - { $$ = $1; } | SPRINTF '(' TEXT sprintf_args ')' - { - $$.filename = $3.filename; - $$.lineno = $3.lineno; - $$.str = do_sprintf($3.str, $4.v, $4.nv); - a_delete $4.v; - a_delete $3.str; - } ; sprintf_args: /* empty */ - { - $$.v = 0; - $$.nv = 0; - $$.maxv = 0; - } | sprintf_args ',' expr - { - $$ = $1; - if ($$.nv >= $$.maxv) { - if ($$.nv == 0) { - $$.v = new double[4]; - $$.maxv = 4; - } - else { - double *oldv = $$.v; - $$.maxv *= 2; - $$.v = new double[$$.maxv]; - memcpy($$.v, oldv, $$.nv*sizeof(double)); - a_delete oldv; - } - } - $$.v[$$.nv] = $3; - $$.nv += 1; - } ; position: position_not_place - { $$ = $1; } | place - { - position pos = $1; - $$.x = pos.x; - $$.y = pos.y; - } ; position_not_place: expr_pair - { $$ = $1; } | position '+' expr_pair - { - $$.x = $1.x + $3.x; - $$.y = $1.y + $3.y; - } | position '-' expr_pair - { - $$.x = $1.x - $3.x; - $$.y = $1.y - $3.y; - } | '(' position ',' position ')' - { - $$.x = $2.x; - $$.y = $4.y; - } | expr between position AND position - { - $$.x = (1.0 - $1)*$3.x + $1*$5.x; - $$.y = (1.0 - $1)*$3.y + $1*$5.y; - } | expr '<' position ',' position '>' - { - $$.x = (1.0 - $1)*$3.x + $1*$5.x; - $$.y = (1.0 - $1)*$3.y + $1*$5.y; - } ; between: @@ -2305,443 +1373,147 @@ between: expr_pair: expr ',' expr - { - $$.x = $1; - $$.y = $3; - } | '(' expr_pair ')' - { $$ = $2; } ; place: /* line at A left == line (at A) left */ label %prec CHOP - { $$ = $1; } | label corner - { - path pth($2); - if (!pth.follow($1, & $$)) - YYABORT; - } | corner label - { - path pth($1); - if (!pth.follow($2, & $$)) - YYABORT; - } | corner OF label - { - path pth($1); - if (!pth.follow($3, & $$)) - YYABORT; - } | HERE - { - $$.x = current_position.x; - $$.y = current_position.y; - $$.obj = 0; - } ; label: LABEL - { - place *p = lookup_label($1); - if (!p) { - lex_error("there is no place `%1'", $1); - YYABORT; - } - $$ = *p; - a_delete $1; - } | nth_primitive - { $$.obj = $1; } | label '.' LABEL - { - path pth($3); - if (!pth.follow($1, & $$)) - YYABORT; - } ; ordinal: ORDINAL - { $$ = $1; } | '`' any_expr TH - { - // XXX Check for overflow (and non-integers?). - $$ = (int)$2; - } ; optional_ordinal_last: LAST - { $$ = 1; } | ordinal LAST - { $$ = $1; } ; nth_primitive: ordinal object_type - { - int count = 0; - object *p; - for (p = olist.head; p != 0; p = p->next) - if (p->type() == $2 && ++count == $1) { - $$ = p; - break; - } - if (p == 0) { - lex_error("there is no %1%2 %3", $1, ordinal_postfix($1), - object_type_name($2)); - YYABORT; - } - } | optional_ordinal_last object_type - { - int count = 0; - object *p; - for (p = olist.tail; p != 0; p = p->prev) - if (p->type() == $2 && ++count == $1) { - $$ = p; - break; - } - if (p == 0) { - lex_error("there is no %1%2 last %3", $1, - ordinal_postfix($1), object_type_name($2)); - YYABORT; - } - } ; object_type: BOX - { $$ = BOX_OBJECT; } | CIRCLE - { $$ = CIRCLE_OBJECT; } | ELLIPSE - { $$ = ELLIPSE_OBJECT; } | ARC - { $$ = ARC_OBJECT; } | LINE - { $$ = LINE_OBJECT; } | ARROW - { $$ = ARROW_OBJECT; } | SPLINE - { $$ = SPLINE_OBJECT; } | '[' ']' - { $$ = BLOCK_OBJECT; } | TEXT - { $$ = TEXT_OBJECT; } ; label_path: '.' LABEL - { $$ = new path($2); } | label_path '.' LABEL - { - $$ = $1; - $$->append($3); - } ; relative_path: corner %prec CHOP - { $$ = new path($1); } /* give this a lower precedence than LEFT and RIGHT so that [A: box] with .A left == [A: box] with (.A left) */ | label_path %prec TEXT - { $$ = $1; } | label_path corner - { - $$ = $1; - $$->append($2); - } ; path: relative_path - { $$ = $1; } | '(' relative_path ',' relative_path ')' - { - $$ = $2; - $$->set_ypath($4); - } + {} /* The rest of these rules are a compatibility sop. */ | ORDINAL LAST object_type relative_path - { - lex_warning("`%1%2 last %3' in `with' argument ignored", - $1, ordinal_postfix($1), object_type_name($3)); - $$ = $4; - } | LAST object_type relative_path - { - lex_warning("`last %1' in `with' argument ignored", - object_type_name($2)); - $$ = $3; - } | ORDINAL object_type relative_path - { - lex_warning("`%1%2 %3' in `with' argument ignored", - $1, ordinal_postfix($1), object_type_name($2)); - $$ = $3; - } | LABEL relative_path - { - lex_warning("initial `%1' in `with' argument ignored", $1); - a_delete $1; - $$ = $2; - } ; corner: DOT_N - { $$ = &object::north; } | DOT_E - { $$ = &object::east; } | DOT_W - { $$ = &object::west; } | DOT_S - { $$ = &object::south; } | DOT_NE - { $$ = &object::north_east; } | DOT_SE - { $$ = &object:: south_east; } | DOT_NW - { $$ = &object::north_west; } | DOT_SW - { $$ = &object::south_west; } | DOT_C - { $$ = &object::center; } | DOT_START - { $$ = &object::start; } | DOT_END - { $$ = &object::end; } | TOP - { $$ = &object::north; } | BOTTOM - { $$ = &object::south; } | LEFT - { $$ = &object::west; } | RIGHT - { $$ = &object::east; } | UPPER LEFT - { $$ = &object::north_west; } | LOWER LEFT - { $$ = &object::south_west; } | UPPER RIGHT - { $$ = &object::north_east; } | LOWER RIGHT - { $$ = &object::south_east; } | LEFT_CORNER - { $$ = &object::west; } | RIGHT_CORNER - { $$ = &object::east; } | UPPER LEFT_CORNER - { $$ = &object::north_west; } | LOWER LEFT_CORNER - { $$ = &object::south_west; } | UPPER RIGHT_CORNER - { $$ = &object::north_east; } | LOWER RIGHT_CORNER - { $$ = &object::south_east; } | NORTH - { $$ = &object::north; } | SOUTH - { $$ = &object::south; } | EAST - { $$ = &object::east; } | WEST - { $$ = &object::west; } | CENTER - { $$ = &object::center; } | START - { $$ = &object::start; } | END - { $$ = &object::end; } ; expr: VARIABLE - { - if (!lookup_variable($1, & $$)) { - lex_error("there is no variable `%1'", $1); - YYABORT; - } - a_delete $1; - } | NUMBER - { $$ = $1; } | place DOT_X - { - if ($1.obj != 0) - $$ = $1.obj->origin().x; - else - $$ = $1.x; - } | place DOT_Y - { - if ($1.obj != 0) - $$ = $1.obj->origin().y; - else - $$ = $1.y; - } | place DOT_HT - { - if ($1.obj != 0) - $$ = $1.obj->height(); - else - $$ = 0.0; - } | place DOT_WID - { - if ($1.obj != 0) - $$ = $1.obj->width(); - else - $$ = 0.0; - } | place DOT_RAD - { - if ($1.obj != 0) - $$ = $1.obj->radius(); - else - $$ = 0.0; - } | expr '+' expr - { $$ = $1 + $3; } | expr '-' expr - { $$ = $1 - $3; } | expr '*' expr - { $$ = $1 * $3; } | expr '/' expr - { - if ($3 == 0.0) { - lex_error("division by zero"); - YYABORT; - } - $$ = $1/$3; - } | expr '%' expr - { - if ($3 == 0.0) { - lex_error("modulus by zero"); - YYABORT; - } - $$ = fmod($1, $3); - } | expr '^' expr - { - errno = 0; - $$ = pow($1, $3); - if (errno == EDOM) { - lex_error("arguments to `^' operator out of domain"); - YYABORT; - } - if (errno == ERANGE) { - lex_error("result of `^' operator out of range"); - YYABORT; - } - } | '-' expr %prec '!' - { $$ = -$2; } | '(' any_expr ')' - { $$ = $2; } | SIN '(' any_expr ')' - { - errno = 0; - $$ = sin($3); - if (errno == ERANGE) { - lex_error("sin result out of range"); - YYABORT; - } - } | COS '(' any_expr ')' - { - errno = 0; - $$ = cos($3); - if (errno == ERANGE) { - lex_error("cos result out of range"); - YYABORT; - } - } | ATAN2 '(' any_expr ',' any_expr ')' - { - errno = 0; - $$ = atan2($3, $5); - if (errno == EDOM) { - lex_error("atan2 argument out of domain"); - YYABORT; - } - if (errno == ERANGE) { - lex_error("atan2 result out of range"); - YYABORT; - } - } | LOG '(' any_expr ')' - { - errno = 0; - $$ = log10($3); - if (errno == ERANGE) { - lex_error("log result out of range"); - YYABORT; - } - } | EXP '(' any_expr ')' - { - errno = 0; - $$ = pow(10.0, $3); - if (errno == ERANGE) { - lex_error("exp result out of range"); - YYABORT; - } - } | SQRT '(' any_expr ')' - { - errno = 0; - $$ = sqrt($3); - if (errno == EDOM) { - lex_error("sqrt argument out of domain"); - YYABORT; - } - } | K_MAX '(' any_expr ',' any_expr ')' - { $$ = $3 > $5 ? $3 : $5; } | K_MIN '(' any_expr ',' any_expr ')' - { $$ = $3 < $5 ? $3 : $5; } | INT '(' any_expr ')' - { $$ = floor($3); } | RAND '(' any_expr ')' - { $$ = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*$3); } | RAND '(' ')' - { - /* return a random number in the range >=0, <1 */ - /* portable, but not very random */ - $$ = (rand() & 0x7fff) / double(0x8000); - } | SRAND '(' any_expr ')' - { - $$ = 0; - srand((unsigned int)$3); - } | expr '<' expr - { $$ = ($1 < $3); } | expr LESSEQUAL expr - { $$ = ($1 <= $3); } | expr '>' expr - { $$ = ($1 > $3); } | expr GREATEREQUAL expr - { $$ = ($1 >= $3); } | expr EQUALEQUAL expr - { $$ = ($1 == $3); } | expr NOTEQUAL expr - { $$ = ($1 != $3); } | expr ANDAND expr - { $$ = ($1 != 0.0 && $3 != 0.0); } | expr OROR expr - { $$ = ($1 != 0.0 || $3 != 0.0); } | '!' expr - { $$ = ($2 == 0.0); } - ; ]]) diff --git a/tests/glr-regression.at b/tests/glr-regression.at index abaec703..ad8f6d86 100644 --- a/tests/glr-regression.at +++ b/tests/glr-regression.at @@ -746,13 +746,14 @@ AT_SETUP([No users destructors if stack 0 deleted]) AT_DATA_GRAMMAR([glr-regr9.y], [[ %{ - #include - #include +# include +# include static void yyerror (char const *); static int yylex (void); - #define YYSTACKEXPANDABLE 0 +# define YYSTACKEXPANDABLE 0 static int tokens = 0; static int destructors = 0; +# define USE(Var) %} %glr-parser @@ -766,7 +767,7 @@ AT_DATA_GRAMMAR([glr-regr9.y], %% start: - ambig0 'a' { destructors += 2; } + ambig0 'a' { destructors += 2; USE ($2); } | ambig1 start { destructors += 1; } | ambig2 start { destructors += 1; } ; -- 2.47.2