Merge branch 'main' of gitlab.cs.wallawalla.edu:lustje/language-interpreter-lab into josh_bison

This commit is contained in:
Josh 2024-11-07 09:11:02 -08:00
commit 5ea801e7dd
22 changed files with 336 additions and 133 deletions

View File

@ -8,7 +8,7 @@ extern char *yytext;
int main(int argc, char *argv[]) {
FILE *file;
const char *filename = "samples/hello-world.cbl"; // Default filename
const char *filename = "samples/quadratic_snippet.cbl"; // Default filename
// Check if a filename is provided as a command-line argument
if (argc > 1) {

View File

@ -50,3 +50,266 @@ UTEST(scanner, hello) {
++index;
} while (t != TOKEN_EOF);
}
UTEST(scanner, quadratic) {
struct token_st tokens[] = {
{TOKEN_COMMENT, "*> Code altered from https://www.quora.com/What-is-a-COBOL-program-that-will-solve-a-quadratic-equation"},
{TOKEN_COMMENT, "*> Program finds the roots to a simple quadratic equation"},
{TOKEN_IDENTIFICATION, "IDENTIFICATION"},
{TOKEN_KEYWORD_DIVISION, "DIVISION"},
{TOKEN_DOT, "."},
{TOKEN_PROGRAM_ID, "PROGRAM-ID"},
{TOKEN_DOT, "."},
{TOKEN_IDENT, "QuadraticSolver"},
{TOKEN_DOT, "."},
{TOKEN_KEYWORD_DATA, "DATA"},
{TOKEN_KEYWORD_DIVISION, "DIVISION"},
{TOKEN_DOT, "."},
{TOKEN_WORKING_STORAGE, "WORKING-STORAGE"},
{TOKEN_KEYWORD_SECTION, "SECTION"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "77"},
{TOKEN_IDENT, "a"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"}, // Check later
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_IMPLIED_DECIMAL, "V9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_3, "COMP-3"},
{TOKEN_KEYWORD_VALUE, "VALUE"},
{TOKEN_INTEGER, "1"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "77"},
{TOKEN_IDENT, "b"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_IMPLIED_DECIMAL, "V9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_3, "COMP-3"},
{TOKEN_KEYWORD_VALUE, "VALUE"},
{TOKEN_INTEGER, "5"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "77"},
{TOKEN_IDENT, "c"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_IMPLIED_DECIMAL, "V9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_3, "COMP-3"},
{TOKEN_KEYWORD_VALUE, "VALUE"},
{TOKEN_INTEGER, "6"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "77"},
{TOKEN_IDENT, "discriminant"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_IMPLIED_DECIMAL, "V9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_3, "COMP-3"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "77"},
{TOKEN_IDENT, "root1"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_IMPLIED_DECIMAL, "V9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_3, "COMP-3"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "77"},
{TOKEN_IDENT, "root2"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_IMPLIED_DECIMAL, "V9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_3, "COMP-3"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "77"},
{TOKEN_IDENT, "square-root-discriminant"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_IMPLIED_DECIMAL, "V9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_3, "COMP-3"},
{TOKEN_DOT, "."},
// {TOKEN_EOF, ""},
{TOKEN_PROCEDURE, "PROCEDURE"},
{TOKEN_KEYWORD_DIVISION, "DIVISION"},
{TOKEN_DOT, "."},
{TOKEN_COMMENT, "*> program begins here"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'EQUATION: (1x^2) + 5x + 6 = 0'"},
{TOKEN_KEYWORD_COMPUTE, "COMPUTE"},
{TOKEN_IDENT, "discriminant"},
{TOKEN_EQUAL, "="},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "b"},
{TOKEN_EXPONENTIAL, "**"},
{TOKEN_INTEGER, "2"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_SUB, "-"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "4"},
{TOKEN_MULTIPLY, "*"},
{TOKEN_IDENT, "a"},
{TOKEN_MULTIPLY, "*"},
{TOKEN_IDENT, "c"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
// {TOKEN_EOF, ""},
{TOKEN_IF, "IF"},
{TOKEN_IDENT, "discriminant"},
{TOKEN_GREATER_THAN, ">"},
{TOKEN_INTEGER, "0"},
{TOKEN_KEYWORD_COMPUTE, "COMPUTE"},
{TOKEN_IDENT, "square-root-discriminant"},
{TOKEN_EQUAL, "="},
{TOKEN_KEYWORD_FUNCTION, "FUNCTION"},
{TOKEN_IDENT, "SQRT"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "discriminant"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_KEYWORD_COMPUTE, "COMPUTE"},
{TOKEN_IDENT, "root1"},
{TOKEN_EQUAL, "="},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_SUB, "-"},
{TOKEN_IDENT, "b"},
{TOKEN_ADD, "+"},
{TOKEN_IDENT, "square-root-discriminant"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_DIVIDE, "/"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "2"},
{TOKEN_MULTIPLY, "*"},
{TOKEN_IDENT, "a"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_KEYWORD_COMPUTE, "COMPUTE"},
{TOKEN_IDENT, "root2"},
{TOKEN_EQUAL, "="},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_SUB, "-"},
{TOKEN_IDENT, "b"},
{TOKEN_SUB, "-"},
{TOKEN_IDENT, "square-root-discriminant"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_DIVIDE, "/"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "2"},
{TOKEN_MULTIPLY, "*"},
{TOKEN_IDENT, "a"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'The equation has two distinct real roots: '"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'Root 1: '"},
{TOKEN_IDENT, "root1"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'Root 2: '"},
{TOKEN_IDENT, "root2"},
// {TOKEN_EOF, ""},
{TOKEN_ELSE, "ELSE"},
{TOKEN_IF, "IF"},
{TOKEN_IDENT, "discriminant"},
{TOKEN_EQUAL, "="},
{TOKEN_INTEGER, "0"},
{TOKEN_KEYWORD_COMPUTE, "COMPUTE"},
{TOKEN_IDENT, "root1"},
{TOKEN_EQUAL, "="},
{TOKEN_SUB, "-"},
{TOKEN_IDENT, "b"},
{TOKEN_DIVIDE, "/"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "2"},
{TOKEN_MULTIPLY, "*"},
{TOKEN_IDENT, "a"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'The equation has one real root: '"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'Root: '"},
{TOKEN_IDENT, "root1"},
{TOKEN_ELSE, "ELSE"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'The equation has no real roots.'"},
// {TOKEN_EOF, ""},
{TOKEN_STOP, "STOP"},
{TOKEN_RUN, "RUN"},
{TOKEN_DOT, "."},
{TOKEN_EOF, ""},
};
yyin = fopen("samples/quadratic-snippet.cbl", "r");
ASSERT_TRUE(yyin);
int index = 0;
token_t t;
do {
printf("index: %d token: %d text: %s\n", index, t, yytext);
ASSERT_EQ(tokens[index].t, (t = yylex()));
ASSERT_STREQ(tokens[index].p, yytext);
++index;
} while (t != TOKEN_EOF);
}

View File

@ -14,22 +14,22 @@
77 square-root-discriminant PIC S9(5)V9(5) COMP-3.
PROCEDURE DIVISION. *> program begins here
DISPLAY "EQUATION: (1x^2) + 5x + 6 = 0"
DISPLAY 'EQUATION: (1x^2) + 5x + 6 = 0'
COMPUTE discriminant = (b ** 2) - (4 * a * c)
IF discriminant > 0
COMPUTE square-root-discriminant = FUNCTION SQRT(discriminant)
COMPUTE root1 = (-b + square-root-discriminant) / (2 * a)
COMPUTE root2 = (-b - square-root-discriminant) / (2 * a)
DISPLAY "The equation has two distinct real roots: "
DISPLAY "Root 1: " root1
DISPLAY "Root 2: " root2
DISPLAY 'The equation has two distinct real roots: '
DISPLAY 'Root 1: ' root1
DISPLAY 'Root 2: ' root2
ELSE IF discriminant = 0
COMPUTE root1 = -b / (2 * a)
DISPLAY "The equation has one real root: "
DISPLAY "Root: " root1
DISPLAY 'The equation has one real root: '
DISPLAY 'Root: ' root1
ELSE
DISPLAY "The equation has no real roots."
DISPLAY 'The equation has no real roots.'
STOP RUN.

View File

@ -27,7 +27,8 @@ PERFORM { return TOKEN_PERFORM; }
END-PERFORM { return TOKEN_END_PERFORM; }
IF { return TOKEN_IF; }
END-IF { return TOKEN_END_IF; }
SPACE { return TOKEN_SPACE; }
ELSE { return TOKEN_ELSE; }
SPACE { return TOKEN_SPACE; }
PIC { return TOKEN_PICTURE; }
OCCURS { return TOKEN_KEYWORD_OCCURS; }
VALUE { return TOKEN_KEYWORD_VALUE; }
@ -42,6 +43,7 @@ COMP-1 { return TOKEN_COMPUTATION_LEVEL_1; }
COMP-2 { return TOKEN_COMPUTATION_LEVEL_2; }
COMP-3 { return TOKEN_COMPUTATION_LEVEL_3; }
{DIGIT} { return TOKEN_INTEGER; }
{NAME} { return TOKEN_IDENT; }
\+ { return TOKEN_ADD; }
@ -53,6 +55,7 @@ COMP-3 { return TOKEN_COMPUTATION_LEVEL_3; }
\< { return TOKEN_LESS_THAN; }
\= { return TOKEN_EQUAL;}
"\""[^"]*"\"" { return TOKEN_STRING; }
"\'"[^']*"\'" { return TOKEN_STRING; }
"(" { return TOKEN_LEFT_PARENTHESIS; }

View File

@ -19,6 +19,7 @@ typedef enum {
TOKEN_UNTIL,
TOKEN_END_PERFORM,
TOKEN_IF,
TOKEN_ELSE,
TOKEN_END_IF,
TOKEN_SPACE,
TOKEN_KEYWORD_OCCURS,
@ -28,11 +29,13 @@ typedef enum {
TOKEN_IDENT,
TOKEN_STRING,
TOKEN_INTEGER,
TOKEN_NEGATIVE_INTEGER,
TOKEN_PICTURE,
TOKEN_ALPHANUMERIC,
TOKEN_NUMERIC,
TOKEN_SIGNED_NUMERIC,
TOKEN_IMPLIED_DECIMAL,
TOKEN_LEVEL_NUM,
TOKEN_COMPUTATION_LEVEL_0,
TOKEN_COMPUTATION_LEVEL_1,
TOKEN_COMPUTATION_LEVEL_2,

View File

@ -28,8 +28,6 @@ int yylex();
%token TOKEN_UNTIL
%token TOKEN_END_PERFORM
%token TOKEN_IF
%token TOKEN_ELSE
%token TOKEN_ELSE_IF
%token TOKEN_END_IF
%token TOKEN_SPACE
%token TOKEN_KEYWORD_OCCURS

View File

@ -27,8 +27,6 @@ PERFORM { return TOKEN_PERFORM; }
END-PERFORM { return TOKEN_END_PERFORM; }
IF { return TOKEN_IF; }
END-IF { return TOKEN_END_IF; }
ELSE { return TOKEN_ELSE; }
ELSE-IF { return TOKEN_ELSE_IF; }
SPACE { return TOKEN_SPACE; }
PIC { return TOKEN_PICTURE; }
OCCURS { return TOKEN_KEYWORD_OCCURS; }

View File

@ -5,23 +5,24 @@ See the [example lab for Python](https://gitlab.cs.wallawalla.edu/cptr354/langua
In this lab, you will focus on basic operations that support your sample code.
- Arithmetic operations - Jenessy
- add
- subtract
- multiple
- divide
- Functions (but implemented directly in the language)
- Printing - Josh
- Square root - Jenessy
- Variable for numbers - Riley
- Variable for lists (or arrays) - Riley
- Branching statements - Josh
- Looping statements - Riley
* Arithmetic operations
* add
* subtract
* multiple
* divide
* Functions (but implemented directly in the language)
* Printing
* Square root
* Variable for numbers
* Variable for lists (or arrays)
* Branching statements
* Looping statements
Notice you will find a new file `expr.c`.
The file is used to implement the parser rule.
Inside these functions, you will create the runtime code that is the interpreter.
## Build Process
The process is similar to prior labs.
@ -74,30 +75,31 @@ To remove the build files, use make clean.
make clean
```
## Assignment Steps
1. Start by confirming these commands work for the sample code provided.
1. Start by confirming these commands work for the sample code provided.
1. Next copy over your `scanner.flex`, `parser.bison` and sample programs from lab 5.
1. Next copy over your `scanner.flex`, `parser.bison` and sample programs from lab 5.
1. Start working on your bison `parser.bison` and `expr.c` files to implement the interpreter part of your parser.
## Grading Rubric
The grading will be over the following categories.
Points Description
Points Description
----------- ------------------------------------
30 points Ability to interpret — Hello world
30 points Ability to interpret — Quadratic equation
30 points Ability to interpret — Arithmetic operations
30 points Ability to interpret — Integer Sort example
20 points Ability to interpret — Looping operations
20 points Ability to interpret — Branching operations
20 points Ability to interpret — Array variables
10 points Report formatting and readability
---
30 points Ability to interpret — Hello world
30 points Ability to interpret — Quadratic equation
30 points Ability to interpret — Arithmetic operations
30 points Ability to interpret — Integer Sort example
20 points Ability to interpret — Looping operations
20 points Ability to interpret — Branching operations
20 points Ability to interpret — Array variables
10 points Report formatting and readability
## Turn In

View File

@ -0,0 +1 @@
a = [ 4, 8, 12 ];

View File

@ -0,0 +1,2 @@
a = [ 3, 5 ];
print a[0];

View File

@ -0,0 +1,4 @@
a = [ 3, 5, 7, 9, 11];
print a[1];
a[1] = 6;
print a[1];

View File

@ -0,0 +1 @@
a = 5;

View File

@ -1,5 +0,0 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-WORLD.
PROCEDURE DIVISION.
DISPLAY 'Hello World!'
STOP RUN.

View File

@ -0,0 +1,2 @@
print 5;
print 6;

View File

@ -0,0 +1,6 @@
if 3==3 then
print 3;
endif
if 3==4 then
print 4;
endif

View File

@ -0,0 +1,5 @@
if 0 then
print 5;
print 3;
print 1;
endif

View File

@ -0,0 +1,5 @@
if 1 then
print 5;
print 3;
print 1;
endif

View File

@ -0,0 +1 @@
print 5;

View File

@ -0,0 +1,2 @@
a = 4 + 4;
print a;

2
lab-5/samples/program.c Normal file
View File

@ -0,0 +1,2 @@
a=(101*20)+4;
print(a);

View File

@ -1,35 +0,0 @@
*> Code altered from https://www.quora.com/What-is-a-COBOL-program-that-will-solve-a-quadratic-equation
*> Program finds the roots to a simple quadratic equation
IDENTIFICATION DIVISION.
PROGRAM-ID. QuadraticSolver.
DATA DIVISION.
WORKING-STORAGE SECTION.
77 a PIC S9(5)V9(5) COMP-3 VALUE 1.
77 b PIC S9(5)V9(5) COMP-3 VALUE 5.
77 c PIC S9(5)V9(5) COMP-3 VALUE 6.
77 discriminant PIC S9(5)V9(5) COMP-3.
77 root1 PIC S9(5)V9(5) COMP-3.
77 root2 PIC S9(5)V9(5) COMP-3.
77 square-root-discriminant PIC S9(5)V9(5) COMP-3.
PROCEDURE DIVISION. *> program begins here
DISPLAY "EQUATION: (1x^2) + 5x + 6 = 0"
COMPUTE discriminant = (b ** 2) - (4 * a * c)
IF discriminant > 0
COMPUTE square-root-discriminant = FUNCTION SQRT(discriminant)
COMPUTE root1 = (-b + square-root-discriminant) / (2 * a)
COMPUTE root2 = (-b - square-root-discriminant) / (2 * a)
DISPLAY "The equation has two distinct real roots: "
DISPLAY "Root 1: " root1
DISPLAY "Root 2: " root2
ELSE IF discriminant = 0
COMPUTE root1 = -b / (2 * a)
DISPLAY "The equation has one real root: "
DISPLAY "Root: " root1
ELSE
DISPLAY "The equation has no real roots."
STOP RUN.

View File

@ -1,55 +0,0 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. sorting.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-SORT-AREA.
05 WS-SORT-TABLE.
10 WS-SORT-ROW PIC X(10) OCCURS 100.
05 WS-TEMP-ROW PIC X(10).
05 WS-ROW-MAX PIC S9(4) COMP VALUE 100.
05 WS-SORT-MAX PIC S9(4) COMP.
05 WS-I PIC S9(4) COMP.
05 WS-J PIC S9(4) COMP.
05 WS-INDEX PIC S9(4) COMP.
PROCEDURE DIVISION.
*> Initialize test data
MOVE "30" TO WS-SORT-ROW(1)
MOVE "10" TO WS-SORT-ROW(2)
MOVE "50" TO WS-SORT-ROW(3)
MOVE "20" TO WS-SORT-ROW(4)
MOVE "40" TO WS-SORT-ROW(5)
MOVE 5 TO WS-SORT-MAX
*> * Display original array
DISPLAY "Original Array Contents:"
DISPLAY "---------------------"
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > WS-SORT-MAX
DISPLAY "Element " WS-INDEX ": " WS-SORT-ROW(WS-INDEX)
END-PERFORM
DISPLAY SPACE
*> * Simplified bubble sort
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > WS-SORT-MAX - 1
PERFORM VARYING WS-J FROM 1 BY 1
UNTIL WS-J > WS-SORT-MAX - WS-I
IF WS-SORT-ROW(WS-J) > WS-SORT-ROW(WS-J + 1)
MOVE WS-SORT-ROW(WS-J) TO WS-TEMP-ROW
MOVE WS-SORT-ROW(WS-J + 1) TO WS-SORT-ROW(WS-J)
MOVE WS-TEMP-ROW TO WS-SORT-ROW(WS-J + 1)
END-IF
END-PERFORM
END-PERFORM
*> * Display sorted array
DISPLAY "Sorted Array Contents:"
DISPLAY "--------------------"
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > WS-SORT-MAX
DISPLAY "Element " WS-INDEX ": " WS-SORT-ROW(WS-INDEX)
END-PERFORM.
STOP RUN.