clean up codebase, add github action to run test

This commit is contained in:
Riley Smith 2024-11-17 02:18:25 -08:00
parent f53cd91890
commit 141b10c9c9
No known key found for this signature in database
GPG Key ID: 5D27A014FD4A29C8
68 changed files with 27 additions and 5416 deletions

21
.github/workflows/run_tests.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Run Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu
steps:
- uses: actions/checkout@v2
# setup build-essentials & flex & bison
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install build-essential flex bison
- name: Run tests
run: |
make run_tests

View File

@ -1,39 +0,0 @@
---
lab_3_tests:
stage: test
image: gitlab.cs.wallawalla.edu:5050/cs_department/docker-images/cpp
script:
- apt update
- apt install -y flex bison
- bison --version
- cd lab-3
- echo "Lab 3 - Flex"
- flex -o scanner.c scanner.flex
- echo "Lab 3 - Compile Tests"
- gcc main_test.c scanner.c -o scanner_test.out
- echo "Lab 3 - Run Tests"
- ./scanner_test.out
lab_4_tests:
stage: test
image: gitlab.cs.wallawalla.edu:5050/cs_department/docker-images/cpp
script:
- apt update
- apt install -y flex bison
- bison --version
- cd lab-4
- echo "Lab 4 - Bison Parser"
- make test
- ./parser_test.out
lab_5_tests:
stage: test
image: gitlab.cs.wallawalla.edu:5050/cs_department/docker-images/cpp
script:
- apt update
- apt install -y flex bison
- bison --version
- cd lab-5
- echo "Lab 5 - Interpreter"
- make test
- ./interpreter_test.out

View File

@ -1,72 +1,9 @@
# Language Interpreter Lab
# COBOL Interpreter Lab
The project has been set up for Flex and Bison.
You must add your language definitions to the _lab-2_ folder.
Each lab has a separate folder where you will continue working on your scanner, parser, and interpreter.
The Unit Test will be automatically run when you commit to Gitlab.
## Overview
## Forking the Repository
During my compilers and languages class at Walla Walla University, my group chose to make a COBOL interpreter.
To create a fork of this repository, click on the *fork* button on the original repository at <https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab>.
Copy the URL of your forked repository by clicking the clipboard icon next to it.
The URL should look something like:
This is the resulting project.
```shell
git@gitlab.cs.wallawalla.edu:YourUsername/language-interpreter-lab.git
```
Once you have forked the repository, you must set its visibility level to private so that only you can see it.
To do this,
1. Click on the gear icon at the top right of the project page in GitLab.
2. Select *Edit Project* from the drop-down menu.
3. Set the *Visibility Level* to *Private* in the *Project settings* box.
4. Scroll down until you find the green *Save changes* button and click it.
Add your partner to the project.
From the project homepage:
1. Click on the side menu labeled *Members*.
2. Search for your partner.
3. Give them *Maintainer* access to the project.
## Setting Up Your Local Workspace
Create your local workspace by cloning the repository to your machine.
Put the repository in a place that will remember.
You can clone the repository by using a command similar to this:
```shell
git clone git@gitlab.cs.wallawalla.edu:YourUsername/language-interpreter-lab.git
```
If you are asked to enter a password, you need to set up your SSH key.
```shell
ssh-keygen
more ~/.ssh/id_rsa.pub
```
Copy the generated public key into GitLab under your profile SSH keys
Finally, to make sure that you can receive updates easily (see below), type the
following commands in the command window at the bottom of the Cloud 9 screen.
```shell
git remote add upstream git@gitlab.cs.wallawalla.edu:cptr354/language-interpreter-lab.git
```
## Passing Tests
Every time you commit code and push it to GitLab, the test will be automatically executed.
You can find the results by looking at the **CI/CD** menu option.
It will list the recent jobs executed and show their status.
You can find the details of each job by clicking on them.
## Examples
A few repositories with code describing **b-minor** which is described in the textbook.
* <https://github.com/tgfisher4/bminor-compiler>
* <https://github.com/johnedquinn/bminor>
> This interpreter is based on the work of Douglas Thain who created the [Compiler Book](https://www3.nd.edu/~dthain/compilerbook/)

View File

@ -1,144 +0,0 @@
# Language Proposal
### 1. Hello World
- source used: [Cobol Emulator](https://www.jdoodle.com/execute-cobol-online)
- display the text "Hello World!" in the terminal
- https://www.tutorialspoint.com/cobol/cobol_program_structure.htm this website has useful information about the structure of the cobol language
- the Identification Division is mandatory for all programs and sub divisions have unique sentences within them and determine what is done with variables or IO in this example
#### Input
there is no input for this example
#### Output
the string "Hello World!" is sent to output via the included DISPLAY function
### 2. Quadratic Function
- Code altered from [Marco Biagini](https://www.quora.com/What-is-a-COBOL-program-that-will-solve-a-quadratic-equation)
- Solves a quadratic equation of the form **ax^2 + bx + c = 0**
#### Input
Coefficients are a fixed value with a = 1, b = 5, c = 6
#### Output
EQUATION: (1x^2) + 5x + 6 = 0
The equation has two distinct real roots:
Root 1: -02.00
Root 2: -03.00
### 3. Integer Sort
- Code altered from [Wikibooks]https://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Bubble_sort#COBOL
- Uses bubble sort to sort an array of integers.
#### Input
An array of integers
#### Output
The array sorted in ascending order
### 4. Language Features
- #### Identifiers
All variables are declared within DATA DIVISION. Variable names accept letters(A-Z), digits(0-9), and hyphens(-). In the syntax of:
<level-number> <variable-name>
[PIC/PICTURE <data-type(variable-length>)]
[VALUE <literal-value>]
Statements in [ ] are optional. Example:
01 INT-VAR PIC 9(03 VALUE 123).
- #### Special words
- Note: Keywords are not case sensitive but good practice is to only use uppercase
- Division statements divide the structure of the code. Some examples are PROGRAM-ID, DATA DIVISION, WORKING STORAGE DIVISION, PROCEDURE DIVISION, and STOP RUN.
- DISPLAY outputs data to user
- MOVE sends data from one variable to another
- ACCEPT allows for user input to go into a variable
- Supports boolean values TRUE and FALSE
- #### Literal
*> This is a comment in COBOL
Non-numeric
DISPLAY "This is a string in COBOL".
DISPLAY 'This is a string in COBOL'.
Numeric
Digits 0 - 9
Positive numbers: +10
Negative numbers: -10
Decimal: 10.00
- #### Math Operators
Supports additon (+), subraction (-), multiplication (\*), and division (/) and exponentation (\*\*). Equations begin with COMPUTE.
COMPUTE total = 1 + 2
- #### Relational Operators
Supports =, >, <, >=, <=, NOT =
IF a > b
- #### Delimiters
Section headers and verb statements should end with a separator period (.)
PROCEDURE DIVISION.
MOVE "Hello" TO VAR1.
Commas (,) can separate two variables
ADD 3 TO VAR1, VAR2.
- #### Lists
Supports arrays (known in COBOL as tables). Declared in DATA DIVISION. In the syntax of:
01 <table-name>.
02 <variable-name> [PIC <data-type(length1)>]
OCCURS <int1> [TO <int2>] TIMES
[DEPENDING ON]
[DESCENDING|ASCENDING KEY IS <key_var>]
[INDEXED BY <index_name>]
Statements in [ ] are optional. Example:
01 Students
03 Student-grades PIC 9(03) OCCURS 6 TIMES.
- #### Loops
Loops begin with a PERFORM statement and end with END-PERFORM. Note that a separator period (.) should not used within a PERFORM block.
PERFORM <conditional statement>
<statements-block>
END-PERFORM.
- #### Branching
Uses IF/END-IF and ELSE statements and nested statements. Note that a separator period (.) should not used within an IF statement.
IF <condition>
DISPLAY "Option 1"
ELSE
DISPLAY "Option 2"
END-IF.
`Language Feature Sources`
- [tutorialspoint.com](https://www.tutorialspoint.com/cobol/cobol_basic_syntax.htm)
- [mainframestechhelp.com](https://www.mainframestechhelp.com/tutorials/cobol/)

View File

@ -1,99 +0,0 @@
# Language Proposal
In this class we will have a series of labs focus developing and implementing an interpreter for a known language.
In this lab you will start the process by researching the language definition for your language.
You will gather code examples and language definitions for specific features.
## Language Choices
Please select one of the following languages (that has not been selected by someone else) for your language interpreter lab project:
ADA 80
Algol 68
COBOL
Dartmouth BASIC
Dart
F#
Fortran 77
MUMPS
Perl
Rust
Smalltalk
Swift
The following are also options, but carry a 5% penalty since they are more familiar:
C++
JavaScript
Ruby
## Code Example
To help guide the features needed in our interpreter, please find the code to implement these tasks.
* Hello World!
* Use the quadratic function to solve an equation
* Sort a list of integers (using any algorithm; keep it simple)
These code snippets will be used as a test case in your interpreter.
If you did not write this code, please cite the source.
Please create files in the `lab-2` folder to hold the snippets of code.
Use the `lab-2/LANGUAGE.md` to describe the input and output for these code snippets.
## Review The Code Snippets
What features are needed to implement this code?
Identifiers
Special words
Literal
Math Operators
Relational Operators
Delimiters
Lists
Loops
Branching
For each feature write down the definition for that feature. For example, create a list of special words (or reserved words) used by your code.
For something like Identifiers, what are the naming rules for an identifier? Please cite sources for language definition.
A Partial Example
An partial example report has been posted for the Python language.
See the example report: <https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab-python>
## Criteria
The following things will be looked for when grading your report:
* Code Snippet — Hello World code, input, and resulting output
* Code Snippet — Quadratic equation code, input, and resulting output
* Code Snippet — Integer sorting code, input, and resulting output
* Language Features — List of required language features
* Language Definitions — For each feature, define the syntax and rules to implement the feature
* Report skills — Easy to follow and writing quality
Your report and code should be in a forked project from <https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab>. Follow the `README.md` to configure your project.
## Grading Rubric
The grading will be over the following categories.
Points Description
----------- ------------------------------------
20 points Code Snippet — Quadratic equation
20 points Code Snippet — Integer sorting
10 points Language Features
40 points Language Definitions
10 points Report formatting and readability
## Turn In
Please submit the URL of your gitlab project to D2L's Brightspace with your report.
On gitlab update the `lab-2` folder to have your report and code snippets before the due date.

View File

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

View File

@ -1 +0,0 @@
2+3

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.

View File

@ -1,73 +0,0 @@
# Flex Scanner
Create a scanner for your sample programs.
See the [example lab for Python](https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab-python).
## Language Scanner
Add the tokens needed to scan your sample code files.
In addition include the following:
* All the math operations (+,-,/,* etc.)
* All boolean expression (==,>,< etc.)
* All relational operators (not,and,or)
* ...
## Testing the Language Scanner
Write unit test for your sample code.
The sample program uses `utest.h` which is a simple c unit test framework.
The documentation can be found at <https://github.com/sheredom/utest.h>.
The `main.c` has been replaced with unit test code.
Your task is to create one unit test for each sample file.
When you submit the code to GitLab, the CI should automatically compile and run your test code.
To recieve full credit, the tests must pass when run through GitLab CI.
## Build Process
To build the `scanner.c` run the following **flex** command.
```sh
flex -o scanner.c scanner.flex
```
Then build the `main.c` and `scanner.c` using **gcc**.
```sh
gcc main_test.c scanner.c -o scanner_test.out
```
Then execute the test suite using `./scanner_test.out`.
```sh
./scanner_test.out
```
## Scanner Only
```sh
flex -o scanner.c scanner.flex
gcc main.c scanner.c -o scanner.out
./scanner.out
```
## Grading Rubric
The grading will be over the following categories.
Points Description
----------- ------------------------------------
30 points Tests for individual language tokens
10 points Ability to scan — Hello world
20 points Ability to scan — Quadratic equation
20 points Ability to scan — Integer sorting
20 points Passes continuous integration
## Turn In
Please submit the URL of your gitlab project to D2L's Brightspace with your report.
On gitlab update the `lab-3` folder to have your report and code snippets before the due date.

View File

@ -1,30 +0,0 @@
#include "token.h"
#include <stdio.h>
#include <stdlib.h>
extern FILE *yyin;
extern int yylex();
extern char *yytext;
int main(int argc, char *argv[]) {
FILE *file;
const char *filename = "samples/quadratic-snippet.cbl";
// Check if a filename is provided as a command-line argument
if (argc > 1) {
filename = argv[1];
}
// Open the file
yyin = fopen(filename, "r");
if (!yyin) {
printf("could not open file!\n");
return 1;
}
while (1) {
token_t t = yylex();
if (t == TOKEN_EOF)
break;
printf("token: %d, text: %s\n", t, yytext);
}
}

View File

@ -1,577 +0,0 @@
#include "token.h"
// https://github.com/sheredom/utest.h/blob/master/utest.h
#include "utest.h"
#include <stdio.h>
typedef struct yy_buffer_state *YY_BUFFER_STATE;
extern void yyrestart(FILE * input_file);
extern YY_BUFFER_STATE yy_scan_buffer(char *str, int i);
extern void yy_delete_buffer(YY_BUFFER_STATE buffer);
extern FILE *yyin;
extern int yylex();
extern char *yytext;
UTEST_MAIN();
struct token_st {
token_t t;
char *p;
};
UTEST(scanner, hello) {
struct token_st tokens[] = {
{TOKEN_KEYWORD_IDENTIFICATION, "IDENTIFICATION"},
{TOKEN_KEYWORD_DIVISION, "DIVISION"},
{TOKEN_DOT, "."},
{TOKEN_PROGRAM_ID, "PROGRAM-ID"},
{TOKEN_DOT, "."},
{TOKEN_IDENT, "HELLO-WORLD"},
{TOKEN_DOT, "."},
{TOKEN_PROCEDURE, "PROCEDURE"},
{TOKEN_KEYWORD_DIVISION, "DIVISION"},
{TOKEN_DOT, "."},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'Hello World!'"},
{TOKEN_STOP, "STOP"},
{TOKEN_RUN, "RUN"},
{TOKEN_DOT, "."},
{TOKEN_EOF, ""},
};
yyin = fopen("samples/hello-world.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);
}
UTEST(scanner, quadratic) {
struct token_st tokens[] = {
{TOKEN_KEYWORD_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_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_END_IF, "END-IF"},
// {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);
}
UTEST(scanner, sorting) {
struct token_st tokens[] = {
{TOKEN_KEYWORD_IDENTIFICATION, "IDENTIFICATION"},
{TOKEN_KEYWORD_DIVISION, "DIVISION"},
{TOKEN_DOT, "."},
{TOKEN_PROGRAM_ID, "PROGRAM-ID"},
{TOKEN_DOT, "."},
{TOKEN_IDENT, "sorting"},
{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, "01"},
{TOKEN_IDENT, "WS-SORT-AREA"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "05"},
{TOKEN_IDENT, "WS-SORT-TABLE"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "10"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_ALPHANUMERIC, "X"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "10"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_KEYWORD_OCCURS, "OCCURS"},
{TOKEN_INTEGER, "100"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "05"},
{TOKEN_IDENT, "WS-TEMP-ROW"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_ALPHANUMERIC, "X"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "10"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "05"},
{TOKEN_IDENT, "WS-ROW-MAX"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "4"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_0, "COMP"},
{TOKEN_KEYWORD_VALUE, "VALUE"},
{TOKEN_INTEGER, "100"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "05"},
{TOKEN_IDENT, "WS-SORT-MAX"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "4"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_0, "COMP"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "05"},
{TOKEN_IDENT, "WS-I"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "4"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_0, "COMP"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "05"},
{TOKEN_IDENT, "WS-J"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "4"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_0, "COMP"},
{TOKEN_DOT, "."},
{TOKEN_INTEGER, "05"},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_PICTURE, "PIC"},
{TOKEN_SIGNED_NUMERIC, "S9"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "4"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_COMPUTATION_LEVEL_0, "COMP"},
{TOKEN_DOT, "."},
{TOKEN_PROCEDURE, "PROCEDURE"},
{TOKEN_KEYWORD_DIVISION, "DIVISION"},
{TOKEN_DOT, "."},
{TOKEN_MOVE, "MOVE"},
{TOKEN_STRING, "\"30\""},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "1"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_MOVE, "MOVE"},
{TOKEN_STRING, "\"10\""},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "2"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_MOVE, "MOVE"},
{TOKEN_STRING, "\"50\""},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "3"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_MOVE, "MOVE"},
{TOKEN_STRING, "\"20\""},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "4"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_MOVE, "MOVE"},
{TOKEN_STRING, "\"40\""},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_INTEGER, "5"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_MOVE, "MOVE"},
{TOKEN_INTEGER, "5"},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-SORT-MAX"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "\"Original Array Contents:\""},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "\"---------------------\""},
{TOKEN_PERFORM, "PERFORM"},
{TOKEN_VARYING, "VARYING"},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_KEYWORD_FROM, "FROM"},
{TOKEN_INTEGER, "1"},
{TOKEN_KEYWORD_BY, "BY"},
{TOKEN_INTEGER, "1"},
{TOKEN_UNTIL, "UNTIL"},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_GREATER_THAN, ">"},
{TOKEN_IDENT, "WS-SORT-MAX"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "\"Element \""},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_STRING, "\": \""},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_END_PERFORM, "END-PERFORM"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_SPACE, "SPACE"},
{TOKEN_PERFORM, "PERFORM"},
{TOKEN_VARYING, "VARYING"},
{TOKEN_IDENT, "WS-I"},
{TOKEN_KEYWORD_FROM, "FROM"},
{TOKEN_INTEGER, "1"},
{TOKEN_KEYWORD_BY, "BY"},
{TOKEN_INTEGER, "1"},
{TOKEN_UNTIL, "UNTIL"},
{TOKEN_IDENT, "WS-I"},
{TOKEN_GREATER_THAN, ">"},
{TOKEN_IDENT, "WS-SORT-MAX"},
{TOKEN_SUB, "-"},
{TOKEN_INTEGER, "1"},
{TOKEN_PERFORM, "PERFORM"},
{TOKEN_VARYING, "VARYING"},
{TOKEN_IDENT, "WS-J"},
{TOKEN_KEYWORD_FROM, "FROM"},
{TOKEN_INTEGER, "1"},
{TOKEN_KEYWORD_BY, "BY"},
{TOKEN_INTEGER, "1"},
{TOKEN_UNTIL, "UNTIL"},
{TOKEN_IDENT, "WS-J"},
{TOKEN_GREATER_THAN, ">"},
{TOKEN_IDENT, "WS-SORT-MAX"},
{TOKEN_SUB, "-"},
{TOKEN_IDENT, "WS-I"},
{TOKEN_IF, "IF"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "WS-J"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_GREATER_THAN, ">"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "WS-J"},
{TOKEN_ADD, "+"},
{TOKEN_INTEGER, "1"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_MOVE, "MOVE"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "WS-J"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-TEMP-ROW"},
{TOKEN_MOVE, "MOVE"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "WS-J"},
{TOKEN_ADD, "+"},
{TOKEN_INTEGER, "1"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "WS-J"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_MOVE, "MOVE"},
{TOKEN_IDENT, "WS-TEMP-ROW"},
{TOKEN_KEYWORD_TO, "TO"},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "WS-J"},
{TOKEN_ADD, "+"},
{TOKEN_INTEGER, "1"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_END_IF, "END-IF"},
{TOKEN_END_PERFORM, "END-PERFORM"},
{TOKEN_END_PERFORM, "END-PERFORM"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "\"Sorted Array Contents:\""},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "\"--------------------\""},
{TOKEN_PERFORM, "PERFORM"},
{TOKEN_VARYING, "VARYING"},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_KEYWORD_FROM, "FROM"},
{TOKEN_INTEGER, "1"},
{TOKEN_KEYWORD_BY, "BY"},
{TOKEN_INTEGER, "1"},
{TOKEN_UNTIL, "UNTIL"},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_GREATER_THAN, ">"},
{TOKEN_IDENT, "WS-SORT-MAX"},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "\"Element \""},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_STRING, "\": \""},
{TOKEN_IDENT, "WS-SORT-ROW"},
{TOKEN_LEFT_PARENTHESIS, "("},
{TOKEN_IDENT, "WS-INDEX"},
{TOKEN_RIGHT_PARENTHESIS, ")"},
{TOKEN_END_PERFORM, "END-PERFORM"},
{TOKEN_DOT, "."},
{TOKEN_STOP, "STOP"},
{TOKEN_RUN, "RUN"},
{TOKEN_DOT, "."},
{TOKEN_EOF, ""},
};
yyin = fopen("samples/sorting-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

@ -1,34 +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."
END-IF
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.

Binary file not shown.

View File

@ -1,69 +0,0 @@
%{
#include "token.h"
%}
%option warn
%option nodefault
%option yylineno
NAME [a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?
DIGIT [0-9]+
%%
(" "|\t|\n) /* skip whitespace */
\*>\ ?.*
IDENTIFICATION { return TOKEN_KEYWORD_IDENTIFICATION; }
DIVISION { return TOKEN_KEYWORD_DIVISION; }
PROGRAM-ID { return TOKEN_PROGRAM_ID; }
PROCEDURE { return TOKEN_PROCEDURE; }
DATA { return TOKEN_KEYWORD_DATA; }
SECTION { return TOKEN_KEYWORD_SECTION; }
WORKING-STORAGE { return TOKEN_WORKING_STORAGE; }
DISPLAY { return TOKEN_DISPLAY; }
STOP { return TOKEN_STOP; }
RUN { return TOKEN_RUN; }
MOVE { return TOKEN_MOVE; }
TO { return TOKEN_KEYWORD_TO; }
VARYING { return TOKEN_VARYING; }
FROM { return TOKEN_KEYWORD_FROM; }
BY { return TOKEN_KEYWORD_BY; }
UNTIL { return TOKEN_UNTIL; }
PERFORM { return TOKEN_PERFORM; }
END-PERFORM { return TOKEN_END_PERFORM; }
IF { return TOKEN_IF; }
ELSE { return TOKEN_ELSE; }
END-IF { return TOKEN_END_IF; }
SPACE { return TOKEN_SPACE; }
PIC { return TOKEN_PICTURE; }
OCCURS { return TOKEN_KEYWORD_OCCURS; }
VALUE { return TOKEN_KEYWORD_VALUE; }
COMPUTE { return TOKEN_KEYWORD_COMPUTE; }
FUNCTION { return TOKEN_KEYWORD_FUNCTION; }
X { return TOKEN_ALPHANUMERIC; }
S9 { return TOKEN_SIGNED_NUMERIC; }
9 { return TOKEN_NUMERIC; }
V9 { return TOKEN_IMPLIED_DECIMAL; }
COMP { return TOKEN_COMPUTATION_LEVEL_0; }
COMP-1 { return TOKEN_COMPUTATION_LEVEL_1; }
COMP-2 { return TOKEN_COMPUTATION_LEVEL_2; }
COMP-3 { return TOKEN_COMPUTATION_LEVEL_3; }
\+ { return TOKEN_ADD; }
\- { return TOKEN_SUB; }
\*\* { return TOKEN_EXPONENTIAL; }
\* { return TOKEN_MULTIPLY; }
\/ { return TOKEN_DIVIDE; }
\> { return TOKEN_GREATER_THAN; }
\< { return TOKEN_LESS_THAN; }
\= { return TOKEN_EQUAL;}
"\""[^"]*"\"" { return TOKEN_STRING; }
"\'"[^']*"\'" { return TOKEN_STRING; }
"(" { return TOKEN_LEFT_PARENTHESIS; }
")" { return TOKEN_RIGHT_PARENTHESIS; }
{NAME} { return TOKEN_IDENT; }
{DIGIT} { return TOKEN_INTEGER; }
\. { return TOKEN_DOT; }
%%
int yywrap() { return 1; }

View File

@ -1,56 +0,0 @@
typedef enum {
TOKEN_EOF = 0,
TOKEN_KEYWORD_IDENTIFICATION,
TOKEN_KEYWORD_DIVISION,
TOKEN_KEYWORD_DATA,
TOKEN_KEYWORD_SECTION,
TOKEN_PROGRAM_ID,
TOKEN_WORKING_STORAGE,
TOKEN_PROCEDURE,
TOKEN_DISPLAY,
TOKEN_STOP,
TOKEN_RUN,
TOKEN_MOVE,
TOKEN_KEYWORD_TO,
TOKEN_PERFORM,
TOKEN_VARYING,
TOKEN_KEYWORD_FROM,
TOKEN_KEYWORD_BY,
TOKEN_UNTIL,
TOKEN_END_PERFORM,
TOKEN_IF,
TOKEN_ELSE,
TOKEN_END_IF,
TOKEN_ELSE_IF,
TOKEN_SPACE,
TOKEN_KEYWORD_OCCURS,
TOKEN_KEYWORD_VALUE,
TOKEN_KEYWORD_COMPUTE,
TOKEN_KEYWORD_FUNCTION,
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,
TOKEN_COMPUTATION_LEVEL_3,
TOKEN_LEFT_PARENTHESIS,
TOKEN_RIGHT_PARENTHESIS,
TOKEN_DOT,
TOKEN_COMMENT,
TOKEN_ADD,
TOKEN_SUB,
TOKEN_MULTIPLY,
TOKEN_DIVIDE,
TOKEN_EQUAL,
TOKEN_GREATER_THAN,
TOKEN_LESS_THAN,
TOKEN_EXPONENTIAL,
} token_t;

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
# The top level rule indicates how to link everything together into main
main: main.o scanner.o parser.o
gcc main.o scanner.o parser.o -o parser.out -lm
test: main_test.o scanner.o parser.o
gcc main_test.o scanner.o parser.o -o parser_test.out -lm
# Only the files generated by flex and bison need explicit rules.
scanner.c: scanner.flex parser.h
flex -oscanner.c scanner.flex
parser.c parser.h: parser.bison
bison --defines=token.h --output=parser.c -v parser.bison
# This pattern indicates that any .o file depends
# upon the .c file of the same name, and all of the .h files.
# So, if a .o file is needed, it is built automatically.
%.o: %.c *.h
gcc -Wall -c $< -o $@
# clean causes all intermediate files to be deleted.
clean:
rm -f parser.c parser.output token.h scanner.c *.o parser.out parser_test.out

View File

@ -1,94 +0,0 @@
# Bison Parser With Tests
Create a scanner for your sample programs with tests.
The tests should include basic statements and the sample files for your language.
See the [example lab for Python](https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab-python).
## Build Process
To build the `scanner.c` run the following **flex** command.
```sh
flex -o scanner.c scanner.flex
```
The parser is built using **bison**.
Note this command also builds the `token.h`.
```sh
bison --defines=token.h --output=parser.c -v parser.bison
```
THe `-v` flag will create a `parser.output` which represents the grammar in text form.
### Running the Parser
Then build the `main.c`, `parcer.c` and `scanner.c` using **gcc**.
Note that you may get a few warnings that can be ignored.
```sh
gcc main.c scanner.c parser.c -o parser.out
```
Then execute the test suite using `./parser.out` and pass in the input from your sample program.
For example here is a command for `samples/program.c`
```sh
./parser.out < samples/program.c
```
### Testing the Parser
Then build the `main_test.c`, `parcer.c` and `scanner.c` using **gcc**.
Note that you may get a few warnings that can be ignored.
```sh
gcc main_test.c scanner.c parser.c -o parser_test.out
```
Then execute the test suite using `./parser_test.out`.
```sh
./parser_test.out
```
### Using Make
Alternatively you can use the supplied make file.
- Build main program - `make`
- Build test program - `make test`
- Clean up build files - `make clean`
## Tests
- Write test for various statements in your language
- assignment - Riley
- print - Josh (write test)
- mathmatical expressions - Jenessy
- boolean expressions - Jenessy
- branching - Josh
- looping - Riley
- Write a test for each sample test file.
- Hello World! - Josh (already done)
- Quadratic - Jenessy
- Sorting - Riley
## Grading Rubric
The grading will be over the following categories.
Points Description
---
60 points Ability to parse — Six different language statements
10 points Ability to parse — Hello world
10 points Ability to parse — Quadratic equation
10 points Ability to parse — Integer sorting
10 points Report formatting and readability
## Turn In
Please submit the URL of your gitlab project to D2L's Brightspace with your report.
On gitlab update the `lab-4` folder to have your report and code snippets before the due date.

View File

@ -1,11 +0,0 @@
#include <stdio.h>
extern int yyparse();
int main() {
if (yyparse() == 0) {
printf("Parse successful!\n");
} else {
printf("Parse failed.\n");
}
}

View File

@ -1,122 +0,0 @@
// https://github.com/sheredom/utest.h/blob/master/utest.h
#include "utest.h"
#include <stdio.h>
extern int yyparse();
typedef struct yy_buffer_state *YY_BUFFER_STATE;
extern int yyrestart();
extern YY_BUFFER_STATE yy_scan_buffer(char *str, int i);
extern YY_BUFFER_STATE yy_scan_string(char *str);
extern void yy_delete_buffer(YY_BUFFER_STATE buffer);
extern FILE *yyin;
extern int yylineno;
UTEST_MAIN();
UTEST(parser, math) {
// Must include the null character to terminate input
char string[] = "COMPUTE A = (b ** 2) - (4 * a * c)\0";
YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
yylineno = 1;
int result = yyparse();
yy_delete_buffer(buffer);
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}
UTEST(parser, hello) {
// Read sample file as input
yyin = fopen("samples/hello-world.cbl", "r");
yyrestart(yyin);
ASSERT_TRUE(yyin);
yylineno = 1;
int result = yyparse();
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}
UTEST(parser, print) {
// Must include the null character to terminate input
char string[] = "DISPLAY 'Hello World!'\0";
YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
yylineno = 1;
int result = yyparse();
yy_delete_buffer(buffer);
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}
UTEST(parser, branching) {
// Must include the null character to terminate input
char string[] = "IF A > B DISPLAY 'A is greater than B' ELSE DISPLAY 'B is greater than A'\0";
YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
yylineno = 1;
int result = yyparse();
yy_delete_buffer(buffer);
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}
UTEST(parser, looping) {
char string[] = "PERFORM VARYING I FROM 1 BY 1 UNTIL I > 10\0";
YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
yylineno = 1;
int result = yyparse();
yy_delete_buffer(buffer);
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}
UTEST(parser, assignment) {
char string[] = "MOVE I TO A(I) MOVE 1 TO I COMPUTE discriminant = (b ** 2) - (4 * a * c)\0";
YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
yylineno = 1;
int result = yyparse();
yy_delete_buffer(buffer);
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}
UTEST(parser, sorting) {
// Read sample file as input
yyin = fopen("samples/sorting-snippet.cbl", "r");
yyrestart(yyin);
ASSERT_TRUE(yyin);
yylineno = 1;
int result = yyparse();
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}
UTEST(parser, quadratic) {
// Read sample file as input
yyin = fopen("samples/quadratic-snippet.cbl", "r");
yyrestart(yyin);
ASSERT_TRUE(yyin);
yylineno = 1;
int result = yyparse();
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}

View File

@ -1,190 +0,0 @@
%{
#define YYDEBUG 1
#include <stdio.h>
extern int yylineno;
void yyerror(const char*);
int yylex();
%}
%debug
%define parse.error detailed
%token TOKEN_ADD
%token TOKEN_ALPHANUMERIC
%token TOKEN_COMPUTATION_LEVEL_0
%token TOKEN_COMPUTATION_LEVEL_1
%token TOKEN_COMPUTATION_LEVEL_2
%token TOKEN_COMPUTATION_LEVEL_3
%token TOKEN_DISPLAY
%token TOKEN_DIVIDE
%token TOKEN_DOT
%token TOKEN_ELSE
%token TOKEN_ELSE_IF
%token TOKEN_END_IF
%token TOKEN_END_PERFORM
%token TOKEN_EQUAL
%token TOKEN_EXPONENTIAL
%token TOKEN_GREATER_THAN
%token TOKEN_IDENT
%token TOKEN_IF
%token TOKEN_IMPLIED_DECIMAL
%token TOKEN_INTEGER
%token TOKEN_KEYWORD_BY
%token TOKEN_KEYWORD_COMPUTE
%token TOKEN_KEYWORD_DATA
%token TOKEN_KEYWORD_DIVISION
%token TOKEN_KEYWORD_FROM
%token TOKEN_KEYWORD_FUNCTION
%token TOKEN_KEYWORD_IDENTIFICATION
%token TOKEN_KEYWORD_OCCURS
%token TOKEN_KEYWORD_SECTION
%token TOKEN_KEYWORD_TO
%token TOKEN_KEYWORD_VALUE
%token TOKEN_LEFT_PARENTHESIS
%token TOKEN_LESS_THAN
%token TOKEN_MOVE
%token TOKEN_MULTIPLY
%token TOKEN_NUMERIC
%token TOKEN_PERFORM
%token TOKEN_PICTURE
%token TOKEN_PROGRAM_ID
%token TOKEN_PROCEDURE
%token TOKEN_RIGHT_PARENTHESIS
%token TOKEN_RUN
%token TOKEN_SIGNED_NUMERIC
%token TOKEN_SPACE
%token TOKEN_STOP
%token TOKEN_STRING
%token TOKEN_SUB
%token TOKEN_UNTIL
%token TOKEN_VARYING
%token TOKEN_WORKING_STORAGE
%token TOKEN_EOF
%%
file : statements
statements : statement_list
;
statement_list : statement_list statement
| statement
;
statement : section
| sect_data
| simple_stmt
| data_space
| data_declaration
;
section : type TOKEN_KEYWORD_DIVISION TOKEN_DOT
| type TOKEN_RUN TOKEN_DOT
;
sect_data : TOKEN_PROGRAM_ID TOKEN_DOT TOKEN_IDENT TOKEN_DOT
;
type : TOKEN_KEYWORD_IDENTIFICATION
| TOKEN_PROCEDURE
| TOKEN_STOP
| TOKEN_KEYWORD_DATA
;
simple_stmt : cbl_func_stmt
| if_branch
| else_parts
| perform_stmt
;
cbl_func_stmt : cbl_function
| cbl_function op_parms
| cbl_function assignment_stmt
| cbl_function op_parm assignment_stmt
;
assignment_stmt : TOKEN_EQUAL op_parms
| TOKEN_KEYWORD_TO op_parms
;
op_parms : op_parm
| op_parms op_parm
;
op_parm : mathmaticalexpr
| booleanexpr
;
term : mathmaticalexpr
;
math_op : TOKEN_ADD
| TOKEN_SUB
| TOKEN_MULTIPLY
| TOKEN_DIVIDE
| TOKEN_EXPONENTIAL
;
mathmaticalexpr : type_expr
| mathmaticalexpr math_op term
| container_expr
| type_expr container_expr
;
container_expr : TOKEN_LEFT_PARENTHESIS mathmaticalexpr TOKEN_RIGHT_PARENTHESIS
;
booleanexpr : mathmaticalexpr TOKEN_LESS_THAN term
| mathmaticalexpr TOKEN_GREATER_THAN term
| mathmaticalexpr TOKEN_EQUAL term
;
type_expr : TOKEN_IDENT
| TOKEN_INTEGER
| TOKEN_STRING
| TOKEN_SPACE
| TOKEN_SUB TOKEN_IDENT
| ext_function
;
ext_function : TOKEN_KEYWORD_FUNCTION TOKEN_IDENT TOKEN_LEFT_PARENTHESIS TOKEN_IDENT TOKEN_RIGHT_PARENTHESIS
;
cbl_function : TOKEN_DISPLAY
| TOKEN_MOVE
| TOKEN_KEYWORD_COMPUTE
;
if_branch : TOKEN_IF booleanexpr
;
else_parts : TOKEN_ELSE_IF booleanexpr simple_stmt
| TOKEN_ELSE simple_stmt
| TOKEN_END_IF
;
perform_stmt : TOKEN_PERFORM TOKEN_VARYING TOKEN_IDENT TOKEN_KEYWORD_FROM TOKEN_INTEGER TOKEN_KEYWORD_BY TOKEN_INTEGER TOKEN_UNTIL op_parms
| TOKEN_END_PERFORM
;
data_space : TOKEN_WORKING_STORAGE TOKEN_KEYWORD_SECTION TOKEN_DOT
;
data_category : TOKEN_ALPHANUMERIC
| TOKEN_NUMERIC
| TOKEN_SIGNED_NUMERIC
| TOKEN_IMPLIED_DECIMAL
;
categry_contain : TOKEN_LEFT_PARENTHESIS TOKEN_INTEGER TOKEN_RIGHT_PARENTHESIS
| TOKEN_LEFT_PARENTHESIS TOKEN_IDENT TOKEN_RIGHT_PARENTHESIS
;
complete_category: data_category categry_contain
| data_category categry_contain complete_category
;
data_clause : TOKEN_COMPUTATION_LEVEL_0
| TOKEN_COMPUTATION_LEVEL_1
| TOKEN_COMPUTATION_LEVEL_2
| TOKEN_COMPUTATION_LEVEL_3
| TOKEN_KEYWORD_VALUE
| TOKEN_KEYWORD_OCCURS
;
full_data_clause: data_clause data_clause
| data_clause
;
simple_decl : TOKEN_INTEGER TOKEN_IDENT TOKEN_DOT
;
complex_decl : TOKEN_INTEGER TOKEN_IDENT TOKEN_PICTURE category_spec TOKEN_DOT
;
category_spec : complete_category
| complete_category data_clauses
;
data_clauses : full_data_clause
| full_data_clause TOKEN_INTEGER
;
data_declaration: simple_decl
| complex_decl
;
%%
void yyerror(const char* msg) {
fprintf(stderr, "Error | Line: %d\n%s\n",yylineno,msg);
}

View File

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

View File

@ -1,33 +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,54 +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-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.

View File

@ -1,64 +0,0 @@
%{
#include "token.h"
%}
NAME [a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?
DIGIT [0-9]+
%%
(" "|\t|\n) /* skip whitespace */
\*>\ ?.*
IDENTIFICATION { return TOKEN_KEYWORD_IDENTIFICATION; }
DIVISION { return TOKEN_KEYWORD_DIVISION; }
PROGRAM-ID { return TOKEN_PROGRAM_ID; }
PROCEDURE { return TOKEN_PROCEDURE; }
DATA { return TOKEN_KEYWORD_DATA; }
SECTION { return TOKEN_KEYWORD_SECTION; }
WORKING-STORAGE { return TOKEN_WORKING_STORAGE; }
DISPLAY { return TOKEN_DISPLAY; }
STOP { return TOKEN_STOP; }
RUN { return TOKEN_RUN; }
MOVE { return TOKEN_MOVE; }
TO { return TOKEN_KEYWORD_TO; }
VARYING { return TOKEN_VARYING; }
FROM { return TOKEN_KEYWORD_FROM; }
BY { return TOKEN_KEYWORD_BY; }
UNTIL { return TOKEN_UNTIL; }
PERFORM { return TOKEN_PERFORM; }
END-PERFORM { return TOKEN_END_PERFORM; }
IF { return TOKEN_IF; }
END-IF { return TOKEN_END_IF; }
SPACE { return TOKEN_SPACE; }
PIC { return TOKEN_PICTURE; }
OCCURS { return TOKEN_KEYWORD_OCCURS; }
VALUE { return TOKEN_KEYWORD_VALUE; }
COMPUTE { return TOKEN_KEYWORD_COMPUTE; }
FUNCTION { return TOKEN_KEYWORD_FUNCTION; }
X { return TOKEN_ALPHANUMERIC; }
S9 { return TOKEN_SIGNED_NUMERIC; }
9 { return TOKEN_NUMERIC; }
V9 { return TOKEN_IMPLIED_DECIMAL; }
COMP { return TOKEN_COMPUTATION_LEVEL_0; }
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; }
\- { return TOKEN_SUB; }
\*\* { return TOKEN_EXPONENTIAL; }
\* { return TOKEN_MULTIPLY; }
\/ { return TOKEN_DIVIDE; }
\> { return TOKEN_GREATER_THAN; }
\< { return TOKEN_LESS_THAN; }
\= { return TOKEN_EQUAL;}
"\""[^"]*"\"" { return TOKEN_STRING; }
"\'"[^']*"\'" { return TOKEN_STRING; }
"(" { return TOKEN_LEFT_PARENTHESIS; }
")" { return TOKEN_RIGHT_PARENTHESIS; }
\. { return TOKEN_DOT; }
%%
int yywrap() { return 1; }

File diff suppressed because it is too large Load Diff

View File

@ -1,107 +0,0 @@
# Bison Interpreter
Create an interpreter for your sample programs.
See the [example lab for Python](https://gitlab.cs.wallawalla.edu/cptr354/language-interpreter-lab-python).
In this lab, you will focus on basic operations that support your sample code.
* 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.
To build the `scanner.c` run the following **flex** command.
```sh
flex -o scanner.c scanner.flex
```
The parser is built using **bison**.
Note this command also builds the `token.h`.
```sh
bison --defines=token.h --output=parser.c parser.bison
```
Then build the `main.c`, `expr.c`, `parcer.c` and `scanner.c` using **gcc**.
Note that you may get a few warnings that can be ignored.
```sh
gcc *.c -o interpreter.out
```
Then execute the test suite using `./interpreter.out` and pass in the input from your sample program.
For example here is a command for `samples/program.c`
```sh
./interpreter.out < samples/program.c
```
Single line command:
```sh
flex -o scanner.c scanner.flex && \
bison --defines=token.h --output=parser.c parser.bison && \
gcc *.c -o interpreter.out && ./interpreter.out < samples/program.c
```
## Building with Make
To simplify the process a Makefile has been supplied.
```sh
make && ./interpreter.out < samples/program.c
```
To remove the build files, use make clean.
```sh
make clean
```
## Assignment Steps
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. 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
----------- ------------------------------------
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
Please submit the URL of your GitLab project to D2L's Brightspace with your report.
On GitLab update the `lab-5` folder to have your report and code snippets before the due date.

View File

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

View File

@ -1,24 +0,0 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. variables.
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.
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.
DISPLAY 'Hello World!'
STOP RUN.

View File

@ -31,7 +31,7 @@ UTEST(scanner, hello) {
{TOKEN_KEYWORD_DIVISION, "DIVISION"},
{TOKEN_DOT, "."},
{TOKEN_DISPLAY, "DISPLAY"},
{TOKEN_STRING, "'Hello World!'"},
{TOKEN_STRING, "Hello World!"},
{TOKEN_STOP, "STOP"},
{TOKEN_RUN, "RUN"},
{TOKEN_DOT, "."},