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.
|
## Overview
|
||||||
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.
|
|
||||||
|
|
||||||
## 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>.
|
This is the resulting project.
|
||||||
Copy the URL of your forked repository by clicking the clipboard icon next to it.
|
|
||||||
The URL should look something like:
|
|
||||||
|
|
||||||
```shell
|
> This interpreter is based on the work of Douglas Thain who created the [Compiler Book](https://www3.nd.edu/~dthain/compilerbook/)
|
||||||
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>
|
|
||||||
|
|
|
||||||
|
|
@ -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_KEYWORD_DIVISION, "DIVISION"},
|
||||||
{TOKEN_DOT, "."},
|
{TOKEN_DOT, "."},
|
||||||
{TOKEN_DISPLAY, "DISPLAY"},
|
{TOKEN_DISPLAY, "DISPLAY"},
|
||||||
{TOKEN_STRING, "'Hello World!'"},
|
{TOKEN_STRING, "Hello World!"},
|
||||||
{TOKEN_STOP, "STOP"},
|
{TOKEN_STOP, "STOP"},
|
||||||
{TOKEN_RUN, "RUN"},
|
{TOKEN_RUN, "RUN"},
|
||||||
{TOKEN_DOT, "."},
|
{TOKEN_DOT, "."},
|
||||||
Loading…
Reference in New Issue