PA 3 Description 1 CS 280 Programming Language Concepts Programming Assignment 3 Implementation of an Interpreter for a Simple Programming Language Programming Assignment 3 ◼ Objectives  Construction...

1 answer below »
In this programming assignment, you will be implementing an interpreter for our small programming language and write a C++ program to test it. You are required to modify the parser you have implemented for the small programming language to implement the simple language interpreter. The syntax definitions and tokens of the programming language were given in Programming Assignment 2, and are given below using EBNF notations.


PA 3 Description 1 CS 280 Programming Language Concepts Programming Assignment 3 Implementation of an Interpreter for a Simple Programming Language Programming Assignment 3 ◼ Objectives  Construction of an interpreter for a simple programming language based on the recursive-descent parser developed in Programming Assignment 2. ◼ Notes:  Read the assignment carefully to understand it.  Understand the functionality of the interpreter, and the required actions to be performed to execute the source code. 3 Given Files ◼ “lex.h” ◼ “lex.cpp”  You can use your implementation, or copy and use my lexical analyzer when I publish it. ◼ “parserIn.h”  Modified version of “parse.h”. ◼ “parse.cpp”  You can use your implementation, or copy and use my parser when I publish it.  This file will should be renamed as “parserInt.cpp” for your submission ◼ “val.h” and “val.cpp”  Specification and implementation of the class Value. 4 Grammar ◼ Modified grammar: Deletion of the ReadStmt and VarList rules Prog = PROGRAM IDENT {Decl} {Stmt} END PROGRAM IDENT Decl = (INTEGER | REAL | CHAR) : IdList IdList = IDENT {,IDENT} Stmt = AssigStmt | IfStmt | PrintStmt PrintStmt = PRINT , ExprList IfStmt = IF (LogicExpr) THEN {Stmt} END IF AssignStmt = Var = Expr ExprList = Expr {, Expr} Expr = Term {(+|-) Term} Term = SFactor {(*|/) SFactor} SFactor = Sign Factor | Factor LogicExpr = Expr (== | <) expr="" var="IDENT" sign="+" |="" -="" factor="IDENT" |="" iconst="" |="" rconst="" |="" sconst="" |="" (expr)="" 5="" example="" program="" of="" our="" simple="" language="" !clean="" program="" program="" circle="" !if="" stmt="" test="" real="" :="" r,="" a,="" p,="" b="" char="" :="" str1,="" str2="" r="5" a="(3.14)" *="" r="" *="" r="" if="" (="" r="=" 5)="" then="" p="2" *="" 3.14="" *="" a="" print,="" "r=", r, " a=" , a, " p=", p END IF END PROGRAM circle 6 Description of the Language 1. The language has three types: INTEGAR, REAL, and CHARacter (as string). 2. The PLUS and MINUS operators in Expr represent addition and subtraction. 3. The MULT and DIV operators in Term represent multiplication and division. 4. The PLUS, MINUS, MULT and DIV operators are left associative. 5. MULT and DIV have higher precedence than PLUS and MINUS. 6. Unary operators for the sign have higher precedence than MULT and DIV. 7. All variables have to be declared in declaration statements. 8. An IfStmt evaluates a logical expression (LogicExpr) as a condition. If the logical expression value is true, then the Stmt block is executed, otherwise it is not. Though the language does not include a Boolean type, Boolean expressions are considered as the type of evaluating LogicExpr. 9. A PrintStmt evaluates the list of expressions (ExprList), and prints their values in order from left to right. 7 Description of the Language 10. The ASSOP operator in the AssignStmt assigns a value to a variable. It evaluates the Expr on the right-hand side and saves its value in memory associated with the left-hand side variable (Var). The left-hand side variable must be of a type that is compatible with the type of the expression value on the right-hand side. For example, an integer variable can be assigned a real value, and a real variable can be assigned an integer value. In either case, conversion of the value to the type of the variable must be applied. However, it is an error to assign a numeric value to a variable of a CHAR type, or to assign a CHAR value to a numeric variable (i.e., integer or real). 11. The binary operations for addition, subtraction, multiplication, and division are performed upon two numeric operands (i.e., integer or real) of the same or different types. If the operands are of the same type, the type of the result is the same type as the operator’s operands. Otherwise, the type of the result is real. It is an error to have string operand to any of the arithmetic operations. 8 Description of the Language 12. The EQUAL and LTHAN relational operators operate upon two compatible operands. The evaluation of a logical expression, based on EQUAL or LTHAN operation, produces either a true or false value that controls whether the statement(s) of the selection IfStmt is executed or not. 13. It is an error to use a variable in an expression before it has been assigned. 14. The unary sign operators (+ or -) are applied upon a unary numeric operand (i.e., INTEGER or REAL). 15. The name of the program at its header must match the name of the program at its end. 9 Implementation of an Interpreter for the Simple Programming Language ◼ The parser includes one function per rule or nonterminal. ◼ Each function recognizes the right hand side of the rule.  If the function needs to read a token, it can read it using getNextToken().  If the function needs a nonterminal symbol, it calls the function for that nonterminal symbol. ◼ The interpreter parses the input source code statement by statement. For each parsed statement:  The parser/interpreter stops if there is a lexical/syntactic error.  If parsing is successful for the statement, it interprets the statement: ◼ Checks for semantic errors (i.e., run-time) in the statement. ◼ Stops the process of interpretation if there is a run-time error. ◼ Executes the statement if no errors found. 10 Implementation of an Interpreter for the Simple Programming Language  The results of an unsuccessful parsing and interpreting are a set of error messages printed by the parser/interpreter functions, as well as the error messages that might be detected by the lexical analyzer. ◼ Suggested messages of the interpreter’s semantics check might include messages such as " run-time="" error-illegal="" mixed="" type="" operands",="" "="" run-time="" error-illegal="" assignment="" operation",="" "run-time="" error-illegal="" division="" by="" zero",="" etc.="" 11="" “val.h”="" description="" enum="" valtype="" {="" vint,="" vreal,="" vchar,="" vbool,="" verr="" };="" class="" value="" {="" private:="" valtype="" t;="" int="" itemp;="" floatrtemp;="" string="" stemp;="" bool="" btemp;="" public:="" value()="" :="" t(verr),="" itemp(0),="" rtemp(0.0){}="" value(int="" vi)="" :="" t(vint),="" itemp(vi)="" {}="" value(float="" vr)="" :="" t(vreal),="" itemp(0),="" rtemp(vr)="" {}="" value(string="" vs)="" :="" t(vchar),="" itemp(0),="" rtemp(0.0),="" stemp(vs)="" {}="" value(bool="" vb)="" :="" t(vbool),="" btemp(vb),="" itemp(0),="" rtemp(0.0)="" {}="" valtype="" gettype()="" const="" {="" return="" t;="" }="" bool="" iserr()="" const="" {="" return="" t="=" verr;="" }="" bool="" isint()="" const="" {="" return="" t="=" vint;="" }="" bool="" ischar()="" const="" {="" return="" t="=" vchar;="" }="" bool="" isreal()="" const="" {return="" t="=" vreal;}="" bool="" isbool()="" const="" {return="" t="=" vbool;}="" 12="" “val.h”="" description="" int="" getint()="" const="" {="" if(="" isint()="" )="" return="" itemp;="" throw="" "runtime="" error:="" value="" not="" an="" integer";="" }="" string="" getchar()="" const="" {="" if(="" ischar()="" )="" return="" stemp;="" throw="" "runtime="" error:="" value="" not="" a="" string";="" }="" float="" getreal()="" const="" {="" if(="" isreal()="" )="" return="" rtemp;="" throw="" "runtime="" error:="" value="" not="" an="" integer";="" }="" bool="" getbool()="" const="" {if(isbool())="" return="" btemp;="" throw="" "runtime="" error:="" value="" not="" a="" boolean";}="" void="" settype(valtype="" type){="" t="type;}" void="" setint(int="" val){="" itemp="val;}" void="" setreal(float="" val){="" rtemp="val;}" void="" setchar(string="" val){="" stemp="val;}" void="" setbool(bool="" val){="" btemp="val;}" 13="" “val.h”="" description="" overloaded="" operations="" add="" op="" to="" this="" value="" operator+(const="" value&="" op)="" const;="" subtract="" op="" from="" this="" value="" operator-(const="" value&="" op)="" const;="" multiply="" this="" by="" op="" value="" operator*(const="" value&="" op)="" const;="" divide="" this="" by="" op="" value="" operator/(const="" value&="" op)="" const;="" compare="" this="" with="" op="" value="" operator="=(const" value&="" op)="" const;="" value=""><(const value&="" op)="" const;="" friend="" ostream&=""><(ostream& out,="" const="" value&="" op)="" {="" if(="" op.isint()="" )="" out="">< op.itemp;="" else="" if(="" op.ischar()="" )="" out="">< op.stemp;="" else="" if(="" op.isreal())="" out="">< op.rtemp;="" else="" out="">< "error";="" return="" out;="" };="" 14="" “val.h”="" description="" add="" this="" with="" op.="" applies="" the="" semantics="" of="" mixed="" type="" numeric="" operands="" value="" value::operator+(const="" value&="" op)="" const="" {="" if(="" gettype()="=" op.gettype()="" ){="" if(="" isint()="" )="" return="" value(="" itemp="" +="" op.getint()="" );="" if(="" isreal()="" )="" return="" value(="" rtemp="" +="" op.getreal()="" );="" }="" else="" if(isint()="" &&="" op.isreal(){="" return="" value(="" (float)="" getint()="" +="" op.getreal());="" }="" else="" if(isreal()="" &&="" op.isint()){="" return="" value(getreal()="" +="" (float)="" op.getint());="" }="" else{="" return="" value();="" }="" }="" other="" overloaded="" operators="" are="" similarly="" implemented.="" 15="" “val.h”="" description="" compare="" this="" with="" op="" for="=" value="" value::operator="=(const" value&="" op)="" const="" {="" if(="" gettype()="=" op.gettype()="" ){="" if(="" isint()="" )="" return="" value(="" (bool)(itemp="=" op.getint()="" ));="" if(="" isreal()="" )="" return="" value(="" (bool)="" (rtemp="=" op.getreal()="" ));="" if(="" ischar())="" return="" value(="" (bool)="" (stemp="">< op.getchar()));="" }="" else="" if(isint()="" &&="" op.isreal()){="" return="" value(="" (bool)="" (((float)="" getint())="=" op.getreal()));="" }="" else="" if(isreal()="" &&="" op.isint()){="" return="" value(="" (bool)="" (getreal()="=" ((float)="" op.getint())));="" }="" else{="" return="" value();="" }="" }="" compare="" this="" with="" op="" for="">< 16="" “parserint.h”="" description="" ◼="" repository="" of="" temporaries="" construction="" using="" map="" container="" =""> TempsResults;  Each entry of TempsResults is a pair of a string and a Value object, representing a variable name, a constant, or an expression value and its corresponding Value object. ◼ Queue container for Value objects  queue * ValQue;  Declaration of a pointer variable to a queue of Value objects  Utilized to queue the evaluated list of expressions (ExprList) in a PrintStmt. The values of evaluated expressions are printed out in order from left to right by the PrintStmt. 17 “parserInt.h” Description ◼ “parserInt.h”: includes the prototype definitions of the parser functions as in “parse.h” header file with following applied modifications: extern bool Var(istream& in, int& line, LexItem & tok); extern bool LogicExpr(istream& in, int& line, Value & retVal); extern bool Expr(istream& in, int& line, Value & retVal); extern bool Term(istream& in, int& line, Value & retVal); extern bool SFactor(istream& in, int& line, Value & retVal); extern bool Factor(istream& in, int& line, int sign, Value & retVal); 18 “parserInt.h” Description ◼ NOTE:  All code segments available in “parserInt.h” have to be moved to your “parserInt.cpp” file, except the defined functions prototypes. This process is needed in order to satisfy the requirements for linking program files on Linux when you are submitting your work to Vocareum. 19 Testing Program Requirements ◼ “prog3.cpp”:  You are given the testing program “prog3.cpp” that reads a file name from the command line. The file is opened for syntax analysis and interpretation, as a source code of the language.  A call to Prog() function is made. If the call fails, the program should stop and display a message as "Unsuccessful Interpretation ", and display the number of errors detected. For example: Unsuccessful Interpretation Number of Syntax Errors: 3  If the call to Prog() function succeeds, the program should stop and display the message "Successful Execution", and the program stops. 20 Testing Program Requirements ◼ Vocareum Automatic Grading  You are provided by a set of 14 testing files associated with
Answered 22 days AfterApr 27, 2021

Answer To: PA 3 Description 1 CS 280 Programming Language Concepts Programming Assignment 3 Implementation of...

Sandeep Kumar answered on May 20 2021
151 Votes
lex.cpp
lex.cpp
/*
 * lex.cpp
 *
 * CS280 - Spring 2021
 */
#include 
#include 
#include "lex.h"
using std::map;
using namespace std;
LexItem id_or_kw(const string &lexeme, int linenum)
{
    Token tt = IDENT;
    auto kIt = kwmap.find(lexeme);
    if (kIt != kwmap.end())
        tt = kIt->second;
    return LexItem(tt, lexeme, linenum);
}
LexItem
getNextToken(istream &in, int &linenum)
{
    enum TokState
    {
        START,
        INID,
        INSTRING,
        ININT,
        INREAL,
        INCOMMENT
    } lexstate = START;
    string lexeme;
    char ch, nextch, nextchar, nextch1;
    int strtype = 0; //0 for double quotes and 1 for single quotes
    while (in.get(ch))
    {
        switch (lexstate)
        {
        case START:
            if (ch =
= '\n')
                linenum++;
            if (isspace(ch))
                continue;
            lexeme = ch;
            if (isalpha(ch))
            {
                lexeme = toupper(ch);
                lexstate = INID;
            }
            else if (ch == '"')
            {
                lexstate = INSTRING;
            }
            else if (ch == '\'')
            {
                strtype = 1;
                lexstate = INSTRING;
            }
            else if (isdigit(ch))
            {
                lexstate = ININT;
            }
            else if (ch == '!')
            {
                lexstate = INCOMMENT;
            }
            else
            {
                Token tt = ERR;
                switch (ch)
                {
                case '+':
                    tt = PLUS;
                    break;
                case '-':
                    tt = MINUS;
                    break;
                case '*':
                    tt = MULT;
                    break;
                case '/':
                    nextch1 = in.peek();
                    if (nextch1 == '/')
                    {
                        in.get(ch);
                        tt = CONCAT;
                        break;
                    }
                    tt = DIV;
                    break;
                case '=':
                    nextchar = in.peek();
                    if (nextchar == '=')
                    {
                        in.get(ch);
                        tt = EQUAL;
                        break;
                    }
                    tt = ASSOP;
                    break;
                case '(':
                    tt = LPAREN;
                    break;
                case ')':
                    tt = RPAREN;
                    break;
                case ':':
                    tt = COLON;
                    break;
                case ',':
                    tt = COMA;
                    break;
                case '<':
                    tt = LTHAN;
                    break;
                case '.':
                    nextch = in.peek();
                    if (isdigit(nextch))
                    {
                        lexstate = INREAL;
                        continue;
                    }
                    else
                    {
                        lexeme += nextch;
                        return LexItem(ERR, lexeme, linenum);
                        cout << "Here what?" << endl;
                    }
                }
                return LexItem(tt, lexeme, linenum);
            }
            break;
        case INID:
            if (isalpha(ch) || isdigit(ch))
            {
                ch = toupper(ch);
                lexeme += ch;
            }
            else
            {
                in.putback(ch);
                return id_or_kw(lexeme, linenum);
            }
            break;
        case INSTRING:
            if (ch == '\n')
            {
                return LexItem(ERR, lexeme, linenum);
            }
            lexeme += ch;
            if (ch == '"' && strtype == 0)
            {
                lexeme = lexeme.substr(1, lexeme.length() - 2);
                return LexItem(SCONST, lexeme, linenum);
            }
            else if (ch == '\'' && strtype == 1)
            {
                lexeme = lexeme.substr(1, lexeme.length() - 2);
                return LexItem(SCONST, lexeme, linenum);
            }
            break;
        case ININT:
            if (isdigit(ch))
            {
                lexeme += ch;
            }
            else if (ch == '.')
            {
                lexstate = INREAL;
                in.putback(ch);
            }
            else
            {
                in.putback(ch);
                return LexItem(ICONST, lexeme, linenum);
            }
            break;
        case INREAL:
            if (ch == '.' && isdigit(in.peek()))
            {
                lexeme += ch;
            }
            else if (isdigit(ch))
            {
                lexeme += ch;
            }
            else if (ch == '.' && !isdigit(in.peek()))
            {
                return LexItem(ERR, lexeme, linenum);
            }
            else
            {
                in.putback(ch);
                return LexItem(RCONST, lexeme, linenum);
            }
            break;
        case INCOMMENT:
            if (ch == '\n')
            {
                ++linenum;
                lexstate = START;
            }
            break;
        }
    } //end of while loop
    if (in.eof())
        return LexItem(DONE, "", linenum);
    return LexItem(ERR, "some strange I/O error", linenum);
}
ostream &operator<<(ostream &out, const LexItem &tok)
{
    Token tt = tok.GetToken();
    out << tokenPrint[tt];
    if (tt == IDENT || tt == ICONST || tt == SCONST || tt == RCONST || tt == ERR)
    {
        out << "(" << tok.GetLexeme() << ")";
    }
    return out;
}
lex.h
/*
* lex.h
*
* CS280
* Spring 2021
*/
#ifndef LEX_H_
#define LEX_H_
#include
#include
#include
using namespace std;
//Definition of all the possible token types
enum Token
{
    // keywords
    PROGRAM,
    PRINT,
    READ,
    INTEGER,
    END,
    IF,
    THEN,
    REAL,
    CHAR,
    // an identifier
    IDENT,
    // an integer, real, and string constant
    ICONST,
    RCONST,
    SCONST,
    // the operators, parens, semicolon
    PLUS,
    MINUS,
    MULT,
    DIV,
    ASSOP,
    LPAREN,
    RPAREN,
    COMA,
    EQUAL,
    LTHAN,
    CONCAT,
    COLON,
    // any error returns this token
    ERR,
    // when completed (EOF), return this token
    DONE
};
static map tokenPrint = {
    {PROGRAM, "PROGRAM"},
    {READ, "READ"},
    {INTEGER, "INTEGER"},
    {REAL, "REAL"},
    {CHAR, "CHAR"},
    {PRINT, "PRINT"},
    {IF, "IF"},
    {END, "END"},
    {THEN, "THEN"},
    {IDENT, "IDENT"},
    {ICONST, "ICONST"},
    {RCONST, "RCONST"},
    {SCONST, "SCONST"},
    {PLUS, "PLUS"},
    {MINUS, "MINUS"},
    {MULT, "MULT"},
    {DIV, "DIV"},
    {ASSOP, "ASSOP"},
    {LPAREN, "LPAREN"},
    {RPAREN, "RPAREN"},
    {COLON, "COLON"},
    {COMA, "COMA"},
    {EQUAL, "EQUAL"},
    {LTHAN, "LTHAN"},
    {CONCAT, "CONCAT"},
    {ERR, "ERR"},
    {DONE, "DONE"},
};
static map kwmap = {
    {"PROGRAM", PROGRAM},
    {"READ", READ},
    {"INTEGER", INTEGER},
    {"REAL", REAL},
    {"CHAR", CHAR},
    {"PRINT", PRINT},
    {"IF", IF},
    {"THEN", THEN},
    {"END", END},
};
//Class definition of LexItem
class LexItem
{
    Token token;
    string lexeme;
    int lnum;
public:
    LexItem()
    {
        token = ERR;
        lnum = -1;
    }
    LexItem(Token token, string lexeme, int line)
    {
        this->token = token;
        this->lexeme = lexeme;
        this->lnum = line;
    }
    bool operator==(const Token token) const { return this->token == token; }
    bool operator!=(const Token token) const { return this->token != token; }
    Token GetToken() const { return token; }
    string GetLexeme() const { return lexeme; }
    int GetLinenum() const { return lnum; }
};
extern ostream &operator<<(ostream &out, const LexItem &tok);
extern LexItem id_or_kw(const string &lexeme, int linenum);
extern LexItem getNextToken(istream &in, int &linenum);
#endif /* LEX_H_...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here