11.7. Some Samples for SFL

%{
#include "ast"
…
%}

%token          TOK_DEF
%token          TOK_END
%token <strval> TOK_ID
%token <intval> TOK_NUMBER

%left <intval> TOK_ADDOP
%left <intval> TOK_MULOP

/* The following are needed by 
 * expr : expr expr 
 */

%nonassoc TOK_ID  TOK_NUMBER  '['   

%left     JUXTAPOSITION

%type <ast>      expr
%type <strlist>  idlist
%type <exprlist> exprlist

%%

/*-------------------------------------
 * program reads all of the definitions 
 * and starts the interpreter.
 *-------------------------------------*/

program	: definitions
              {runInterpreter();
              }
        ;

/*-------------------------------------
 * definitions gets all of the
 * definitions and stores each into 
 * the symbol table.
 *-------------------------------------*/

definitions: /*empty*/
              {}

           | definitions  definition
              {}
           ;

/*-------------------------------------
 * definition matches a single
 * definition, which it stores into 
 * the symbol table.
 *-------------------------------------*/

definition : TOK_DEF  idlist  '='  expr  TOK_END
               {installDefinition($2, $4);
               }
           ;

/*-------------------------------------
 * idlist matches a sequence of
 * identifiers, without any separation.
 * Its attribute is a linked list of
 * the identifiers backwards.
 * For example, if the list is
 *     a b c
 * then the attribute of idlist is
 *     ["c", "b", "a"]
 *-------------------------------------*/

idlist     : /* empty */
               {$$ = NULL;
               }

           | idlist  TOK_ID
               {$$ = strCons($2, $1);
               }
           ;

/*-------------------------------------
 * expr matches an expression.  It's
 * attribute is an abstract syntax tree
 * that represents the expression.
 *-------------------------------------*/

expr       : TOK_ID
               {$$ = identifierNode($1);
               }

           | TOK_NUMBER
               {$$ = integerConstant($1);
               }

           | expr  expr  %prec JUXTAPOSITION
               {$$ = applyNode($1, $2);
               }

           | expr  TOK_MULOP  expr
               {$$ = operatorNode($2, $1, $3);
               }

           | expr  TOK_ADDOP  expr
               {$$ = operatorNode($2, $1, $3);
               }

           | '['  ']'
               {$$ = emptyList();
               }

           | '['  exprlist  ']'
               {$$ = listAST($2);
               }

…
           ;

/*-------------------------------------
 * exprlist matches a list of exprs,
 * separated by commas.  
 *
 * It's attribute is a linked list of
 * the ASTs for the exprs, in forward
 * order.
 *-------------------------------------*/

exprlist   : expr
               {$$ = exprCons($1, NULL);
               }

           | expr  ','  exprlist
               {$$ = exprCons($1, $3);
               }
           ;
%%

/*-------------------------------------
 * installDefinition(lhs, body)
 * converts a definition into form
 *
 *    def id = expr end
 *
 * and stores pair (id, expr) into the
 * symbol table.
 *
 * For example, it converts definition
 *
 *   def a b c = body end
 *
 * into
 *
 *   def a = b -> (c -> body) end
 *
 * lhs is the list of ids on the
 * left-hand side backwards.
 * For 
 *
 *   def a b c = body end
 *
 * lis is ["c", "b", "a"].
 *-------------------------------------*/

void installDefinition(IDLIST lhs, AST body)
{
  AST newbody = body;

  for(IDLIST p = lhs; p->next != NULL; p = p->next)
  {
    newbody = functionNode(p->item, newBody);
  }
  insertSymbolTable(p->item, newbody);
  freelist(lhs);
}