/* file: additive.java author: Robert Keller purpose: Tutorial additive expression parser The program reads an additive expression and shows its tree as an S expr. compile and run: java -cs additive Your CLASSPATH must include a directory containing the polya library. A -> V { '+' V } sum V -> a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z In the grammar { }, means 0 or more of what's inside. */ import polya.*; import java.io.*; class additive // additive parser class { static public void main(String arg[]) // USER INTERFACE { LineBufferInputStream in = new LineBufferInputStream(System.in); while( prompt() && !in.eof() ) { String input = in.getLine(); additive parser = new additive(input); Object result = parser.parse(); System.out.println("result: " + result); System.out.println(); } System.out.println(); } Object A() // PARSE FUNCTION for A -> V { '+' V } { Object result; Object V1 = V(); if( isFailure(V1) ) return failure; result = V1; while( peek() == '+' ) { nextChar(); Object V2 = V(); if( isFailure(V2) ) return failure; result = Polylist.list("+", result, V2); } return result; } // PARSE FUNCTION for V -> a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z Object V() { if( isVar(peek()) ) { return (new StringBuffer(1).append(nextChar())).toString(); } return failure; } Object parse() // TOP LEVEL: parse with check for residual input { Object result = A(); skipWhitespace(); if( position < lastPosition ) { System.out.print("*** Residual characters after input: "); while( !eof ) { char c = nextChar(); System.out.print(c); } System.out.println(); } return result; } // isVar indicates whether its argument is a variable boolean isVar(char c) { switch( c ) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': return true; default: return false; } } // SUPPORT CODE static String promptString = "input: "; // prompt string static ParseFailure failure = new ParseFailure(); // failure String input; // input to parser int position; // position of current character int lastPosition; // last position in input string boolean eof; // end-of-file condition exists additive(String input) // constructor for parser { this.input = input; // initialize variables dealing with string position = -1; lastPosition = input.length()-1; eof = lastPosition == -1; } char nextChar() // get next character in input { if( position >= lastPosition ) { eof = true; return ' '; } return input.charAt(++position); } char peek() // return, but retain, next character { if( position >= lastPosition ) { return ' '; } return input.charAt(position+1); } void putBack() // put previously read character back { if( position >= 0 ) { position--; } } void skipWhitespace() // skip whitespace { while( !eof && peek() == ' ' ) { nextChar(); } } boolean isFailure(Object ob) // test for failure { return ob instanceof ParseFailure; } static boolean prompt() { System.out.print(promptString); System.out.flush(); return true; } } // class additive // ParseFailure object is used to indicate a parse failure class ParseFailure { } // LineBufferInputStream is an input stream capable of reading one line // at a time and returning the line as a string, by calling method getLine(). // It also provides the method eof() for testing for end-of-file. class LineBufferInputStream extends PushbackInputStream { /** * LineBufferInputStream constructs from an InputStream **/ LineBufferInputStream(InputStream in) { super(in); } /** * getLine() gets the next line of input **/ String getLine() { StringBuffer b = new StringBuffer(); try { int c; while( !eof() && ((c = read()) != '\n') ) { b.append((char)c); } return b.toString(); } catch( java.io.IOException e ) { handleException("getLine", e); return ""; } } /** * eof() tells whether end-of-file has been reached. **/ public boolean eof() { try { int c = read(); if( c == -1 ) { return true; } else { unread(c); return false; } } catch( IOException e ) { handleException("eof", e); } return false; } /** * handleException is called when there is an IOException in any method. **/ public void handleException(String method, IOException e) { System.out.println("IOException in LineBufferInputStream: " + e + " calling method " + method); } }