// This file is from Tucker and Noonan's web site, with // the changes noted below. // // I made the following changes: // (1) I removed a useless import. // (2) I updated all the places that use Tokens to correspond // with how we previously changed the Token class. // (3) I added "throws IOException" throughout to correspond // with our previous addition of this to TokenStream's // nextToken method, and I imported this from java.io. // (4) I corrected the comment at the start of the method "statements". // // You should make the following changes: // (1) Fill in the missing pieces marked "...". // (2) Add a main method for testing. // (a) First, this main should create a TokenStream, // just like in the testing main in that class. // (b) Then it should make a ConcreteSyntax using // that TokenStream. // (c) Next it should ask the ConcreteSyntax to // parse a Program. // (d) Finally, it should print out the Program; this // printing will use the toString() method of the Program. // (3) Once everything else is working, fix one gap in // the syntax checking -- right now, there can be extra // tokens after the '}' that ends the program. Add an // error message if not at EOF after the '}'. // // There are plenty of other improvements you could make // if you feel like it, particularly in how this class interfaces // to the various AST classes. import java.io.IOException; public class ConcreteSyntax { // Recursive descent parser that inputs a Jay program and // generates its abstract syntax. Each method corresponds to // a concrete syntax grammar rule, which appears as a comment // at the beginning of the method. Token token; // current token from the input stream TokenStream input; public ConcreteSyntax(TokenStream ts) throws IOException { // Open the Jay source program input = ts; // as a TokenStream, and token = input.nextToken(); // retrieve its first Token } private void match (String s) throws IOException { if (token.getValue().equals(s)) token = input.nextToken(); else SyntaxError(s); } public Program program() throws IOException { // Program --> void main ( ) '{' Declarations Statements '}' String[] header = {"void", "main", "(", ")"}; Program p = new Program(); for (int i=0; i { Declaration }* Declarations ds = new Declarations (); while (token.getValue().equals("int") || token.getValue().equals("boolean")) { declaration(ds); } return ds; } private void declaration (Declarations ds) throws IOException { // Declaration --> Type Identifiers ; Type t = type(); identifiers(ds, t); match(";"); } private Type type () throws IOException { // Type --> int | boolean Type t = null; if (token.getValue().equals("int")) t = new Type(token.getValue()); else if (token.getValue().equals("boolean")) t = new Type(token.getValue()); else SyntaxError("int | boolean"); token = input.nextToken(); // pass over the type return t; } private void identifiers (Declarations ds, Type t) throws IOException { // Identifiers --> Identifier { , Identifier }* Declaration d = new Declaration (); // first declaration d.t = t; // its type if (token.getType() == Token.Type.IDENTIFIER) { d.v = new Variable(); d.v.id = token.getValue(); // its value ds.addElement(d); token = input.nextToken(); while (token.getValue().equals(",")) { d = new Declaration (); // next declaration d.t = t; // its type token = input.nextToken(); if (token.getType() == Token.Type.IDENTIFIER) { d.v = new Variable(); // its value d.v.id = token.getValue(); ds.addElement(d); token = input.nextToken(); // get "," or ";" } else SyntaxError("Identifier"); } } else SyntaxError("Identifier"); } private Statement statement() throws IOException { // Statement --> ; | Block | Assignment | IfStatement | WhileStatement Statement s = new Skip(); if (token.getValue().equals(";")) { // Skip token = input.nextToken(); return s; } else if (token.getValue().equals("{")) { // Block token = input.nextToken(); s = statements(); match("}"); } else if (token.getValue().equals("if")) // IfStatement s = ifStatement(); else if (token.getValue().equals("while")) // WhileStatement s = whileStatement(); else if (token.getType() == Token.Type.IDENTIFIER) // Assignment s = assignment(); else SyntaxError("Statement"); return s; } private Block statements () throws IOException { // Statements --> { Statement }* Block b = new Block(); ... return b; } private Assignment assignment () throws IOException { // Assignment --> Identifier = Expression ; Assignment a = new Assignment(); if (token.getType() == Token.Type.IDENTIFIER) { a.target = new Variable(); a.target.id = token.getValue(); token = input.nextToken(); match("="); a.source = expression(); match(";"); } else SyntaxError("Identifier"); return a; } private Expression expression () throws IOException { // Expression --> Conjunction { || Conjunction }* Binary b; Expression e; e = conjunction(); while (token.getValue().equals("||")) { b = new Binary(); b.term1 = e; b.op = new Operator(token.getValue()); token = input.nextToken(); b.term2 = conjunction(); e = b; } return e; } private Expression conjunction () throws IOException { // Conjunction --> Relation { && Relation }* Binary b; Expression e; ... return e; } private Expression relation () throws IOException { // Relation --> Addition [ < | <= | > | >= | == | != ] Addition }* Binary b; Expression e; ... return e; } private Expression addition () throws IOException { // Addition --> Term { [ + | - ] Term }* Binary b; Expression e; e = term(); while (token.getValue().equals("+") || token.getValue().equals("-")) { b = new Binary(); b.term1 = e; b.op = new Operator(token.getValue()); token = input.nextToken(); b.term2 = term(); e = b; } return e; } private Expression term () throws IOException { // Term --> Negation { [ '*' | / ] Negation }* Binary b; Expression e; ... return e; } private Expression negation() throws IOException { // Negation --> { ! }opt Factor Unary u; if (token.getValue().equals("!")) { u = new Unary(); u.op = new Operator(token.getValue()); token = input.nextToken(); u.term = factor(); return u; } else return factor(); } private Expression factor () throws IOException { // Factor --> Identifier | Literal | ( Expression ) Expression e = null; ... return e; } private Conditional ifStatement () throws IOException { // IfStatement --> if ( Expression ) Statement { else Statement }opt Conditional c = new Conditional(); ... return c; } private Loop whileStatement () throws IOException { // WhileStatement --> while ( Expression ) Statement Loop l = new Loop(); ... return l; } private boolean isInteger(String s) { boolean result = true; for (int i=0; i s.charAt(i) || '9' < s.charAt(i)) result = false; return result; } private void SyntaxError(String tok) { System.out.println("Syntax error: expecting: " + tok + "; saw: " + token.getType() + " = " + token.getValue()); System.exit(0); } }