Lab 3
This commit is contained in:
parent
303e16b851
commit
47d1e653ed
|
|
@ -1 +1,14 @@
|
||||||
---
|
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
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
# 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.
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#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/hello.py"; // Default filename
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
#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, identifier) {
|
||||||
|
token_t t;
|
||||||
|
// Must include the null character to terminate input
|
||||||
|
char string[] = "test\0";
|
||||||
|
YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
|
||||||
|
|
||||||
|
ASSERT_EQ(TOKEN_IDENT, (t = yylex()));
|
||||||
|
ASSERT_STREQ("test", yytext);
|
||||||
|
|
||||||
|
ASSERT_EQ(TOKEN_EOF, (t = yylex()));
|
||||||
|
ASSERT_STREQ("", yytext);
|
||||||
|
|
||||||
|
yy_delete_buffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
UTEST(scanner, assignment) {
|
||||||
|
token_t t;
|
||||||
|
// Must include the null character to terminate input
|
||||||
|
char string[] = "=\0";
|
||||||
|
YY_BUFFER_STATE buffer = yy_scan_buffer(string, sizeof(string));
|
||||||
|
|
||||||
|
ASSERT_EQ(TOKEN_ASSIGNMENT, (t = yylex()));
|
||||||
|
ASSERT_STREQ("=", yytext);
|
||||||
|
|
||||||
|
ASSERT_EQ(TOKEN_EOF, (t = yylex()));
|
||||||
|
ASSERT_STREQ("", yytext);
|
||||||
|
|
||||||
|
yy_delete_buffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
UTEST(scanner, sample) {
|
||||||
|
struct token_st tokens[] = {
|
||||||
|
{TOKEN_IDENT, "answer"},
|
||||||
|
{TOKEN_ASSIGNMENT, "="},
|
||||||
|
{TOKEN_NUMBER, "2020"},
|
||||||
|
{TOKEN_ADD, "+"},
|
||||||
|
{TOKEN_NUMBER, "4"},
|
||||||
|
{TOKEN_EOF, ""}
|
||||||
|
};
|
||||||
|
|
||||||
|
yyin = fopen("samples/program.c", "r");
|
||||||
|
yyrestart(yyin);
|
||||||
|
ASSERT_TRUE(yyin);
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
token_t t;
|
||||||
|
do {
|
||||||
|
ASSERT_EQ(tokens[index].t, (t = yylex()));
|
||||||
|
ASSERT_STREQ(tokens[index].p, yytext);
|
||||||
|
++index;
|
||||||
|
} while (t != TOKEN_EOF);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
answer = 2020+4
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
%{
|
||||||
|
#include "token.h"
|
||||||
|
%}
|
||||||
|
DIGIT [0-9]
|
||||||
|
LETTER [a-zA-Z]
|
||||||
|
%%
|
||||||
|
(" "|\t|\n) /* skip whitespace */
|
||||||
|
\+ { return TOKEN_ADD; }
|
||||||
|
"=" { return TOKEN_ASSIGNMENT; }
|
||||||
|
while { return TOKEN_WHILE; }
|
||||||
|
{LETTER}+ { return TOKEN_IDENT; }
|
||||||
|
{DIGIT}+ { return TOKEN_NUMBER; }
|
||||||
|
. { return TOKEN_ERROR; }
|
||||||
|
%%
|
||||||
|
int yywrap() { return 1; }
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
typedef enum {
|
||||||
|
TOKEN_EOF = 0,
|
||||||
|
TOKEN_WHILE,
|
||||||
|
TOKEN_ADD,
|
||||||
|
TOKEN_ASSIGNMENT,
|
||||||
|
TOKEN_IDENT,
|
||||||
|
TOKEN_NUMBER,
|
||||||
|
TOKEN_ERROR
|
||||||
|
} token_t;
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue