/* FILE: parser.c
 * PURPOSE:
 *    Functions that implement a Predictive Parser.
 *    The grammar implemented is Program Grammar #1.
 *    (CST 8152 - 98W - Assignment 4)
 * HISTORY:
 *    Ian D. Allen   idallen@freenet.carleton.ca
 */

//FIXME-- add system includes here
//FIXME-- add your local includes here

/* Static storage local to this parser:
 * - the look ahead token
 * - a statement counter
 * - the fd of the output stream
 * - the name of the output stream
 */
static Token token;		/* look-ahead token returned by scanner */
static long stmtcounter = 0;	/* count statements parsed */
static char *pinfname = "UNKNOWN-IN";
static FILE *poutfd = NULL;
static char *poutfname = "UNKNOWN-OUT";

/* Some macros that make the parser code nicer to read.
 * We cast the line number into a long int so that it has a known
 * width when passed to varargs functions on different architectures.
 */
#define LOOKAHEAD	token.type
#define LEXEME   	token.lexeme
#define LINENO   	(long int)token.lineno
#define GET_LOOKAHEAD	{token = scanner();}

//FIXME-- Your prototypes for your static functions go here.

/* FUNCTION:
 * PURPOSE:
 *    A matching function (similar to match() in text figure 2.17).
 * ALGORITHM:
 *    Check that the lookahead token type matches the TokenType argument.
 *    If it doesn't, print an error message that includes the line
 *    number of the token, the type of token that was expected, and the
 *    type of token that was found; then, exit indicating failure.  
 *    Load the next lookahead token.
 */
//FIXME-- your code goes here

/* FUNCTION:
 * PURPOSE:
 *    Recognize a FACTOR.
 * ALGORITHM:
 *    <From the grammar>
 *    Error messages contain the line number of the token, 
 *    the type(s) of token(s) that was/were expected, and the
 *    type of token that was found; then, exit indicating failure.  
 *    Load the next lookahead token.
 */
//FIXME-- your code goes here

/* FUNCTION:
 * PURPOSE:
 *    Recognize a TERM.
 * ALGORITHM:
 *    <From the grammar>
 *    No errors can be detected here.
 */
//FIXME-- your code goes here

/* FUNCTION:
 * PURPOSE:
 *    Recognize an EXPR.
 * ALGORITHM:
 *    <From the grammar>
 *    No errors can be detected here.
 */
//FIXME-- your code goes here

/* FUNCTION:
 * PURPOSE:
 *    Recognize an ASST.
 * ALGORITHM:
 *    <From the grammar>
 */
//FIXME-- your code goes here

/* FUNCTION:
 * PURPOSE:
 *    Recognize a STMT.
 * ALGORITHM:
 *    <From the grammar>
 *    Additional actions to perform:
 *       Save the line number and lexeme that starts the statement.
 *       When the end of the STMT is found, print a message to the
 *       parser output stream indicating the statement number, the
 *       lexeme starting the statement, and the line number of the
 *       start of the statement.
 */
//FIXME-- your code goes here

/* FUNCTION:
 * PURPOSE:
 *    Recognize a PROGRAM.
 * ALGORITHM:
 *    <From the grammar>
 *    This is the top-level, root parsing function.
 */
//FIXME-- your code goes here

/* FUNCTION: parser()
 * PURPOSE:
 *    Parse an open input stream.
 * ALGORITHM:
 *    Initialize the scanner.
 *    Set the statement counter to zero.
 *    Pre-load the first look-ahead token.
 *    Call the root parsing function.
 *    Terminate the scanner.
 */
	void
parser(
	FILE *infd,       /* IN: open input file descriptor to read */
	char *infname,    /* IN: name of open input stream */
	FILE *outfd,      /* IN: open output file descriptor to write */
	char *outfname    /* IN: name of open output stream */
){
	/* Save static copies of initialization data for use by Parser.
	 * We don't have to save a copy of the infd since only the
	 * scanner_init call in this function uses it.
	 */
	poutfd = outfd;
	pinfname = infname;
	poutfname = outfname;

	fprintf(poutfd, "PARSER: Now parsing '%s' to '%s'\n",
		pinfname, poutfname);

//FIXME-- your code goes here

	fprintf(poutfd, "PARSER: Parsed %ld statements from '%s' to '%s'.\n",
		stmtcounter, pinfname, poutfname);

	/* Undo what was done during the Parser initialization.
	 */
	poutfd = NULL;
	pinfname = NULL;
	poutfname = NULL;
}
