Prover/Parser.pizza
changeset 96 907b1fff5637
equal deleted inserted replaced
95:345dd18f020e 96:907b1fff5637
       
     1 package G4ip;
       
     2 
       
     3 import java.util.*;
       
     4 import pizza.lang.Pair;
       
     5 import G4ip.Form.*;
       
     6 import G4ip.Token.*;
       
     7 
       
     8 public class Token {
       
     9   public static final int AND = 0;
       
    10   public static final int OR  = 1;
       
    11   public static final int IMP = 2;
       
    12   public static final int EQU = 3;
       
    13 
       
    14   /** End-of-Input */
       
    15   public case EOI();             // end-of-input
       
    16   public case LPAREN();
       
    17   public case RPAREN();
       
    18   public case ID(String id);
       
    19   public case FALSE();
       
    20   public case BINOP(int op);     // binary operation
       
    21   public case COMMA();
       
    22 }
       
    23 
       
    24 /** A left-to-right, rightmost-derivation parser.<p> 
       
    25   * The following grammar is implemented:<p>
       
    26   * <dl>
       
    27   * <dd><u>Formula</u> ::= <u>Id</u>                             </dd>
       
    28   * <dd><code>| false</code>                                     </dd>
       
    29   * <dd><code>|</code> ( <u>Formula</u> )                        </dd>         
       
    30   * <dd><code>|</code> <u>Formula</u> <u>Binop</u> <u>Formula</u></dd>  
       
    31   * </dl><p>
       
    32   * <dl>
       
    33   * <dd><u>Id</u> is a string of lower case letters</dd>
       
    34   * </dl><p>
       
    35   * <dl>
       
    36   * <dd><u>Binop</u> is either <code>&, v, -></code> or <code><-></code></dd>
       
    37   * </dl><p>
       
    38   * <dl>
       
    39   * <dd><u>FormulaList</u> ::=  <em>empty</em></dd>
       
    40   * <dd><code>|</code> [ <u>FormulaList</u> ,]* <u>Formula</u></dd>
       
    41   * <dl><p>
       
    42   * The parser uses a stack where two actions are performed:
       
    43   * <dl>
       
    44   * <dd><b>shift</b> moves the next token to the top of the stack (getNextToken)</dd>
       
    45   * <dd><b>reduce</b> chooses a grammar rule, X -> A B C; pops A, B, C from the 
       
    46   *                   top of the stack and pushes X onto the stack  
       
    47   * </dl>
       
    48   * @author      Christian Urban
       
    49   */       
       
    50 public class Parser {
       
    51   final Pair<String,Token> keywords[] = 
       
    52           { new Pair("(",    LPAREN()),
       
    53 	    new Pair(")",    RPAREN()),
       
    54 	    new Pair(",",    COMMA()),
       
    55 	    new Pair("&",    BINOP(Token.AND)),
       
    56 	    new Pair("v ",   BINOP(Token.OR)),
       
    57 	    new Pair("->",   BINOP(Token.IMP)),
       
    58             new Pair("<->",  BINOP(Token.EQU)),
       
    59 	    new Pair("false",FALSE()) };
       
    60   String in;     // string to be parsed
       
    61   int index;     // position of the current input
       
    62   Stack stack;   // stack for the left-to-right parser 'LR(0)'
       
    63   
       
    64   public Parser(String init_in){
       
    65     index = 0;
       
    66     in = init_in;
       
    67     stack = new Stack();
       
    68   }
       
    69 
       
    70   /** tokens are: identifiers<code>( ) , & v -> <-> false</code> 
       
    71     *             and <code>EOI</code> <em>(end of input)</em> 
       
    72     */
       
    73   public Token getNextToken() throws Exception {
       
    74     while ( index < in.length() && Character.isSpace(in.charAt(index)) ) 
       
    75           { index++; }                                //delete  white-spaces  
       
    76     if (index == in.length()) { return EOI(); }       //end-of-string  
       
    77     for (int i=0;i<keywords.length;i++)               //keywords
       
    78       { if (in.startsWith(keywords[i].fst,index)) {
       
    79 	   index=index+keywords[i].fst.length();
       
    80 	   return keywords[i].snd;
       
    81         }
       
    82       }
       
    83     if (Character.isLowerCase(in.charAt(index)) || Character.isDigit(in.charAt(index))) 
       
    84       {     //reads identifiers
       
    85       String s = ""; 
       
    86       while ( index < in.length() && 
       
    87               (    Character.isLowerCase(in.charAt(index))
       
    88                 || Character.isDigit(in.charAt(index))
       
    89               ) 
       
    90             ) 
       
    91 	{ s=s.concat(in.substring(index,index+1)); 
       
    92           index++;
       
    93         }
       
    94       return ID(s);
       
    95     }
       
    96     throw new Exception("Syntax error at: '" + in.charAt(index)  + "'");   
       
    97                // no match at all: probably an unknown character
       
    98     return null;
       
    99   }
       
   100 
       
   101   /** Implements the grammar rules. */
       
   102   public void reduce()
       
   103     { boolean again = false;
       
   104       /*   ID  -> Atm(string)  */
       
   105       if (stack.size() > 0 && 
       
   106 	 (stack.elementAt(stack.size()-1) instanceof ID))
       
   107 	    { ID id = (ID)stack.pop();
       
   108 	      stack.push(Atm(id.id));
       
   109 	      again = true;
       
   110 	    } 
       
   111       /*  FALSE -> False()   */
       
   112       if (stack.size() > 0 && 
       
   113 	  (stack.elementAt(stack.size()-1) instanceof FALSE))
       
   114 	    { stack.pop();
       
   115 	      stack.push(False());
       
   116 	      again = true;
       
   117 	    } 
       
   118       /*   ( Formula )  -> Formula  */ 
       
   119       if (stack.size() > 2 &&
       
   120 	  (stack.elementAt(stack.size()-3) instanceof LPAREN) &&
       
   121 	  (stack.elementAt(stack.size()-2) instanceof Form)   &&
       
   122 	  (stack.elementAt(stack.size()-1) instanceof RPAREN))
       
   123 	    {  stack.pop();
       
   124                Form form = (Form)stack.pop(); 
       
   125                stack.pop();
       
   126                stack.push(form);
       
   127                again = true;
       
   128             }   
       
   129       /*   Formula BINOP Formula  -> Formula  */
       
   130       if (stack.size() > 2 &&
       
   131 	  (stack.elementAt(stack.size()-3) instanceof Form)  &&
       
   132 	  (stack.elementAt(stack.size()-2) instanceof BINOP) &&
       
   133 	  (stack.elementAt(stack.size()-1) instanceof Form))
       
   134 	    {  Form  c2 = (Form)stack.pop();
       
   135                BINOP op = (BINOP)stack.pop();
       
   136                Form  c1 = (Form)stack.pop(); 
       
   137                switch(op.op) {
       
   138 	       case Token.AND: stack.push(new And(c1,c2)); again = true;break;
       
   139                case Token.OR:  stack.push(new Or(c1,c2));  again = true;break; 
       
   140 	       case Token.IMP: stack.push(new Imp(c1,c2)); again = true;break;
       
   141                case Token.EQU: stack.push(new And(Imp(c1,c2),Imp(c2,c1))); again = true;break;
       
   142 	       }
       
   143             }  
       
   144       if (again == true) { reduce(); }  // do as many "reduces" as possible 
       
   145     }
       
   146 
       
   147   /** parses a single formula
       
   148     */
       
   149   public Form parseFormula() throws Exception {
       
   150     Token tok;
       
   151     while (!((tok = getNextToken()) instanceof EOI)) {
       
   152       stack.push(tok);
       
   153       reduce();
       
   154     }
       
   155     if (stack.size() == 1 &&
       
   156        (stack.elementAt(stack.size()-1) instanceof Form))
       
   157        { return (Form)stack.pop(); } 
       
   158     else throw new Exception("Grammar error");
       
   159     return null;  
       
   160   }
       
   161 
       
   162   /** parses a list of formulae separated by commas
       
   163     */
       
   164   public Context parseFormulae() throws Exception {
       
   165     Token tok;
       
   166     Context erg = new Context();
       
   167     while (!((tok = getNextToken()) instanceof EOI)) {
       
   168       stack.push(tok);
       
   169       reduce();
       
   170     }
       
   171     if (stack.empty()) return erg;  // LHS can be empty  !!
       
   172     stack.push(new COMMA());
       
   173     for(int i=0;i<stack.size()-1;i=i+2){
       
   174       if (stack.elementAt(i)  instanceof Form)
       
   175 	{ erg.addElement(stack.elementAt(i));
       
   176 	}  else throw new Exception("Grammar error");
       
   177       if (stack.elementAt(i+1) instanceof COMMA)
       
   178         {} else throw new Exception("Grammar error");
       
   179     }
       
   180     return erg;
       
   181   }
       
   182 
       
   183 }