James I
James I

Reputation: 1

Parser not reading left parenthesis on read(V)

Hey first post help greatly appreciated

Creating a parser using automatic grader to test parser is supposed to detect errors, Correctly identifies all the errors; however, when there is no errors it incorrectly identifies errors,

My error is the code isn't acknowledging left_parenthesis on key_read leading to it viewing this as an error

for the first four tests where their should be 0 errors gives the output " The next lexeme was and the next token was LEFT_PAREN"

Where the blank should be (

attached all code

dcooke language, the read(V) is whats having the issue
P ::= S
S ::= V:=E | read(V) | write(E) | if C: then S fi | if C: then S else S fi | S;S
C ::= E < E | E > E | E = E | E <> E | E <= E | E >= E | ( C )
E ::= T | E + T | E - T
T ::= F | T * F | T / F | T % F
F ::= (E) | O | N | V
O ::= ++V | --V
V ::= a | b | … | y | z | aV | bV | … | yV | zV
N ::= 0 | 1 | … | 8 | 9 | 0N | 1N | … | 8N | 9N"

parser.c

#include <stdio.h>
#include <stdlib.h>
#include "parser.h"
#include "front.h"

/**
 * This is the example Recursive-Descent Parser in pp. 181 - 185 in the
 * textbook
 *
 * Sebesta, R. W. (2012). Concepts of Programming Languages.
 * Pearson, 10th edition.
 *
 *
 * */

/* expr
 * Parses strings in the language generated by the rule:
 * <expr> -> <term> {(+ | -) <term>}
 */
void expr();
void term();
void factor();
void error();

void expr()
{
    printf("Enter <expr>\n");

    /* Parse the first term */
    term();

    /* As long as the next token is + or -, get
    the next token and parse the next term */
    while (nextToken == ADD_OP || nextToken == SUB_OP) {
        lex();
        term();
    }

    printf("Exit <expr>\n");
} /* End of function expr */

/* term
 * Parses strings in the language generated by the rule:
 * <term> -> <factor> {(* | /) <factor>)
 */
void term()
{
    printf("Enter <term>\n");
    /* Parse the first factor */

    factor();

    /* As long as the next token is * or /, get the
    next token and parse the next factor */
    while (nextToken == MULT_OP || nextToken == DIV_OP || nextToken == MOD_OP) {
            lex();
            factor();
    }
    printf("Exit <term>\n");
} /* End of function term */

/* factor
 * Parses strings in the language generated by the rule:
 * <factor> -> id | int_constant | ( <expr )
 * */
void factor()
{
    printf("Enter <factor>\n");
    /* Determine which RHS */
    if (nextToken == IDENT || nextToken == INT_LIT) {
        lex(); /* Get the next token */
    } else {
        /* If the RHS is (<expr>), call lex to pass over the
        left parenthesis, call expr, and check for the right
        parenthesis */
        if (nextToken == LEFT_PAREN) {
            lex();
            expr();

            if (nextToken == RIGHT_PAREN) {
                lex();
            } else {
                error("Expected ')'");
            }
        }
        else if(nextToken== INC_OP || nextToken==DEC_OP){
                lex();
                if(nextToken==IDENT){
                        lex();
                }
                else{
                        error();
                }
        }
         /* End of if (nextToken == ... */
        /* It was not an id, an integer literal, or a left parenthesis */
        else
        {
            error("Expected identifier, integer literal, or '('");
        }
    } /* End of else */
    printf("Exit <factor>\n");;
} /* End of function factor */

void c(){
        if(nextToken==LEFT_PAREN){
                lex();
                c();
                if(nextToken==RIGHT_PAREN){
                        lex();
                }
                else{
                        error();
                }
        }
        else{
                expr();
                if(nextToken==GREATER_OP||nextToken==LEQUAL_OP||nextToken==EQUAL_OP||nextToken==NEQUAL_OP||nextToken==LESSER_OP||nextToken==GEQUAL_OP)
        {
                lex();
                expr();
        }
        }
}

void s(){
        if(nextToken==IDENT){
                lex();
                if(nextToken==ASSIGN_OP){
                        lex();
                        expr();
                }
                else{
                        error();
                }
        }
        else if(nextToken==KEY_WRITE){
                lex();
                if(nextToken==LEFT_PAREN){
                        lex();
                        expr();
                        if(nextToken==RIGHT_PAREN){
                                lex();
                        }
                        else{
                                error();
                        }
                }
                else{
                        error();
                }

        }
        else if(nextToken==KEY_READ){
                lex();
                if(nextToken==LEFT_PAREN){
                        lex();
                        if(nextToken==IDENT){
                                lex();
                                if(nextToken==RIGHT_PAREN){
                                        lex();
                                }
                                else{
                                        error();
                                }
                        }
                        else{
                                error();
                        }
                }
                else{
                        error();
                }
        }
        else if(nextToken==KEY_IF){
                lex();
                c();
                if(nextToken==COLON){
                        lex();
                        if(nextToken==KEY_THEN){
                                lex();
                                s();
                                if(nextToken==KEY_ELSE){
                                        lex();
                                        s();
                                }
                                if(nextToken==KEY_FI){
                                        lex();
                                }
                                else{
                                        error();
                                }
                        }
                        else{
                                error();
                        }

                }
                else{
                        error();
                }
        }
        if(nextToken==SEMICOLON){
                lex();
                if(nextToken==EOF){
                        error();
                }
                else{
                        s();
                }
        }

}

void error(char *msg, char *lexeme)
{
    printf("ERROR encounter: %s The next lexeme was %s and the next token was %s \n", msg, lexeme, tokenToString(nextToken));
    exit(1);
}


front.c

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "front.h"
#include "parser.h"

#define MAX_TOKEN_LENGTH 1000

/* Function prototypes */
const char *tokenToString(int token);
//int lex(FILE *fp);
int lookup(char ch);
int checkKeyword();

/* Global Variable */
int nextToken;
char lexeme[MAX_TOKEN_LENGTH];

/* Local Variables */
static int charClass;
static char nextChar;
static int lexLen;
static FILE *in_fp;

/* Local Function declarations */
static void addChar();
static void getChar();
static void getNonBlank();

/* Main */
int main(int argc, char *argv[]) {
    if (argc != 2) {
        exit(2);
    }
    if ((in_fp = fopen(argv[1], "r")) == NULL) {
        printf("ERROR - cannot open file\n");
        exit(3);
    } else {
        getChar();

        while (nextToken != EOF) {
            lex(in_fp);
        s();
            // Print lexeme and corresponding token
            if(nextToken != EOF){
                printf("%s %s\n", lexeme, tokenToString(nextToken));
                }
         if (nextToken != EOF) {
                printf("%s %s\n", lexeme, tokenToString(nextToken));
            }
        }
        fclose(in_fp);
    }
    return 0;
}
/*****************************************************/
/* getNonBlank - a function to call getChar until it returns a non-whitespace 
 * character */
static void getNonBlank() {
    while (isspace(nextChar)) getChar();
}

/*****************************************************/
/* lex - a simple lexical analyzer for arithmetic expressions */
int lex() { /*FILE *fp*/
    lexLen = 0;
    getNonBlank();

    switch (charClass) {
        /* Parse identifiers */
        case LETTER:
         
            addChar();
            getChar();
            while (charClass == LETTER || charClass == DIGIT || nextChar == '_') {
                addChar();
                getChar();
            }
            nextToken = checkKeyword();
            break;

        /* Parse integer literals */
        case DIGIT:
            addChar();
            getChar();
            while (charClass == DIGIT) {
                addChar();
                getChar();
            }
            nextToken = INT_LIT;
            break;

        /* Parentheses and operators */
        case UNKNOWN:
            nextToken = lookup(nextChar); // Pass the address of nextChar
            getChar(); 
            break;

        /* EOF */
        case EOF:
            nextToken = EOF;
            lexeme[0] = 'E';
            lexeme[1] = 'O';
            lexeme[2] = 'F';
            lexeme[3] = '\0';
            break;
    } /* End of switch */

    return nextToken;
} /* End of function lex */

/* Check if lexeme is a keyword */
int checkKeyword() {
    if (strcmp(lexeme, "if") == 0) {
        return KEY_IF;
    } else if (strcmp(lexeme, "else") == 0) {
        return KEY_ELSE;
    } else if (strcmp(lexeme, "then") == 0) {
        return KEY_THEN;
    } else if (strcmp(lexeme, "hen") == 0) {
    strcpy(lexeme, "then");
        return KEY_THEN;
    } else if (strcmp(lexeme, "fi") == 0) {
        return KEY_FI;
    } else if (strcmp(lexeme, "read") == 0) {
        return KEY_READ;
    } else if (strcmp(lexeme, "write") == 0) {
        return KEY_WRITE;
    } else {
        nextToken = IDENT;
        return IDENT;
    }
}



static void addChar() {
    if (lexLen <= MAX_TOKEN_LENGTH-1) {
        lexeme[lexLen++] = nextChar;
//      lexeme[lexLen] = '\0';
    } else {
        printf("Error - lexeme is too long \n");
    }
}



static void getChar() {
    if ((nextChar = getc(in_fp)) != EOF) {
        if (isalpha(nextChar))
            charClass = LETTER;
        else if (isdigit(nextChar))
            charClass = DIGIT;
        else
            charClass = UNKNOWN;
    } else {
        charClass = EOF;
    }
}

int lookup(char ch) {
    switch (ch) {
        case '(':
            addChar();
            return LEFT_PAREN;
        case ')':
            addChar();
            return RIGHT_PAREN;
        case '+':
            addChar();
            getChar();
            if (nextChar == '+') {
                addChar();
                return INC_OP;
            } else {
        ungetc(nextChar, in_fp);
                return ADD_OP;
            }
        case '*':
            addChar();
            return MULT_OP;
        case '/':
            addChar();
            return DIV_OP;
        case '<':
            addChar();
            getChar();
            if (nextChar == '>') {
                addChar();
                return NEQUAL_OP;
            } else if (nextChar == '=') {
                addChar();
                return LEQUAL_OP;
            } else {
        ungetc(nextChar, in_fp);
                return LESSER_OP;
            }
        case '>':
            addChar();
            getChar();
            if (nextChar == '=') {
                addChar();
                return GEQUAL_OP;
            } else {
        ungetc(nextChar, in_fp);
                return GREATER_OP;
            }
        case '=':
            addChar();
            return EQUAL_OP;
        case '%':
            addChar();
            return MOD_OP;
        case ';':
            addChar();
            return SEMICOLON;
        case ':':
            addChar();
            getChar();
            if (nextChar == '=') {
                addChar();
                return ASSIGN_OP;
            } else {
                return COLON;
            }
        case '-':
            addChar();
            getChar();
            if (nextChar == '-') {
                addChar();
                return DEC_OP;
            } else {
        ungetc(nextChar, in_fp);
                return SUB_OP;
            }
        default:
            addChar();
            if (nextChar == EOF)
                return EOF;
            else
                return UNKNOWN;
    }
}

const char *tokenToString(int token) {
    switch (token) {
        case ASSIGN_OP:
            return "ASSIGN_OP";
        case KEY_READ:
            return "KEY_READ";
        case KEY_WRITE:
            return "KEY_WRITE";
        case KEY_IF:
            return "KEY_IF";
        case KEY_ELSE:
            return "KEY_ELSE";
        case KEY_THEN:
            return "KEY_THEN";
        case KEY_FI:
            return "KEY_FI";
        case ADD_OP:
            return "ADD_OP";
        case SUB_OP:
            return "SUB_OP";
        case MULT_OP:
            return "MULT_OP";
        case DIV_OP:
            return "DIV_OP";
        case LESSER_OP:
            return "LESSER_OP";
        case GREATER_OP:
            return "GREATER_OP";
        case EQUAL_OP:
            return "EQUAL_OP";
        case NEQUAL_OP:
            return "NEQUAL_OP";
        case LEQUAL_OP:
            return "LEQUAL_OP";
        case MOD_OP:
            return "MOD_OP";
        case GEQUAL_OP:
            return "GEQUAL_OP";
        case INC_OP:
            return "INC_OP";
        case DEC_OP:
            return "DEC_OP";
        case LEFT_PAREN:
            return "LEFT_PAREN";
        case RIGHT_PAREN:
            return "RIGHT_PAREN";
        case INT_LIT:
            return "INT_LIT";
        case IDENT:
            return "IDENT";
        case SEMICOLON:
            return "SEMICOLON";
        case COLON:
            return "COLON";
        default:
            return "UNKNOWN";
    }
}

Have tried messing with the parser however, I cannot find the issue example of the execution is Error encounter: The next lexeme was write and the next token was KEY_WRITE However; im receiving Error encounter: The next lexeme was and the next token was LEFT_PAREN where their should be a (

Upvotes: 0

Views: 37

Answers (0)

Related Questions