/*********************************************************************
 * Author: B. Alex Bridges                                           *
 * Login ID: brid0129                                                *
 * Class: CPSC-431, Winter 2000                                      *
 * Project: Laboratory Exercise 2                                    *
 * Description: This program is a lexical analyzer and the parser    *
 *              portion of a syntax analyzer for the lanaguage Micro *
 *              Modula-2.                                            *
 * Contents: Methods for doing the lexical analyzing.                *
 *********************************************************************/

/* IMPORTS */
import java.io.*;


class Syntax
{
  /* CONSTANTS */
    final static boolean b_debug = false;   // CONTROLS EXTRA DEBUG OUTPUT

  /* GLOBAL VARIABLES */
    public static StreamTokenizer stmT_file_in; // STREAM OF INPUT
    public static Token Token_look_ahead;       // LOOK AHEAD TOKEN FOR PARSING
    public static boolean b_errors = false;     // ERROR STATUS
  
  /*************************************************************************
   * Method: parse                                                         *
   * Purpose: Parses the stream of input.                                  *
   * Input: --PARAMATERS--                                                 *
   *        => 'stmT_file_in' = The given stream of input.                 *
   * Output: --RETURNS--                                                   *
   *         => NONE                                                       *
   *************************************************************************/
  public static void parse(StreamTokenizer stmT_file_in_given)
  {
    /* LOCAL VARIABLES */
    // NONE

    stmT_file_in = stmT_file_in_given;

    /* SKIP THE COMMENTS */
    do
    {
      Token_look_ahead = Lexical.process(stmT_file_in);
      
      if(b_debug)
        System.out.println("=> Looking at "+Token_look_ahead.str_name+
                           " token (line "+Token_look_ahead.int_line+": '"+
                           Token_look_ahead.str_actual+"').");
    } while( Token_look_ahead.str_name.equals("comment") );
   
    program_module();
  } // method parse

  /*************************************************************************
   * Method: match                                                         *
   * Purpose: Tries to match the given token name against the name for the *
   *          look ahead token.                                            *
   * Input: --PARAMATERS--                                                 *
   *        => 'str_name_given' = The token name which is expected.        *
   * Output: --RETURNS--                                                   *
   *         => NONE                                                       *
   *************************************************************************/
  public static void match(String str_name_given)
  {
    /* LOCAL VARIABLES */
    // NONE

    if( Token_look_ahead.str_name.equals(str_name_given) )
    {
      if(b_debug)
        System.out.println("=> Matched "+Token_look_ahead.str_name+
                           " token (line "+Token_look_ahead.int_line+": '"+
                           Token_look_ahead.str_actual+"').");
      
      /* SKIP THE COMMENTS */
      do
      {
        Token_look_ahead = Lexical.process(stmT_file_in);
        
        if(b_debug)
          System.out.println("=> Looking at "+Token_look_ahead.str_name+
                             " token (line "+Token_look_ahead.int_line+": '"+
                             Token_look_ahead.str_actual+"').");
      } while( Token_look_ahead.str_name.equals("comment") );
    } // if
    else
    {
      b_errors = true;
      
      System.out.println(" SYNTAX ERROR FOR match: '"+
                         Token_look_ahead.str_name+"' instead of '"+
                         str_name_given+"' (line "+
                         Token_look_ahead.int_line+")");
    } // else
  } // method match

  /*************************************************************************
   * Method: error                                                         *
   * Purpose: Handles the reporting of and recovery from syntax errors.    *
   * Input: --PARAMATERS--                                                 *
   *        => 'str_prod_given' = The associated production.               *
   *        => 'str_err_given'  = The assocated error message.             *
   * Output: --RETURNS--                                                   *
   *         => NONE                                                       *
   *************************************************************************/
  public static void error(String str_prod_given, String str_err_given)
  {
    /* LOCAL VARIABLES */
    // NONE

    /* MARK, PRODUCE, AND REPORT ERROR */
    b_errors = true;

    if(str_err_given == null)
      str_err_given = "Unexpected input of '"+Token_look_ahead.str_actual+"'.";
    
    System.out.println(" SYNTAX ERROR FOR "+str_prod_given+": "+
                       str_err_given+" (line "+Token_look_ahead.int_line+").");


    /* SKIP AHEAD TO SYNCHRONIZED TOKEN */
    do
    {
      Token_look_ahead = Lexical.process(stmT_file_in);

      if(b_debug)
        System.out.println("=> Looking at "+Token_look_ahead.str_name+
                           " token (line "+Token_look_ahead.int_line+": '"+
                           Token_look_ahead.str_actual+"').");
    } while( !( Token_look_ahead.str_name.equals("semicolon") ) );
  } // method error
  
  /*************************************************************************
   * Methods to handle the various productions.                            *
   *************************************************************************/
  public static void program_module()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the program_module production . . . ");
    
    // program_module => module_header imports block identifier "."
    //
    // FIRST(program_module) = 
    // FIRST(module_header) = 
    // "MODULE"

    if( Token_look_ahead.str_name.equals("module") )
    {
      module_header();
      imports();
      block();
      match("identifier");
      match("period");
      
      if( Token_look_ahead.str_ttype.equals("TT_EOF") && !b_errors )
        System.out.println("\n End of file successfully reached.");
      else
        System.out.println("\n End of file NOT successfully reached.");
    } // if
    else
    {
      error("program_module",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the program_module production . . . ");
  } // method program_module

  public static void module_header()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the module_header production . . . ");
    
    // module_header => "MODULE" identifier ";"
    //
    // FIRST(module_header) = "MODULE"

    if( Token_look_ahead.str_name.equals("module") )
    {
      match("module");
      match("identifier");
      match("semicolon");
    } // if
    else
    {
      error("module_header",null);
    } // else 

    if(b_debug)
      System.out.println("Exiting the module_header production . . . ");
  } // method module_header

  public static void imports()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the imports production . . . ");
    
    // imports => import imports | null
    //
    // FIRST(imports) = "FROM" , null

    if( Token_look_ahead.str_name.equals("from") )
    {
      import_();
      imports();
    } // if

    if(b_debug)
      System.out.println("Exiting the imports production . . . ");
  } // method imports

  public static void import_()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the import_ production . . . ");
    
    // import => "FROM" identifier "IMPORT" identifier_list ";"
    //
    // FIRST(import) = "FROM"
    
    if( Token_look_ahead.str_name.equals("from") )
    {
      match("from");
      match("identifier");
      match("import");
      identifier_list();
      match("semicolon");
    } // if
    else
    {
      error("import_",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the import_ production . . . ");
  } // method import_
  
  public static void block()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the block production . . . ");
    
    // block => declarations "BEGIN" statement_sequence "END"
    //
    // FIRST(block) = "VAR" , "TYPE" , "PROCEDURE" , "BEGIN"
 
    if( Token_look_ahead.str_name.equals("var")  ||
        Token_look_ahead.str_name.equals("type") ||
        Token_look_ahead.str_name.equals("procedure") )
    {
      declarations();
    } // if
    if( Token_look_ahead.str_name.equals("begin") )
    {
      match("begin");
      statement_sequence();
      match("end");
    } // if
    else
    {
      error("block",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the block production . . . ");
  } // method block
  
  public static void declarations()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the declarations production . . . ");
    
    // declarations => declaration declarations | null
    // FIRST(declaration) = "VAR" , "TYPE" , "PROCEDURE" , null
    
    if( Token_look_ahead.str_name.equals("var")  ||
        Token_look_ahead.str_name.equals("type") ||
        Token_look_ahead.str_name.equals("procedure") )
    {
      declaration();
      declarations();
    } // if

    if(b_debug)
      System.out.println("Exiting the declarations production . . . ");
  } // method declarations
  
  public static void declaration()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the declaration production . . . ");
    
    // declaration => "VAR" variable_decls |
    //                "TYPE" type_decls |
    //                procedure_declaration
    //
    // FIRST(declaration) = "VAR" , "TYPE" , "PROCEDURE"
    
    if( Token_look_ahead.str_name.equals("var") )
    {
      match("var");
      variable_decls();
    } // if
    else if( Token_look_ahead.str_name.equals("type") )
    {
      match("type");
      type_decls();
    } // if
    else if( Token_look_ahead.str_name.equals("procedure") )
    {
      procedure_declaration();
    } // else
    else
    {
      error("declaration",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the declaration production . . . ");
  } // method declaration
  
  public static void variable_decls()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the variable_decls production . . . ");
    
    // variable_decls => variable_decl varibale_decls  | null
    //
    // FIRST(variable_decls) = identifier , null
    
    if( Token_look_ahead.str_name.equals("identifier") )
    {
      variable_decl();
      variable_decls();
    } // if
    
    if(b_debug)
      System.out.println("Exiting the variable_decls production . . . ");
  } // method variable_decls
  
  public static void variable_decl()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the variable_decl production . . . ");
    
    // variable_decl => identifier_list ":" type ";"
    //
    // FIRST(variable_decl) = identifier
    
    if( Token_look_ahead.str_name.equals("identifier") )
    {
      identifier_list();
      match("colon");
      type();
      match("semicolon");
    } // if
    else
    {
      error("variable_decl",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the variable_decl production . . . ");
  } // method variable_decl
  
  public static void type_decls()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the type_decls production . . . ");
    
    // type_decls => type_decl type_decls | null
    //
    // FIRST(type_decls) = identifier , null
    
    if( Token_look_ahead.str_name.equals("identifier") )
    {
      type_decl();
      type_decls();
    } // if

    if(b_debug)
      System.out.println("Exiting the type_decls production . . . ");
  } // method type_decls
  
  public static void type_decl()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the type_decl production . . . ");
    
    // type_decl => identifier "=" type ";"
    //
    // FIRST(type_decl) = identifier
    
    if( Token_look_ahead.str_name.equals("identifier") )
    {
      match("identifier");
      match("=");
      type();
      match("semicolon");
    } // if
    else
    {
      error("type_decl",null);
    } // else
    
    if(b_debug)
      System.out.println("Exiting the type_decl production . . . ");
  } // method type_decl
  
  public static void procedure_declaration()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the procedure_declaration production . . . ");
    
    // procedure_declaration => procedure_header block identifier ";"
    //
    // FIRST(procedure_declaration) = "PROCEDURE"

    if( Token_look_ahead.str_name.equals("procedure") )
    {
      procedure_header();
      block();
      match("identifier");
      match("semicolon");
    } // if
    else
    {
      error("procedure_declaration",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the procedure_declaration production . . . ");
  } // method procedure_declaration
  
  public static void procedure_header()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the procedure_header production . . . ");
    
    // procedure_header => "PROCEDURE" identifier procedure_header'
    // procedure_header' => "(" parameter_list ")" opt_func ";" | ";"
    //
    // FIRST (procedure_header) = "PROCEDURE"
    // FIRST (procedure_header') = "(" , ";"
    
    if( Token_look_ahead.str_name.equals("procedure") )
    {
      match("procedure");
      match("identifier");
      
      if( Token_look_ahead.str_name.equals("l_paran") )
      {
        match("l_paran");
        parameter_list();
        match("r_paran");
        opt_func();
      } // if
      match("semicolon");
    } // if
    else
    {
      error("procedure_header",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the procedure_header production . . . ");
  } // method procedure_header
  
  public static void parameter_list()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the parameter_list production . . . ");
    
    // parameter_list => parameter_group parameter_list'
    // parameter_list' => ";" parameter_group parameter_list' | null
    //
    // FIRST(parameter_list) = "VAR" , identifier
    // FIRST(parameter_list') = ";" , null
    
    if( Token_look_ahead.str_name.equals("var") ||
        Token_look_ahead.str_name.equals("identifier") )
    {
      parameter_group();
      while(true)
      {
        if( Token_look_ahead.str_name.equals("semicolon") )
        {
          match("semicolon");
          parameter_group();
          continue;
        } // if
        else
          break;
      } // while
    } // if
    else
    {
      error("parameter_list",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the parameter_list production . . . ");
  } // method parameter_list
  
  public static void parameter_group()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the parameter_group production . . . ");
    
    // parameter_group => "VAR" identifier_list ":" type_name |
    //                    identifier_list ":" type_name
    //
    // FIRST(paremeter_group) = "VAR" , identifier
    
    if( Token_look_ahead.str_name.equals("var") )
    {
      match("var");
    } // if
    if( Token_look_ahead.str_name.equals("identifier") )
    {
      identifier_list();
      match("colon");
      type_name();
    } // if
    else
    {
      error("parameter_group",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the parameter_group production . . . ");
  } // method parameter_group
  
  public static void opt_func()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the opt_func production . . . ");

    // opt_func => ":" type_name
    //
    // FIRST(opt_func) = ":"
    if( Token_look_ahead.str_name.equals("colon") )
    {
      match("colon");
      type_name();
    } // if
    else
    {
      error("opt_func",null);
    } // else
    
    if(b_debug)
      System.out.println("Exiting the opt_func production . . . ");
  } // method opt_func

  public static void statement_sequence()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the statement_sequence production . . . ");

    // statement_sequence => statement statement_sequence'
    // statement_sequence' => ";" statement statement_sequence' | null
    //
    // FIRST(statement_sequence) = null , ";" , identifier , 
    //                             "WHILE" , "REPEAT" , "IF", "RETURN"
    // FIRST(statement_sequence') = ";" , null
    
    if( Token_look_ahead.str_name.equals("semicolon")  ||
        Token_look_ahead.str_name.equals("identifier") ||
        Token_look_ahead.str_name.equals("while")      ||
        Token_look_ahead.str_name.equals("repeat")     ||
        Token_look_ahead.str_name.equals("if")         ||
        Token_look_ahead.str_name.equals("return") )
    {
      if( !( Token_look_ahead.str_name.equals("semicolon") ) )
      {
        statement();
      } // if
      
      while(true)
      {
        if( Token_look_ahead.str_name.equals("semicolon") )
        {
          match("semicolon");
          statement();
          continue;
        } // if
        else
          break;
      } // while
    } // if

    if(b_debug)
      System.out.println("Exiting the statement_sequence production . . . ");
  } // method statement_sequence
  
  public static void statement()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the statement production . . . ");

    // statement => null |
    //              identifier statement'
    //              "WHILE" expression "DO" statement_sequence "END" |
    //              "REPEAT" statement_sequence "UNTIL" expression |
    //              "IF" expression "THEN" statement_sequence statement'' |
    //              "RETURN" expression
    // statement' => null |
    //               "(" expression_list ")" |
    //               ":=" expression |
    //               [" simple_expression "]" ":=" expression
    // statement'' => "END" |
    //                "ELSE" statement_sequence "END"
    //
    // FIRST(statement) = null , identifier , 
    //                    "WHILE" , "REPEAT" , "IF", "RETURN"
    // FIRST(statement') = null , "(" , ":=", "["
    // FIRST(statement'') = "END" , "ELSE"
    
    if( Token_look_ahead.str_name.equals("identifier") )
    {
      match("identifier");
      if( Token_look_ahead.str_name.equals("l_paran") )
      {
        match("l_paran");
        expression_list();
        match("r_paran");
      } // if
      else if( Token_look_ahead.str_name.equals("assignment") )
      {
        match("assignment");
        expression();
      } // if
      else if( Token_look_ahead.str_name.equals("l_bracket") )
      {
        match("l_bracket");
        simple_expression();
        match("r_bracket");
        match("assignment");
        expression();
      } // if  
    } // if
    else if( Token_look_ahead.str_name.equals("while") )
    {
      match("while");
      expression();
      match("do");
      statement_sequence();
      match("end");
    } // if
    else if( Token_look_ahead.str_name.equals("repeat") )
    {
      match("repeat");
      statement_sequence();
      match("until");
      expression();
    } // if
    else if( Token_look_ahead.str_name.equals("if") )
    {
      match("if");
      expression();
      match("then");
      statement_sequence();
      
      if( Token_look_ahead.str_name.equals("else") )
      {
        match("else");
        statement_sequence();
      } // if
      match("end");
    } // if
    
    if(b_debug)
      System.out.println("Exiting the statement production . . . ");
  } // method statement
  
  public static void expression_list()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the expression_list production . . . ");

    // expression_list => expression expression_list'
    // expression_list' => "," expression expression_list' | null
    //
    // FIRST(expression_list) = add_op , 
    //                          string_constant , 
    //                          integer , real , 
    //                          identifier , 
    //                          "("
    // FIRST(expression_list) = "," , null

    if( Token_look_ahead.str_name.equals("add_op")     ||
        Token_look_ahead.str_name.equals("str_const")  ||
        Token_look_ahead.str_name.equals("integer")    ||
        Token_look_ahead.str_name.equals("real")       ||
        Token_look_ahead.str_name.equals("identifier") ||
        Token_look_ahead.str_name.equals("l_paran") )
    {
      expression();
      
      while(true)
      {
        if( Token_look_ahead.str_name.equals("comma") )
        {
          match("comma");
          expression();
          continue;
        } // if
        else
          break;
      } // while
    } // if
    else
    {
      error("expression_list",null);
    } // else
    
    if(b_debug)
      System.out.println("Exiting the expression_list production . . . ");
  } // method expression_list
  
  public static void expression()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the expression production . . . ");

    // expression => simple_expression expression'
    // expression' => rel_op simple_expression | null
    //
    // FIRST(expression) = add_op , 
    //                     string_constant , 
    //                     integer , real , 
    //                     identifier , 
    //                     "("
    // FIRST(expression') = rel_op , null
    
    if( Token_look_ahead.str_name.equals("add_op")     ||
        Token_look_ahead.str_name.equals("str_const")  ||
        Token_look_ahead.str_name.equals("integer")    ||
        Token_look_ahead.str_name.equals("real")       ||
        Token_look_ahead.str_name.equals("identifier") ||
        Token_look_ahead.str_name.equals("l_paran") )
    {
      simple_expression();

      while(true)
      {
        if( Token_look_ahead.str_name.equals("rel_op") )
        {
          match("rel_op");
          simple_expression();
          continue;
        } // if
        else
          break;
      } // while
    } // if
    else
    {
      error("expression",null);
    } // else
   
    if(b_debug)
      System.out.println("Exiting the expression production . . . ");
  } // method expression
  
  public static void simple_expression()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the simple_expression production . . . ");

    // simple_expression => add_op uns_simple_expression | uns_simple_expression
    //
    // FIRST(simple_expression) = add_op , 
    //                            string_constant , 
    //                            integer , real , 
    //                            identifier , 
    //                            "("
    
    if( Token_look_ahead.str_name.equals("add_op") )
    {
      match("add_op");
    } // if
    if( Token_look_ahead.str_name.equals("str_const")  ||
        Token_look_ahead.str_name.equals("integer")    ||
        Token_look_ahead.str_name.equals("real")       ||
        Token_look_ahead.str_name.equals("identifier") ||
        Token_look_ahead.str_name.equals("l_paran") )
    {
      uns_simple_expression();
    } // if
    else
    {
      error("simple_expression",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the simple_expression production . . . ");
  } // method simple_expression
  
  public static void uns_simple_expression()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the uns_simple_expression production . . . ");

    // uns_simple_expression => term uns_simple_expression'
    // uns_simple_expression' => add_op term uns_simple_expression' | null
    //
    // FIRST(uns_simple_expression) = string_constant , 
    //                                integer , real , 
    //                                identifier , 
    //                                "("
    // FIRST(uns_simple_expression') = add_op , null

    if( Token_look_ahead.str_name.equals("str_const")  ||
        Token_look_ahead.str_name.equals("integer")    ||
        Token_look_ahead.str_name.equals("real")       ||
        Token_look_ahead.str_name.equals("identifier") ||
        Token_look_ahead.str_name.equals("l_paran") )
    {
      term();

      while(true)
      {
        if( Token_look_ahead.str_name.equals("add_op") )
        {
          match("add_op");
          term();
          continue;
        } // if
        else
          break;
      } // while
    } // if
    else
    {
      error("uns_simple_expression",null);
    } // else
    
    if(b_debug)
      System.out.println("Exiting the uns_simple_expression production . . . ");
  } // method uns_simple_expression
  
  public static void term()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the term production . . . ");

    // term => factor term'
    // term' => mul_op factor term' | null
    //
    // FIRST(term) = string_constant , 
    //               integer , real , 
    //               identifier , 
    //               "("
    // FIRST(term') = mul_op , null

    if( Token_look_ahead.str_name.equals("str_const")  ||
        Token_look_ahead.str_name.equals("integer")    ||
        Token_look_ahead.str_name.equals("real")       ||
        Token_look_ahead.str_name.equals("identifier") ||
        Token_look_ahead.str_name.equals("l_paran") )
    {   
      factor();

      while(true)
      {
        if( Token_look_ahead.str_name.equals("mul_op") )
        {
          match("mul_op");
          factor();
          continue;
        } // if
        else
          break;
      } // while
    } // if
    else
    {
      error("term",null);
    } // else
    
    if(b_debug)
      System.out.println("Exiting the term production . . . ");
  } // method term
  
  public static void factor()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the factor production . . . ");

    // factor => constant |
    //           identifier factor' |
    //           "(" expression ")"
    // factor' => null |
    //            "(" expression_list ")" |
    //            "[" simple_expression "]"
    //
    // FIRST(factor) = string_constant , 
    //                 integer , real , 
    //                 identifier , 
    //                 "("
    // FIRST(factor') = null , "(" , "["
    
    if( Token_look_ahead.str_name.equals("str_const") ||
        Token_look_ahead.str_name.equals("integer")   ||
        Token_look_ahead.str_name.equals("real") )
    {
      constant();    
    } // if
    else if( Token_look_ahead.str_name.equals("identifier") )
    {
      match("identifier");
      
      if( Token_look_ahead.str_name.equals("l_paran") )
      {
        match("l_paran");
        expression_list();
        match("r_paran");
      } // if
      else if( Token_look_ahead.str_name.equals("l_bracket") )
      {
        match("l_bracket");
        simple_expression();
        match("r_bracket");
      } // if   
    } // if  
    else if( Token_look_ahead.str_name.equals("l_paran") )
    {
      match("l_paran");
      expression();
      match("r_paran");
    } // if
    else
    {
      error("factor",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the factor production . . . ");
  } // method factor
  
  public static void constant()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the constant production . . . ");

    // constant => string_constant | number
    //
    // FIRST(constant) = string_constant , integer , real
    
    if( Token_look_ahead.str_name.equals("str_const") )
    {
      match("str_const");
    } // if
    else if( Token_look_ahead.str_name.equals("integer") ||
             Token_look_ahead.str_name.equals("real") )
    {
      number();
    } // if
    else
    {
      error("constant",null);
    } // else
    
    if(b_debug)
      System.out.println("Exiting the constant production . . . ");
  } // method constant
  
  public static void number()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the number production . . . ");

    // number => integer | real
    //
    // FIRST(number) = integer , real
    
    if( Token_look_ahead.str_name.equals("integer") )
    {
      match("integer");
    } // if
    else if( Token_look_ahead.str_name.equals("real") )
    {
      match("real");
    } // if
    else
    {
      error("number",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the number production . . . ");
  } // method number
  
  public static void identifier_list()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the identifier_list production . . . ");

    // identifier_list => identifier identifier_list'
    // identifier_list' => "," identifier identifier_list' | null
    //
    // FIRST(identifier_list) = identifier
    // FIRST(identifier_list) = "," , null
    
    if( Token_look_ahead.str_name.equals("identifier") )
    {
      match("identifier");

      while(true)
      {
        if( Token_look_ahead.str_name.equals("comma") )
        {
          match("comma");
          match("identifier");
          continue;
        } // if
        else
          break;
      } // while
    } // if
    else
    {
      error("identifier_list",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the identifier_list production . . . ");   
  } // method identifier_list
  
  public static void type()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the type production . . . ");

    // type => type_name | 
    //         "ARRAY" "[" integer ".." integer "]" "OF" type_name
    //
    // FIRST(type) = identifier , "ARRAY"
    
    if( Token_look_ahead.str_name.equals("array") )
    {
      match("array");
      match("l_bracket");
      match("integer");
      match("ellipsis");
      match("integer");
      match("r_bracket");
      match("of");
    } // if
    if( Token_look_ahead.str_name.equals("type_name") )
    {
      type_name();
    } // if
    else
    {
      error("type",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the type production . . . ");
  } // method type
  
  public static void type_name()
  {
    /* LOCAL VARIABLES */
    // NONE

    if(b_debug)
      System.out.println("Entering the type_name production . . . ");

    // type_name => identifier
    //
    // FIRST(type_name) = identifier
    //
    // NOTE: This kind of identifier is recognized by the 
    //       lexical analyzer and therefore has been given 
    //       the name "type_name" as opposed to "identifier".
    
    if( Token_look_ahead.str_name.equals("type_name") )
    {
      match("type_name");
    } // if
    else
    {
      error("type_name",null);
    } // else

    if(b_debug)
      System.out.println("Exiting the type_name production . . . ");
  } // method type_name
} // class Syntax

