clean up codebase, add github action to run test
This commit is contained in:
parent
f53cd91890
commit
141b10c9c9
|
|
@ -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
|
||||
|
|
@ -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
|
||||
73
README.md
73
README.md
|
|
@ -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/)
|
||||
|
|
|
|||
|
|
@ -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/)
|
||||
|
|
@ -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.
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
IDENTIFICATION DIVISION.
|
||||
PROGRAM-ID. HELLO-WORLD.
|
||||
PROCEDURE DIVISION.
|
||||
DISPLAY "Hello World!"
|
||||
STOP RUN.
|
||||
if
|
||||
|
|
@ -1 +0,0 @@
|
|||
2+3
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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.
|
||||
30
lab-3/main.c
30
lab-3/main.c
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
||||
BIN
lab-3/scanner
BIN
lab-3/scanner
Binary file not shown.
|
|
@ -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; }
|
||||
|
|
@ -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;
|
||||
1668
lab-3/utest.h
1668
lab-3/utest.h
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
||||
|
|
@ -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.
|
||||
11
lab-4/main.c
11
lab-4/main.c
|
|
@ -1,11 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern int yyparse();
|
||||
|
||||
int main() {
|
||||
if (yyparse() == 0) {
|
||||
printf("Parse successful!\n");
|
||||
} else {
|
||||
printf("Parse failed.\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
IDENTIFICATION DIVISION.
|
||||
PROGRAM-ID. HELLO-WORLD.
|
||||
PROCEDURE DIVISION.
|
||||
DISPLAY 'Hello World!'
|
||||
STOP RUN.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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; }
|
||||
1668
lab-4/utest.h
1668
lab-4/utest.h
File diff suppressed because it is too large
Load Diff
107
lab-5/README.md
107
lab-5/README.md
|
|
@ -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.
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
IDENTIFICATION DIVISION.
|
||||
PROGRAM-ID. HELLO-WORLD.
|
||||
PROCEDURE DIVISION.
|
||||
DISPLAY 'Hello World!'
|
||||
STOP RUN.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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, "."},
|
||||
Loading…
Reference in New Issue