|
Term.grm
|
// FILE. . . . . /home/hak/ilt/doc/ilog/jacc/term.grm // EDIT BY . . . Hassan Ait-Kaci // ON MACHINE. . Latitude407.Ilog.Biz // STARTED ON. . Tue Dec 14 18:20:30 2004 // Last modified on Mon Dec 20 18:41:07 2004 by hak
|
This example is a Jacc specification of an interactive parser for
Prolog terms (and thus for Prolog). It illustrates the use of dynamic
operators and how to specify top-down undo semantic actions. The parser
repeatedly reads a term from the standard input, prints its canonical
form - i.e., f(t1, ... ,tn). All
Prolog dynamic operators are predefined, but may be redefined at parse
time. New dynamic operators may also be defined and redefined at parse
time as well.
|
/*
* Declarations
*/
%import java.util.*;
%start Session
%token NUMBER FUNCTOR
%dynamic Op // Prolog operator category
%Op ':-' 1200 xfx
%Op ':-' 1200 fx
%Op '-->' 1200 xfx
%Op ';' 1100 xfy
%Op ',' 1000 xfy
%Op '=' 700 xfx
%Op '\\=' 700 xfx
%Op '==' 700 xfx
%Op '\\==' 700 xfx
%Op '=..' 700 xfx
%Op 'is' 700 xfx
%Op '=:=' 700 xfx
%Op '=\\=' 700 xfx
%Op '<' 700 xfx
%Op '<=' 700 xfx
%Op '>' 700 xfx
%Op '>=' 700 xfx
%Op '+' 500 yfx
%Op '-' 500 yfx
%Op '*' 400 yfx
%Op '/' 400 yfx
%Op '&' 200 xfy
%Op '^' 200 xfy
%Op '-' 200 fy
// we add, with lesser precedence that relational operators's (700):
%Op if 800 fx // if X ==> if(X)
%Op then 850 xfy // X then Y ==> then(X,Y)
%Op else 820 xfx // X else Y ==> else(X,Y)
// THEREFORE // if C then T else E ==> then(if(C),else(T,E))
// Note that // if A then B ==> then(if(A),B).
// However // if A then B else if C then D else E.
// parses as // ==> then(if(A),then(else(B,if(C)),else(D,E)))
// instead of// ==> then(if(A),else(B,then(if(C),else(D,E))))
// which is // if A then B else (if C then D else E).
%{
Stack terms = new Stack();
Term term, temp;
%}
%%
/*
* Production rules
*/
Session
: Clauses Exit
| Exit
;
Exit
: 'exit'
{
System.out.println("*** Bye bye!...");
System.exit(0);
} '.'
;
Clauses
: Clause
| Clauses Clause
;
Clause
:
{ /* Bottom-up reduction semantic action: */
terms = new Stack();
}
Term
{ /* Bottom-up reduction semantic action: */
term = (Term)terms.pop();
// Operator (re)definition:
if (term.functor != null && term.functor.equals("op")
&& term.body != null && term.body.size() == 3)
{
try
{
Op(((Term)term.body.get(2)).functor,
((Term)term.body.get(1)).functor,
(int)((Term)term.body.get(0)).number);
}
catch (Exception e)
{
System.err.println("*** Bad op declaration: "+term);
}
}
out.println(term.toString()); // print out the term's canonical form
cutAll(); // delete all pending token choices
TermTokenizer.prompt();
} '.'
| error
{
errorManager().reportErrors(true);
TermTokenizer.prompt();
} '.'
;
Op : FUNCTOR
;
Term
: NUMBER
{ /* Bottom-up reduction semantic action: */
terms.push($1.isInteger() ? new Term((int)$1.nvalue())
: new Term($1.nvalue()));
}
{ /* Top-down undo semantic action: */
terms.pop();
}
| Op
{ /* Bottom-up reduction semantic action: */
terms.push(new Term($1.svalue()));
}
{ /* Top-down undo semantic action: */
terms.pop();
}
| Op '('
{ /* Bottom-up reduction semantic action: */
terms.push(new Term($1.svalue(),new Vector()));
}
{ /* Top-down undo semantic action: */
terms.pop();
}
Body ')'
| OP_
{ /* Bottom-up reduction semantic action: */
terms.push(new Term($1.svalue(),new Vector()));
}
{ /* Top-down undo semantic action: */
terms.pop();
}
Term
{ /* Bottom-up reduction semantic action: */
term = (Term)terms.pop();
((Term)terms.peek()).body.add(term);
}
{ /* Top-down undo semantic action: */
temp = (Term)terms.peek();
term = (Term)temp.body.lastElement();
temp.body.removeElementAt(temp.body.size()-1);
terms.push(term);
}
| Term _OP_
{ /* Bottom-up reduction semantic action: */
term = (Term)terms.pop();
terms.push(new Term($2.svalue(),new Vector()));
((Term)terms.peek()).body.add(term);
}
{ /* Top-down undo semantic action: */
temp = (Term)terms.pop();
term = (Term)temp.body.lastElement();
terms.push(term);
}
Term
{ /* Bottom-up reduction semantic action: */
term = (Term)terms.pop();
((Term)terms.peek()).body.add(term);
}
{ /* Top-down undo semantic action: */
temp = (Term)terms.peek();
term = (Term)temp.body.lastElement();
temp.body.removeElementAt(temp.body.size()-1);
terms.push(term);
}
| Term _OP
{ /* Bottom-up reduction semantic action: */
term = (Term)terms.pop();
terms.push(new Term($2.svalue(),new Vector()));
((Term)terms.peek()).body.add(term);
}
{ /* Top-down undo semantic action: */
temp = (Term)terms.pop();
term = (Term)temp.body.lastElement();
terms.push((Term)temp.body.lastElement());
}
| '(' Term ')'
;
Body
: Term
{ /* Bottom-up reduction semantic action: */
term = (Term)terms.pop();
((Term)terms.peek()).body.add(term);
}
{ /* Top-down undo semantic action: */
temp = (Term)terms.peek();
term = (Term)temp.body.lastElement();
temp.body.removeElementAt(temp.body.size()-1);
terms.push(term);
}
| Body ',' Term
{ /* Bottom-up reduction semantic action: */
term = (Term)terms.pop();
((Term)terms.peek()).body.add(term);
}
{ /* Top-down undo semantic action: */
temp = (Term)terms.peek();
term = (Term)temp.body.lastElement();
temp.body.removeElementAt(temp.body.size()-1);
terms.push(term);
}
;
%%
| Ancillary classes |
class Term
{
String functor = null;
Vector body = null;
double number = Double.NaN;
boolean isInteger = false;
Term (double n)
{
number = n;
}
Term (int n)
{
number = n;
isInteger = true;
}
Term (String functor)
{
this.functor = functor;
}
Term (String functor, Vector body)
{
this.functor = functor;
this.body = body;
}
public final boolean isNumber ()
{
return !Double.isNaN(number);
}
public final boolean hasBody ()
{
return (body != null && !body.isEmpty());
}
public String toString ()
{
if (isNumber())
return(isInteger ? String.valueOf((int)number)
: String.valueOf(number));
if (!hasBody())
return functor;
StringBuffer s = new StringBuffer(functor);
s.append("(");
for (int i=0; i<body.size(); i++)
{
s.append(body.get(i));
if (i<body.size()-1) s.append(",");
}
s.append(")");
return s.toString();
}
}
This file was generated on Mon Dec 20 19:03:12 PST 2004 from file Term.grm
by the ilog.language.tools.Hilite Java tool written by Hassan Aït-Kaci