Recitation Week 4: Infix Expressions

This is based on Programming Problem 9 in our Java text book.

Infix expressions are ones in which the operator appears between the two operands, like

In Programming Problem 9, a simple grammar defines a language that is a subset of infix expressions. In this language, single letters are used instead of numbers, and the available operators are +, -, * and /. Also, pairs of parentheses can be included.

Here is the grammar, repeated from the text book.

Your goal for this recitation is to finish the following Java code for recognizing strings in this language. It is fairly straightforward to handle the all of the grammar rules on a single line with a single method.

Study the following incomplete code. It is missing the implementation of the validTerm method that handles the rules in the second line of the above grammar.

Try to implement this method for 15 minutes on your own. Then discuss it as a class as the TA guides you to the answer.

Your final version should correctly process the examples included in the main method. The output should look like:

Valid: a + b
Valid: a * b - c
Valid: a * ( b + c )
Valid: d / ( f + g )
Not Valid: a + b z
Not Valid: a *
Not Valid: x +
Not Valid: a + ( b - c
Not Valid: * b + c
Valid: ( a + ( b * ( c / ( x - y ) ) ) )
Not Valid: ( a + ( b * c / ( x - y ) ) ) )
Infix.java
import java.lang.Character;  // for isLetter()
 
public class Infix {
 
   public static char[] tokens;  // character array of tokens from an expression
   public static int current;    // index into tokens showing next token to deal with
 
   // Precondition: Receives expression as a String, with spaces between each token
   // Postcondition: static characer array 'tokens' contains the single-character tokens
   //                given in the argument expression string.  Also, static variable 'count'
   //                is set to zero.  Returns result of validExpressionRec(true).
   public static boolean validExpression(String expression) {
      String [] tokenStrings = expression.split(" ");
      tokens = new char[tokenStrings.length];
      for (int i = 0; i < tokenStrings.length; i++)
         tokens[i] = tokenStrings[i].charAt(0);
      current = 0;
 
      return validExpressionRec(true);
   }
 
   // Precondition: static array 'tokens' contains all expression tokens and 'current' is 
   //               index into 'tokens' of next token to process. Argument 'top' is true if
   //               called at the top level of processing an expression; it is false if called
   //               recursively from validFactor().  
   // Postcondition: Returns true if expression starting from 'current' contains a valid expression,
   //                defined by these grammar rules:
   //          <expression> = <term> | <term> + <term> | <term> - <term>
   //                'current' is updated to be index of next token to process.
   public static boolean validExpressionRec(boolean top) {
      boolean valid = false;
      if (validTerm()) {
         if (current < tokens.length && (tokens[current] == '+' || tokens[current] == '-')) {
            current++;
            valid = validTerm();
         } else {
            valid = true;
         }
      }
      if (top) // If called at top level, make sure there are no extra tokens.
         return valid && current == tokens.length;
      else
         return valid;
   }
 
   // Precondition: static array 'tokens' contains all expression tokens and 'current' is 
   //               index into 'tokens' of next token to process. 
   // Postcondition: Returns true if expression starting from 'current' contains a valid term,
   //                defined by these grammar rules:
   //         <term> = <factor> | <factor> * <factor> | <factor> / <factor>
   //                'current' is updated to be index of next token to process.
   public static boolean validTerm() {
      // NOT FINISHED!!!
      return false;
   }
 
   // Precondition: static array 'tokens' contains all expression tokens and 'current' is 
   //               index into 'tokens' of next token to process. 
   // Postcondition: Returns true if expression starting from 'current' contains a valid factor,
   //                defined by these grammar rules:
   //          <factor> = <letter> | ( <expression> )
   //          <letter> = a | b | ...| z
   //                'current' is updated to be index of next token to process.
   public static boolean validFactor() {
      if (current >= tokens.length)
         return false;
      if (Character.isLetter(tokens[current])) {
         current++;
         return true;
      }
      if (tokens[current] == '(') {
         current++;
         if (validExpressionRec(false))
            if (current < tokens.length && tokens[current] == ')') {
               current++;
               return true;
            }
      }
      return false;
   }
 
   // --------------------------------------------------------------------------------
   // ---------------------------main-------------------------------------------------
   // --------------------------------------------------------------------------------
   public static void main(String [] args) {
      // Expressions to be analyzed.
      String [] expressions = {"a + b", "a * b - c", "a * ( b + c )", "d / ( f + g )",
                               "a + b z", "a *", "x +", "a + ( b - c","* b + c",
                               "( a + ( b * ( c / ( x - y ) ) ) )",
                               "( a + ( b * c / ( x - y ) ) ) )"};
      // Check validity of each expression
      for (String exp : expressions) {
         if (validExpression(exp))
            System.out.println("Valid: " + exp);
         else 
            System.out.println("Not Valid: " + exp);
      }
   }
}
Recent changes RSS feed CC Attribution-Share Alike 3.0 Unported Driven by DokuWiki