Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The goal of this assignment is the development of an interpreter for a subset of

ID: 3848794 • Letter: T

Question

The goal of this assignment is the development of an interpreter for a subset of the SCL language. The interpreter can implemented in any of the following programming languages: C/C++, Java, Python, or Ada.

Interpreter

This project consists of developing an interpreter for a minimal form (subset) of the SCL language. The specification of the grammar is given below.

The interpreter will process an SCL program and build some intermediate data structures. These data structures will then be interpreted to execute the program. All tokens in this language are separated by white space. The parsing algorithm should detect any syntactical or semantic error. The first such error discovered should cause an appropriate error message to be printed, and then the interpreter should terminate. Run-time errors should also be detected with appropriate error messages being printed.

rammar for the (subset of SCL) language Syntax Rules, see scl_subset.yy

Lexical Rules

identifier letter char_list
char_list letter_digit char_list | letter_digit

literal_integer digit literal_integer | digit assignment_operator =
le_operator <=
lt_operator <

ge_operator >=

gt_operator > eq_operator = = ne_operator ~= add_operator + sub_operator - mul_operator * div_operator /

///// scl_subset.yy

%{
/*
SCL A Scientific Computing Language
// for the low-level programming

// First implemented as a pre-processor that generates C programs
// Feb. 2016
//
// Subset of SCL specified for YACC (Bison), Jan 2017
// Department of Computer Science
// Kennessaw State University

start : symbols forward_refs specifications globals implement
;
symbols :
| symbols symbol_def
;
symbol_def : SYMBOL IDENTIFIER HCON
;
forward_refs :
| FORWARD frefs
;
frefs : REFERENCES forward_list
| forward_list
;
forward_list : forwards
| forward_list forwards
;
forwards :
| check_ext func_main dec_parameters
;
check_ext :
| MEXTERN
;
func_main :
| FUNCTION IDENTIFIER oper_type
| MAIN {dec_main();}
;
oper_type : RETURN chk_ptr chk_array ret_type
;
chk_ptr :
| POINTER {pointer_flag = true;}
;
chk_array :
| ARRAY array_dim_list
;
array_dim_list : LB array_index RB
| array_dim_list LB array_index RB
;
array_index : IDENTIFIER
| ICON
;

ret_type : TYPE type_name
| STRUCT IDENTIFIER
| STRUCTYPE IDENTIFIER
;   
type_name : MVOID
| INTEGER   
| SHORT
| REAL
| FLOAT
| DOUBLE
| TBOOL   
| CHAR
| TSTRING OF LENGTH ICON
| TBYTE   
;

specifications :
| SPECIFICATIONS spec_list
;
spec_list : spec_def
| spec_list spec_def
;
spec_def : ENUM
| STRUCT
;
globals :
| GLOBAL declarations
;
declarations :
| DECLARATIONS
;
implement : IMPLEMENTATIONS funct_list
;
funct_list : funct_def
| funct_list funct_def
;
funct_def : funct_body
;
funct_body: FUNCTION main_head parameters f_body
;
main_head : MAIN
| IDENTIFIER
;   
parameters :
| PARAMETERS param_list
;
param_list : param_def
| param_list COMMA param_def
;
param_def : identifier chk_const chk_ptr chk_array OF TYPE type_name
;
chk_const :
| CONSTANT
;
f_body : BEGIN <statement_list> ENDFUN
;
statement_list : statement
| statement_list statement
;
statement : if_statement
| assignment_statement
       | while_statement
       | print_statement
       | repeat_statement
;
if_statement : IF boolean_expression THEN statement_list
ELSE statement_list ENDIF
   ;

while_statement : WHILE boolean_expression DO statement_list ENDWHILE
;

assignment_statement : LET identifier assignment_operator arithmetic_expression
;

repeat_statement : REPEAT statement_list UNTIL boolean_expression ENDREPEAT
;

print_statement : DISPLAY arg_list
;
arg_list : args
| arg_list comma args
       ;
args : identifier
| constant
| string
   ;
     
boolean_expression : arithmetic_exp relative_op arithmetic_exp
;

relative_op : le_operator | lt_operator | ge_operator | gt_operator | eq_operator | ne_operator
;

arithmetic_exp : arithmetic_exp add_operator mulexp
| arithmetic_exp sub_operator mulexp
           | mulexp
           ;
mulexp : mulexp mul_operator primary
| mulexp div_operator primary
| primary
;
primary : left_paren arithmetic_exp right_paren
| minus primary
       | constant
       | identifier
;   

Explanation / Answer

#include "setjmp.h"
#include "math.h"
#include "ctype.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
#define NUM_FUNC 200
#define NUM_GLOBAL_VARS 200
#define NUM_LOCAL_VARS 300
#define ID_LEN 41
#define FUNC_CALLS 41
#define PROG_SIZE 10000
#define FOR_NEST 41
enum tok_types {DELIMITER, IDENTIFIER, NUMBER, KEYWORD, TEMP,
STRING, BLOCK};
enum tokens {ARG, CHAR, INT, IF, ELSE, FOR, DO, WHILE, SWITCH,
RETURN, EOL, FINISHED, END};
enum double_ops {LT=1, LE, GT, GE, EQ, NE};
enum error_msg
{SYNTAX, UNBAL_PARENS, NO_EXP, EQUALS_EXPECTED,
NOT_VAR, PARAM_ERR, SEMI_EXPECTED,
UNBAL_BRACES, FUNC_UNDEF, TYPE_EXPECTED,
NEST_FUNC, RET_NOCALL, PAREN_EXPECTED,
WHILE_EXPECTED, QUOTE_EXPECTED, NOT_TEMP,
TOO_MANY_LVARS};
extern char *prog;
extern char *p_buf;
extern jmp_buf e_buf;
extern struct var_type {
char var_name[32];
enum variable_type var_type;
int value;
} global_vars[NUM_GLOBAL_VARS];
extern struct func_type {
char func_name[32];
char *loc;
} func_stack[NUM_FUNC];
extern struct commands {
char command[20];
char tok;
} table[];
int call_getche(void), call_putch(void);
int call_puts(void), print(void), getnum(void);

struct intern_func_type {
char *f_name;/
int (* p)(); /* pointer to the function */
} intern_func[] = {
"getche", call_getche,
"putch", call_putch,
"puts", call_puts,
"print", print,
"getnum", getnum,
"", 0
};
extern char token[80];
extern char token_type;
extern char tok;
extern int ret_value;
void eval_exp(int *value), eval_exp1(int *value);
void eval_exp2(int *value);
void eval_exp3(int *value), eval_exp4(int *value);
void eval_exp5(int *value), atom(int *value);
void eval_exp0(int *value);
void sntx_err(int error), putback(void);
void assign_var(char *var_name, int value);
int isdelim(char c), look_up(char *s), iswhite(char c);
int find_var(char *s), get_token(void);
int internal_func(char *s);
int is_var(char *s);
char *find_func(char *name);
void call(void);
void eval_exp(int *value)
{
get_token();
if(!*token) {
sntx_err(NO_EXP);
return;
}
if(*token==';') {
*value = 0;
return;
}
eval_exp0(value);
putback();
}
void eval_exp0(int *value)
{
char temp[ID_LEN];
register int temp_tok;
if(token_type==IDENTIFIER) {
if(is_var(token)) {
strcpy(temp, token);
temp_tok = token_type;
get_token();
if(*token=='=') {
get_token();
eval_exp0(value);
assign_var(temp, *value);
return;
}
else {
putback();
strcpy(token, temp);
token_type = temp_tok;
}
}
}
eval_exp1(value);
}
char relops[7] = {
LT, LE, GT, GE, EQ, NE, 0
};
void eval_exp1(int *value)
{
int partial_value;
register char op;
eval_exp2(value);
op = *token;
if(strchr(relops, op)) {
get_token();
eval_exp2(&partial_value);
switch(op) {
case LT:
*value = *value < partial_value;
break;
case LE:
*value = *value <= partial_value;
break;
case GT:
*value = *value > partial_value;
break;
case GE:
*value = *value >= partial_value;
break;
case EQ:
*value = *value == partial_value;
break;
case NE:
*value = *value != partial_value;
break;
}
}
}
void eval_exp2(int *value)
{
register char op;
int partial_value;
eval_exp3(value);
while((op = *token) == '+' || op == '-') {
get_token();
eval_exp3(&partial_value);
switch(op) {
case '-':
*value = *value - partial_value;
break;
case '+':
*value = *value + partial_value;
break;
}
}
}
void eval_exp3(int *value)
{
register char op;
int partial_value, t;
eval_exp4(value);
while((op = *token) == '*' || op == '/' || op == '%') {
get_token();
eval_exp4(&partial_value);
switch(op) {
case '*':
*value = *value * partial_value;
break;
case '/':
*value = (*value) / partial_value;
break;
case '%':
t = (*value) / partial_value;
*value = *value-(t * partial_value);
break;
}
}
}
void eval_exp4(int *value)
{
register char op;
op = '';
if(*token=='+' || *token=='-') {
op = *token;
get_token();
}
eval_exp5(value);
if(op)
if(op=='-') *value = -(*value);
}
void eval_exp5(int *value)
{
if((*token == '(')) {
get_token();
eval_exp0(value);
if(*token != ')') sntx_err(PAREN_EXPECTED);
get_token();
}
else
atom(value);
}
void atom(int *value)
{
int i;
switch(token_type) {
case IDENTIFIER:
i = internal_func(token);
if(i!= -1) {
*value = (*intern_func[i].p)();
}
else
if(find_func(token)){
call();
*value = ret_value;
}
else *value = find_var(token);
get_token();
return;
case NUMBER:
*value = atoi(token);
get_token();
return;
case DELIMITER:
if(*token==''') {
*value = *prog;
prog++;
if(*prog!=''') sntx_err(QUOTE_EXPECTED);
prog++;
get_token();
}
return;
default:
if(*token==')') return;
else sntx_err(SYNTAX);
}
}
void sntx_err(int error)
{
char *p, *temp;
int linecount = 0;
register int i;
static char *e[]= {
"syntax error",
"unbalanced parentheses",
"no expression present",
"equals sign expected",
"not a variable",
"parameter error",
"semicolon expected",
"unbalanced braces",
"function undefined",
"type specifier expected",
"too many nested function calls",
"return without call",
"parentheses expected",
"while expected",
"closing quote expected",
"not a string",
"too many local variables"
};
printf("%s", e[error]);
p = p_buf;
while(p != prog) {
p++;
if(*p == ' ') {
linecount++;
}
}
printf(" in line %d ", linecount);
temp = p;
for(i=0; i<20 && p>p_buf && *p!=' '; i++, p--);
for(i=0; i<30 && p<=temp; i++, p++) printf("%c", *p);
longjmp(e_buf, 1);
}
get_token(void)
{
register char *temp;
token_type = 0; tok = 0;
temp = token;
*temp = '';
while(iswhite(*prog) && *prog) ++prog;
if(*prog==' ') {
++prog;
++prog;
while(iswhite(*prog) && *prog) ++prog;
}
if(*prog=='') {
*token = '';
tok = FINISHED;
return(token_type=DELIMITER);
}
if(strchr("{}", *prog)) {
*temp = *prog;
temp++;
*temp = '';
prog++;
return (token_type = BLOCK);
}
if(*prog=='/')
if(*(prog+1)=='*') {
prog += 2;
do {
while(*prog!='*') prog++;
prog++;
} while (*prog!='/');
prog++;
}
if(strchr("!<>=", *prog)) {
switch(*prog) {
case '=': if(*(prog+1)=='=') {
prog++; prog++;
*temp = EQ;
temp++; *temp = EQ; temp++;
*temp = '';
}
break;
case '!': if(*(prog+1)=='=') {
prog++; prog++;
*temp = NE;
temp++; *temp = NE; temp++;
*temp = '';
}
break;
case '<': if(*(prog+1)=='=') {
prog++; prog++;
*temp = LE; temp++; *temp = LE;
}
else {
prog++;
*temp = LT;
}
temp++;
*temp = '';
break;
case '>': if(*(prog+1)=='=') {
prog++; prog++;
*temp = GE; temp++; *temp = GE;
}
else {
prog++;
*temp = GT;
}
temp++;
*temp = '';
break;
}
if(*token) return(token_type = DELIMITER);
}
if(strchr("+-*^/%=;(),'", *prog)){
*temp = *prog;
prog++;
temp++;
*temp = '';
return (token_type=DELIMITER);
}
if(*prog=='"') {
prog++;
while(*prog!='"'&& *prog!=' ') *temp++ = *prog++;
if(*prog==' ') sntx_err(SYNTAX);
prog++; *temp = '';
return(token_type=STRING);
}
if(isdigit(*prog)) {
while(!isdelim(*prog)) *temp++ = *prog++;
*temp = '';
return(token_type = NUMBER);
}
if(isalpha(*prog)) {
while(!isdelim(*prog)) *temp++ = *prog++;
token_type=TEMP;
}
*temp = '';
if(token_type==TEMP) {
tok = look_up(token);
if(tok) token_type = KEYWORD;
else token_type = IDENTIFIER;
}
return token_type;
}
void putback(void)
{
char *t;
t = token;
for(; *t; t++) prog--;
}
look_up(char *s)
{
register int i;
char *p;
p = s;
while(*p){ *p = tolower(*p); p++; }
for(i=0; *table[i].command; i++)
if(!strcmp(table[i].command, s)) return table[i].tok;
return 0;
}
internal_func(char *s)
{
int i;
for(i=0; intern_func[i].f_name[0]; i++) {
if(!strcmp(intern_func[i].f_name, s)) return i;
}
return -1;
}
isdelim(char c)
{
if(strchr(" !;,+-<>'/*%^=()", c) || c==9 ||
c==' ' || c==0) return 1;
return 0;
}
iswhite(char c)
{
if(c==' ' || c==' ') return 1;
else return 0;
}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote