yyerror: called upon a parser error
	receives one string arg
#define	YYERROR_VERBOSE produces a more interesting string
	will attempt recovery, if that fails, then yyparse returns 1.
yynerrs

****

Actions in midrule
	may refer to the elemenst so far
	the mid-rule action counts as a component (for $n)
	can have a value, but must use $<type> notation
	cannot set value of entire rule

****

How bison parsers work:


expr:     term '+' expr
        | term
        ;

term:     '(' expr ')'
        | term '!'
        | NUMBER
        ;

with input 1 + 2

yychar is the lookahead token, if you want it.

****

if-then-else is a shift/reduce conflict
operator precedence situations are shift/reduce
	each rule gets a precedence from the last terminal mentioned in
		its components
default is shift

****

%prec modifies the precedence of a particular rule; you say %prec OP
after a rule, and it assigns the precedence of OP to that rule.

****

more serious:
reduce/reduce confilcts

sequence: /* empty */
                { printf ("empty sequence\n"); }
        | maybeword
        | sequence word
                { printf ("added word %s\n", $2); }
        ;

maybeword: /* empty */
                { printf ("empty maybeword\n"); }
        | word
                { printf ("single word %s\n", $1); }
        ;

(multiple ways to parse a single word into a sequence
	word -> maybeword -> sequence
	eps word -> sequence word -> sequence

Fix with:

sequence: /* empty */
                { printf ("empty sequence\n"); }
        | sequence word
                { printf ("added word %s\n", $2); }
        ;


reduce/reduce #2:

sequence: /* empty */
        | sequence words
        | sequence redirects
        ;

words:    /* empty */
        | words word
        ;

redirects:/* empty */
        | redirects redirect
        ;

(epsilon could be `words' or, two worsd, or three, or a redirects, or many.)

Fix with:


sequence: /* empty */
        | sequence word
        | sequence redirect
        ;

Or fix with:


sequence: /* empty */
        | sequence words
        | sequence redirects
        ;

words:    word
        | words word
        ;

redirects:redirect
        | redirects redirect
        ;


mysterious reduce/reduce conflicts usu. indicate non-LALR(1)

****

Complete list of declarations:
%token NAME
%token NAME value
%token <type> NAME

%left
%right
%nonassoc
	later has higher precedence; 
	all declared together have equal precedence
	nonassoc causes the conflict to become a syntax error


%type defines nonterminal types

%expect N

%start

%pure_parser  produces a re-entrant parser

%no_lines

%raw
%token_table

-p renames external variables

****

Error recovery:

   pop elements from stack until an error token can be shifted,
   then read tokens until one is acceptible.


stmnts:  /* empty string */
        | stmnts '\n'
        | stmnts exp '\n'
        | stmnts error '\n'

One common strategy is to look for end of statement (as above, or ; in C)

Also match close delimiters with rules like

exp:	'(' expr ')'
	| '(' error ')'
	...
	;

Cascades: (consider spurious semi in middle of statement)
	no error messages for additional errors until three tokens have
	been successfully shifted

	yyerrok turns error messages back on.

	yyclearin: if you read input yourself in an error token, then
	the parser's lookahead will be wrong; use yyclearin to toss
	the previous lookahead token.

YYRECOVERING (1 or 0) marks error-messages-off.

****

Building syntax trees
	1: why?
	2: how
	3: partial ways of doing it

****

Homework 1:
	turn calculator into an infix calculator
2:	recognize variable names and assignments
3:	do arrays
4:	turn calculator into a syntax tree thingie
5: 	add a looping construct

extra: turn C into syntax trees
	(continue to ignore typedef)
