
Changes by Dan (Spring Break 1999):
* How should we do the path in files.c so it doesn't have to be changed
  on installation? Probably an environment variable, but which one?
* Similarly, the Makefile had an absolute path I had to change.
* Makefile also failed on bison.s1 target, but I just ignored it.
* Replaced private with static to be current with popcorn.
  (Maybe private shouldn't be a keyword anymore.)
  Files: output.c and pop_bison.simple
* Also had parse error until I took "public" out of pop_bison.simple.

To do:
* Remove "#define short int" once we fully support short.
  Put explicit coercions in as necessary.
  Files: reader.c, pop_bison.simple
* Generated header file doesn't include other files as necessary.  Maybe it
  shouldn't, though.  Anyway, it means you can't just blithely include it.
  We could just throw any types abstractly that "appear free" in the file --
  that's the only headache I ran up against.
* Header File needs #ifndef stuff
Suggestion:
* Since we have exceptions, use them exclusively instead of requiring a 
  yyerror function to be imported.

Using bison:

1. I've only tested this in the simplest of configurations.  Many things
(like location stuff) has not been tested and is most likely broken.  
In particular, the PURE support (re-entrant) is not done, and nor has
the bison.hairy parse engine been ported.

2. I'm explicitly defining short to be int within reader.c until we have
support for shorts.  

3. I'm explicitly checking "(x)>0 && (x) <= %d" instead of "((unsigned)(x)) <= 
%d" within output until we have support for unsigned comparisons.

4. Here's a sample grammar for reverse-polish notation.  Note that we
more or less follow exactly the same conventions as in the C version.
You translate it to popcorn code with:

  bison -d rpcalc.y

This produces two files rpcalc_tab.pop and rpcalc_tab.h.  The .h file
is suitable for including within a lexer or some other tool.  The parser
contains all of the tables as well as the parse engine.  It's invoked
by calling yyparse() which in turn calls yylex() expecting that yylex()
produces an integer token and a semantic value in yylval.

The type of yylval is specified with the %union declaration.  This is
required for us (but optional for C-bison.)  The syntax for the union
declaration does not mention the type -- it becomes YYSTYPE.  Note that
this union should have as its initial field something that can be used
at top level for initialization.  For instance, the union should not
be polymorphic and the first field should carry a type (such as int,
bool, void, ?struct, etc.) that has a default value.

One declares tokens using the %token <id> notation as in bison.

One declares the type of tokens (terminals) and non-terminals
using %type <field> t1 t2 ... tn where <field> is a field of
the union type, and t1,t2,...,tn are [non-]terminals.  

The grammar rules work just as in bison/yacc.  The biggest difference
is within the actions of the grammar rules.  In particular, $$ refers
to yylval.  Because it's declared to be of type YYSTYPE, anything
that goes into $$ should have this type.  If you use it as an r-value,
then you probably need to switch on it or use the new union projection
(e.g., $$.foo).  

$1 $2 and so forth continue to refer to the semantic elements of the rule.
They are translated as (yysv[yysvp_offset-i]).<field> where <field> is
associated with that particular terminal/non-terminal in a %type declaration.
That is, a reference to $1 will implicitly "downcast" to the "type"
of the [non-]terminal.  

Some new syntax is ^$.  This is essentially translated to ^YYSTYPE.<field>
where <field> is the field name of the union associated with $$ (i.e.,
the rule's left-hand-side.)

So for instance, in the grammar below, for the "+" case, we have as the
action:

	exp : exp exp '+' { $$ = ^$($1 + $2); }

The $1 gets the exp value.  Since exp is associated with the foo label
of the union, this means that the semantic value is cast to "int" from
YYSTYPE.  Similarly for $2.  The default semantic value would be there
for the token '+'.  Anyway, because $1 and $2 are automatically cast
to integers, we can add them to produce an integer.  But we can't
just place the result in $$ -- rather, we have to "cast up", hence
the ^$ wrapped around the expression.
---file rpcalc.y--------------------------------------------------------------
%{
extern void print_string(string);
extern int print_int(int);
%}

%union {
  int    foo;
  short    x;
}

%token NUM 
%type <foo> exp NUM
%type <x> line input

%% /* Grammar rules and actions follow */

input:   /*empty*/      { $$ = ^$(3); }
        | input line   { $$ = ^$(4); }
;

line:   '\n'       { $$ = ^$(6); }
        | exp '\n' { print_string ("RESULT=");
	             print_int($1);
		     $$ = ^$(5); }
;

exp:    NUM { $$ = ^$($1); }
        | exp exp '+' { $$ = ^$($1 + $2); }
        | exp exp '-' { $$ = ^$($1 - $2); }
        | exp exp '*' { $$ = ^$($1 - $2); }

;
%%
------------------------------------------------------------------------------
Another example is in scheme.y which is a very simple s-expression 
parser.  It's teamed with a file scheme_lex.pop that serves as the
lexer to see how things get linked together.  
