Reputation: 1
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