(* Parser for clause lists in Prolog format.
   Copyright (C) 2003 Jean Goubault-Larrecq and LSV, CNRS UMR 8643 & ENS Cachan.

   This file is part of h1.

   h1 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, or (at your option)
   any later version.

   h1 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with h1; see the file COPYING.  If not, write to
   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*)

%{
  %}

%header {
open "gclause_h";
%}

%union {
  plnone of unit
| plclauselist of string gclause list
| plclause of string gclause
| plterm of string term
| pltermlist of string term list
| plstring of string
}

%start problem

%type <plclauselist> problem clause_list
%type <plclause> clause
%type <pltermlist> clause_body non_empty_clause_body
%type <plterm> atom term application
%type <pltermlist> term_list

%token <plstring> identifier
%token kw_open_paren kw_close_paren kw_provided kw_comma kw_period kw_question_mark
%token <plstring> VAR
%token kw_false

%%

problem : clause_list { $$ (rev ($1)) }
;

clause_list : { $$ nil }
| clause_list clause { $$ ($2 :: $1) }
;

clause : kw_question_mark clause_body kw_period
{ $$ (GCLAUSE (rev $2, nil)) }
| atom kw_provided clause_body kw_period
{ $$ (GCLAUSE (rev $3, [$1])) }
| atom kw_period
{ $$ (GCLAUSE (nil, [$1])) }
| false_head kw_provided clause_body kw_period
{ $$ (GCLAUSE (rev $3, nil)) }
| false_head kw_period
{ $$ (GCLAUSE (nil, nil)) }
;

clause_body : { $$ nil }
| non_empty_clause_body { $$ $1 }
;

non_empty_clause_body : atom { $$ [$1] }
| non_empty_clause_body kw_comma atom { $$ ($3::$1) }
;

false_head : kw_false
| kw_false kw_open_paren identifier kw_close_paren
;

atom : identifier kw_open_paren term_list kw_close_paren { $$ ($1 $ (rev $3)) }
| identifier term { $$ ($1 $ [$2]) }
| identifier { $$ ($1 $ nil) }
;

term_list : term { $$ [$1] }
| term_list kw_comma term { $$ ($3 :: $1) }
;

term : VAR { $$ (V $1) }
| application { $$ $1 }
;

application : identifier kw_open_paren term_list kw_close_paren { $$ ($1 $ (rev $3)) }
| identifier { $$ ($1 $ nil) }
;
