Merge branch 'main' of gitlab.cs.wallawalla.edu:cptr354/student354
This commit is contained in:
commit
d20a11d829
|
|
@ -1,3 +1,4 @@
|
|||
---
|
||||
lab_3_tests:
|
||||
stage: test
|
||||
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
|
||||
- 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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern int yyparse();
|
||||
|
||||
int main() {
|
||||
if (yyparse() == 0) {
|
||||
printf("Parse successful!\n");
|
||||
} else {
|
||||
printf("Parse failed.\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
2020+4;
|
||||
|
|
@ -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; }
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue