--
--    Program : Parser.ada
--    Author  : Charles Kann, The George Washington University
--    Purpose : This program implements a recursive descent parser.  It is
--      based on the recursive descent parser given in Aho, Sethi,
--      and Ullman, "Principles, Techniques and Tools", 
--      Addison-Wesley, 1986.  Note that symbols are limited to
--      a single character.
--

--    The purpose of this program is to show recursion, and how in showing that
--    recursion the parse tree can be represented.
--
WITH Text_IO; USE Text_IO;
PACKAGE Parser IS
  PROCEDURE Parse;
END;

PACKAGE BODY Parser IS

  Token : Character;
  Token_Type : Character;

  -- "forward" declarations to accommodate mutual recursion
  
  PROCEDURE Lex;
  PROCEDURE Expr;
  PROCEDURE Factor;
  PROCEDURE Term;
        
  PROCEDURE Parse IS
  BEGIN
    Lex;
    Expr;
  END Parse;
    
  PROCEDURE Lex IS
  BEGIN
    LOOP
      IF NOT End_Of_Line THEN
        GET( Token );
        IF Token /= ' ' THEN
          CASE Token IS
            WHEN '+' | '-' =>
              Token_Type := 'A';
            WHEN '*' | '/' =>
              Token_Type := 'M';
            WHEN OTHERS =>
              Token_Type := 'I';
          END CASE;
          EXIT;
        END IF;
      ELSE
        Token_Type := ' ';
        Token := ' ';
        EXIT;
      END IF;
    END LOOP;
  END Lex;

  PROCEDURE Expr IS
    Save_Token : Character;
  BEGIN
    Term;
    LOOP
      IF Token = '+' OR Token = '-' THEN
        Save_Token := Token;
        Lex;
        Term;
        Put( Save_Token );        
      ELSE
        EXIT;
      END IF;
    END LOOP;
  END Expr;

  PROCEDURE Term IS
    Save_Token : Character;
  BEGIN
    Factor;
    LOOP
      IF Token = '*' OR Token = '/' THEN
        Save_Token := Token;
        Lex;
        Factor;
        Put( Save_Token );
      ELSE
        EXIT;
      END IF;
    END LOOP;
  END Term;

  PROCEDURE Factor IS
    Save_Token : Character;
  BEGIN
    IF Token = '(' THEN
      Lex;
      Expr;
      IF Token /= ')' THEN
        Put_Line(" ");
        Put_Line( "Error, ')' expected, tossing token" );
      ELSE
        Lex;
      END IF;
    ELSE 
      IF Token_Type = 'I' THEN
        Put( Token );
        Lex;
      ELSE
        Put_Line(" ");
        Put( "Error, identifier expected, got ");
        Put( Token );
        New_Line;
      END IF;
    END IF;

  END Factor;

END Parser;


WITH Text_IO; USE Text_IO;
WITH Parser; USE Parser;
PROCEDURE Parse_Expr IS
BEGIN

  Put_Line( "Enter an expression to be parsed >" );
  Parse;

END Parse_Expr;

