%{
/* vim: set tw=0 et: */

// .dat file parser
//
// Copyright 2001, KUN.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

// $Id: parser.y,v 1.11 2006/04/12 16:00:23 olafs Exp $

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif // HAVE_CONFIG_H

using namespace std;
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "globtables.h"   /* for rule_table */
#include "parserinterface.h"

extern char* yytext;
extern void yyerror(char*);
extern int yylex();

/* quick fix problem in /usr/local/gnu/lib/bison/yacc.c */
#undef __GNUC_MINOR__
%}

%token COMMENT 
%token NUMBER IDPART DOUBLECOLON COLON PERIOD
%token COMMA SEMICOLON OPENPAR CLOSEPAR VBAR STRING AMPERSAND SLASH
%token OPENGUARD CLOSEGUARD OPENOPT CLOSEOPT PERIODNUMBER NEWLINE

%union {
    char* chars;
    EntryList* EntryListPtr;
    IDList* ids;
    Param* param_ptr;
    pParam p_param;
    MyParamList* params;
    string* string_ptr;
    long number;
}

%type <chars> STRING
%type <number> NUMBER
%type <ids> aff_term_list
%type <param_ptr> aff_denotation
%type <params> paramlist
%type <p_param> params opt_params
%type <EntryListPtr> nont
%type <string_ptr> identifier IDPART

%%

lexicon: lex_module_body
       ;

identifier: identifier IDPART
                {
                    *($1) += " " + *($2);
                    delete $2;
                    $$ = $1;
                }
          | IDPART
                {
                    $$ = $1;
                }
          ;

lex_module_body: rules
               ;

rules: rules rule
     |
     ;

rule: term_rule
    | NEWLINE
    ;

/* affix terminals: */

aff_denotation: STRING
                    {
                        ID id = idtable.add($1);
                        free($1);
                        $$ = new Param(TextType, id);
                    }
              | NUMBER                  { $$ = new Param($1); }
              | aff_term_list           { $$ = affterms_to_param($1); }
              ;

aff_term_list: aff_term_list VBAR identifier
                                        { $$ = aff_terml_add($1, $3); }
             | identifier               { $$ = aff_terml_new($1); }
             ;


/* parameter packs: */

opt_params: params                      { $$ = $1; }
          |                             { $$ = NULL; }
          ;

params: OPENPAR paramlist CLOSEPAR      { $$ = build_params($2); }
      ;

paramlist: paramlist COMMA aff_denotation
            {
                ($1)->push_front($3);
                $$ = $1;
            }
         | aff_denotation
            {
                MyParamList* params = new MyParamList;
                params->push_front($1);
                $$ = params;
            }
         ;


/* terminal rules: */

term_rule: STRING nont NEWLINE
            {
                rule_table.enter($1, *($2));
                delete $2;
                free($1);
            }
         ;

nont: identifier opt_params             { $$ = nont_def($1, $2, 0); }
    | identifier opt_params NUMBER      { $$ = nont_def($1, $2, $3); }
    ;
      
%%

void yyerror(char* s)
{
    parser_error = s;
}
