Merge branch 'main' of gitlab.cs.wallawalla.edu:cptr354/student354

This commit is contained in:
Jenessy Lustre 2024-10-24 11:10:17 -07:00
commit 31acd919e7
9 changed files with 1944 additions and 0 deletions

View File

@ -1,3 +1,4 @@
---
lab_3_tests: lab_3_tests:
stage: test stage: test
image: gitlab.cs.wallawalla.edu:5050/cs_department/docker-images/cpp image: gitlab.cs.wallawalla.edu:5050/cs_department/docker-images/cpp
@ -12,3 +13,15 @@ lab_3_tests:
- gcc main_test.c scanner.c -o scanner_test.out - gcc main_test.c scanner.c -o scanner_test.out
- echo "Lab 3 - Run Tests" - echo "Lab 3 - Run Tests"
- ./scanner_test.out - ./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

29
lab-4/Makefile Normal file
View File

@ -0,0 +1,29 @@
# 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

98
lab-4/README.md Normal file
View File

@ -0,0 +1,98 @@
# 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
* print
* mathmatical expressions
* boolean expressions
* branching
* looping
* Write a test for each sample test file.
* Hello World!
* Quadratic
* Sorting
## 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 Normal file
View File

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

57
lab-4/main_test.c Normal file
View File

@ -0,0 +1,57 @@
// 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[] = "1+8/4-3;\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, missing_semi_colon) {
// Must include the null character to terminate input
char string[] = "1+8/4-3\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, 1);
}
UTEST(parser, sample) {
// Read sample file as input
yyin = fopen("samples/program.c", "r");
yyrestart(yyin);
ASSERT_TRUE(yyin);
yylineno = 1;
int result = yyparse();
// Assert the result to test correctness
ASSERT_EQ(result, 0);
}

42
lab-4/parser.bison Normal file
View File

@ -0,0 +1,42 @@
%{
#define YYDEBUG 1
#include <stdio.h>
extern int yylineno;
void yyerror(const char*);
int yylex();
%}
%debug
%define parse.error detailed
%token TOKEN_INT
%token TOKEN_PLUS
%token TOKEN_MINUS
%token TOKEN_MUL
%token TOKEN_DIV
%token TOKEN_LPAREN
%token TOKEN_RPAREN
%token TOKEN_SEMI
%token TOKEN_ERROR
%%
program : expr TOKEN_SEMI;
expr : expr TOKEN_PLUS term
| expr TOKEN_MINUS term
| term
;
term : term TOKEN_MUL factor
| term TOKEN_DIV factor
| factor
;
factor: TOKEN_MINUS factor
| TOKEN_LPAREN expr TOKEN_RPAREN
| TOKEN_INT
;
%%
void yyerror(const char* msg) {
fprintf(stderr, "Error | Line: %d\n%s\n",yylineno,msg);
}

1
lab-4/samples/program.c Normal file
View File

@ -0,0 +1 @@
2020+4;

25
lab-4/scanner.flex Normal file
View File

@ -0,0 +1,25 @@
%{
#include "token.h"
%}
%option nounput
%option noinput
%option yylineno
DIGIT [0-9]
LETTER [a-zA-Z]
%%
(" "|\t|\n) /* skip whitespace */
\+ { return TOKEN_PLUS; }
\- { return TOKEN_MINUS; }
\* { return TOKEN_MUL; }
\/ { return TOKEN_DIV; }
\( { return TOKEN_LPAREN; }
\) { return TOKEN_RPAREN; }
\; { return TOKEN_SEMI; }
{DIGIT}+ { return TOKEN_INT; }
. { return TOKEN_ERROR; }
%%
int yywrap() { return 1; }

1668
lab-4/utest.h Normal file

File diff suppressed because it is too large Load Diff