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