update lab-5 to use the correct files

This commit is contained in:
vel 2024-11-10 17:11:28 -08:00
parent ff8119ee56
commit 282aeafa54
Signed by: velvox
GPG Key ID: 59D9762F674151DF
21 changed files with 336 additions and 254 deletions

View File

@ -1,189 +1,172 @@
/*
Declare token types at the top of the bison file,
causing them to be automatically generated in parser.tab.h
for use by scanner.c.
*/
%{
#define YYDEBUG 1
#include <stdio.h>
extern int yylineno;
void yyerror(const char*);
int yylex();
%}
%debug
%define parse.error detailed
%token TOKEN_ASSIGNMENT
%token TOKEN_COMMA
%token TOKEN_DIV
%token TOKEN_EQUAL_EQUAL
%token TOKEN_GREATER_THAN
%token TOKEN_GREATER_THAN_OR_EQUAL
%token TOKEN_ID
%token TOKEN_INT
%token TOKEN_EOF
%token TOKEN_KEYWORD_IDENTIFICATION
%token TOKEN_KEYWORD_DIVISION
%token TOKEN_KEYWORD_DATA
%token TOKEN_KEYWORD_SECTION
%token TOKEN_PROGRAM_ID
%token TOKEN_WORKING_STORAGE
%token TOKEN_PROCEDURE
%token TOKEN_STOP
%token TOKEN_RUN
%token TOKEN_MOVE
%token TOKEN_KEYWORD_TO
%token TOKEN_PERFORM
%token TOKEN_VARYING
%token TOKEN_KEYWORD_FROM
%token TOKEN_KEYWORD_BY
%token TOKEN_UNTIL
%token TOKEN_END_PERFORM
%token TOKEN_IF
%token TOKEN_ELSE_IF
%token TOKEN_ELSE
%token TOKEN_END_IF
%token TOKEN_SPACE
%token TOKEN_KEYWORD_OCCURS
%token TOKEN_KEYWORD_VALUE
%token TOKEN_KEYWORD_COMPUTE
%token TOKEN_KEYWORD_FUNCTION
%token TOKEN_IDENT
%token TOKEN_STRING
%token TOKEN_INTEGER
%token TOKEN_KEYWORD_ENDIF
%token TOKEN_KEYWORD_IF
%token TOKEN_KEYWORD_PRINT
%token TOKEN_KEYWORD_THEN
%token TOKEN_LBRACKET
%token TOKEN_PICTURE
%token TOKEN_ALPHANUMERIC
%token TOKEN_NUMERIC
%token TOKEN_SIGNED_NUMERIC
%token TOKEN_IMPLIED_DECIMAL
%token TOKEN_COMPUTATION_LEVEL_0
%token TOKEN_COMPUTATION_LEVEL_1
%token TOKEN_COMPUTATION_LEVEL_2
%token TOKEN_COMPUTATION_LEVEL_3
%token TOKEN_LEFT_PARENTHESIS
%token TOKEN_RIGHT_PARENTHESIS
%token TOKEN_DOT
%token TOKEN_COMMENT
%token TOKEN_ADD
%token TOKEN_SUB
%token TOKEN_MULTIPLY
%token TOKEN_DIVIDE
%token TOKEN_EQUAL
%token TOKEN_GREATER_THAN
%token TOKEN_LESS_THAN
%token TOKEN_LESS_THAN_OR_EQUAL
%token TOKEN_LPAREN
%token TOKEN_MINUS
%token TOKEN_MUL
%token TOKEN_NOT_EQUAL
%token TOKEN_PLUS
%token TOKEN_RBRACKET
%token TOKEN_RPAREN
%token TOKEN_SEMI
%token TOKEN_EXPONENTIAL
%token TOKEN_DISPLAY
%union {
struct stmt *stmt;
struct expr *expr;
struct decl *decl;
};
%type <stmt> program statement_list statement print_statement assignment_statement if_statement block
%type <expr> expr term factor name sum array_subscript star_expr
%type <decl> declaration
%{
#define YYDEBUG 1
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "expr.h"
/*
Clunky: Manually declare the interface to the scanner generated by flex.
*/
extern int yylineno;
extern char *yytext;
extern int yylex();
extern void yyerror(const char*);
/*
Clunky: Keep the final result of the parse in a global variable,
so that it can be retrieved by main().
*/
struct stmt * parser_result = 0;
%}
%%
file : statements
statements : statements 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_function
| cbl_function op_parms
| cbl_function assignment_stmt
| cbl_function op_parms assignment_stmt
| if_branch
| perform_stmt
;
;
assignment_stmt : TOKEN_EQUAL ext_function
| TOKEN_EQUAL function
| TOKEN_KEYWORD_TO op_parms
;
op_parms : op_parms TOKEN_ADD op_parms
| op_parms TOKEN_SUB op_parms
| op_parms TOKEN_MULTIPLY op_parms
| op_parms TOKEN_DIVIDE op_parms
| op_parms TOKEN_EXPONENTIAL op_parms
| op_parms TOKEN_LESS_THAN op_parms
| op_parms TOKEN_GREATER_THAN op_parms
| op_parms TOKEN_EQUAL op_parms
| TOKEN_SUB op_parms
| TOKEN_LEFT_PARENTHESIS op_parms TOKEN_RIGHT_PARENTHESIS
| TOKEN_IDENT
| TOKEN_INTEGER
| TOKEN_STRING
| TOKEN_SPACE
| op_parms op_parms
;
function : op_parms
;
ext_function : TOKEN_KEYWORD_FUNCTION TOKEN_IDENT TOKEN_LEFT_PARENTHESIS TOKEN_IDENT TOKEN_RIGHT_PARENTHESIS
;
cbl_function : TOKEN_DISPLAY
| TOKEN_MOVE
| TOKEN_KEYWORD_COMPUTE
| TOKEN_PERFORM
;
if_branch : TOKEN_IF op_parms
| TOKEN_ELSE_IF op_parms
| TOKEN_ELSE statement
| 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: complete_category complete_category
| data_category categry_contain
;
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
;
full_decl : TOKEN_INTEGER TOKEN_IDENT TOKEN_PICTURE complete_category TOKEN_DOT
| TOKEN_INTEGER TOKEN_IDENT TOKEN_PICTURE complete_category full_data_clause TOKEN_DOT
| TOKEN_INTEGER TOKEN_IDENT TOKEN_PICTURE complete_category full_data_clause TOKEN_INTEGER TOKEN_DOT
;
data_declaration: simple_decl
| full_decl
;
/* Here is the grammar: program is the start symbol. */
program : statement_list
{ parser_result = $1; return 0; }
;
statement_list : statement
{ $$ = $1; }
| statement statement_list
{ $$ = $1; $1->next = $2; }
;
block : statement
{ $$ = $1; }
| statement block
{ $$ = $1; $1->next = $2; }
;
statement : assignment_statement TOKEN_SEMI
{ $$ = $1; }
| print_statement TOKEN_SEMI
{ $$ = $1; }
| if_statement
{ $$ = $1; }
;
assignment_statement : declaration
{ $$ = stmt_create(STMT_DECL,$1,0,0,0,0,0,0); }
;
print_statement : TOKEN_KEYWORD_PRINT expr
{ $$ = stmt_create(STMT_PRINT,0,0,$2,0,0,0,0); }
;
if_statement : TOKEN_KEYWORD_IF expr TOKEN_KEYWORD_THEN block TOKEN_KEYWORD_ENDIF
{ $$ = stmt_create(STMT_IF,0,0,$2,0,$4,0,0); }
;
declaration : name TOKEN_ASSIGNMENT expr
{ $$ = decl_create($1,0,$3,0,0); }
| array_subscript TOKEN_ASSIGNMENT expr
{ $$ = decl_create($1,0,$3,0,0); }
;
name : TOKEN_ID
{ $$ = expr_create_name(yytext); }
;
array_subscript : name TOKEN_LBRACKET expr TOKEN_RBRACKET
{ $$ = expr_create(EXPR_SUBSCRIPT,$1,$3); }
;
star_expr : expr
{ $$ = expr_create(EXPR_ARRAY,$1,0); }
| expr TOKEN_COMMA star_expr
{ $$ = expr_create(EXPR_ARRAY,$1,$3); }
;
expr : sum TOKEN_LESS_THAN sum
{ $$ = expr_create(EXPR_LESS_THAN,$1,$3); }
| sum TOKEN_LESS_THAN_OR_EQUAL sum
{ $$ = expr_create(EXPR_LESS_THAN_OR_EQUAL,$1,$3); }
| sum TOKEN_GREATER_THAN sum
{ $$ = expr_create(EXPR_GREATER_THAN,$1,$3); }
| sum TOKEN_GREATER_THAN_OR_EQUAL sum
{ $$ = expr_create(EXPR_GREATER_THAN_OR_EQUAL,$1,$3); }
| sum TOKEN_EQUAL_EQUAL sum
{ $$ = expr_create(EXPR_EQUAL_EQUAL,$1,$3); }
| sum TOKEN_NOT_EQUAL sum
{ $$ = expr_create(EXPR_NOT_EQUAL,$1,$3); }
| sum
{ $$ = $1; }
;
sum : sum TOKEN_PLUS term
{ $$ = expr_create(EXPR_ADD,$1,$3); }
| sum TOKEN_MINUS term
{ $$ = expr_create(EXPR_SUBTRACT,$1,$3); }
| term
{ $$ = $1; }
;
term : term TOKEN_MUL factor
{ $$ = expr_create(EXPR_MULTIPLY,$1,$3); }
| term TOKEN_DIV factor
{ $$ = expr_create(EXPR_DIVIDE,$1,$3); }
| factor
{ $$ = $1; }
;
factor : TOKEN_LPAREN expr TOKEN_RPAREN
{ $$ = $2; }
| TOKEN_MINUS factor
{ $$ = expr_create(EXPR_SUBTRACT,expr_create_integer_literal(0),$2); }
| TOKEN_INT
{ $$ = expr_create_integer_literal(atoi(yytext)); }
| TOKEN_LBRACKET star_expr TOKEN_RBRACKET
{ $$ = $2; }
| array_subscript
{ $$ = $1; }
| name
{ $$ = $1; }
;
%%
/*
This function will be called by bison if the parse should
encounter an error. In principle, "str" will contain something
useful. In practice, it often does not.
*/
void yyerror(const char* msg) {
fprintf(stderr, "Error | Line: %d\n%s\n", yylineno, msg);
fprintf(stderr, "Error | Line: %d\n%s\n",yylineno,msg);
}

View File

@ -1 +0,0 @@
a = [ 4, 8, 12 ];

View File

@ -1,2 +0,0 @@
a = [ 3, 5 ];
print a[0];

View File

@ -1,4 +0,0 @@
a = [ 3, 5, 7, 9, 11];
print a[1];
a[1] = 6;
print a[1];

View File

@ -1 +0,0 @@
a = 5;

View File

@ -0,0 +1,5 @@
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-WORLD.
PROCEDURE DIVISION.
DISPLAY 'Hello World!'
STOP RUN.

View File

@ -1,2 +0,0 @@
print 5;
print 6;

View File

@ -1 +0,0 @@
56

View File

@ -1,2 +0,0 @@
print 5;
print 6;

View File

@ -0,0 +1,24 @@
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.

View File

@ -1,6 +0,0 @@
if 3==3 then
print 3;
endif
if 3==4 then
print 4;
endif

View File

@ -1,5 +0,0 @@
if 0 then
print 5;
print 3;
print 1;
endif

View File

@ -1,5 +0,0 @@
if 1 then
print 5;
print 3;
print 1;
endif

View File

@ -1 +0,0 @@
print 5;

View File

@ -1,2 +0,0 @@
a = 4 + 4;
print a;

View File

@ -1,2 +0,0 @@
a=(101*20)+4;
print(a);

View File

@ -1 +0,0 @@
2024

View File

@ -1,2 +0,0 @@
a = ((101*20)+4);
print(a);

View File

@ -0,0 +1,35 @@
*> 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.

View File

@ -0,0 +1,55 @@
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.

View File

@ -1,47 +1,64 @@
%{
#include "parser.h"
#include "token.h"
%}
%option nounput
%option noinput
%option noyywrap
%option yylineno
DIGIT [0-9]
LETTER [a-zA-Z_]
NAME [a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])?
DIGIT [0-9]+
%%
[ \n\r\t]* /* skip whitespace */;
"print" return TOKEN_KEYWORD_PRINT;
"if" return TOKEN_KEYWORD_IF;
"then" return TOKEN_KEYWORD_THEN;
"endif" return TOKEN_KEYWORD_ENDIF;
{DIGIT}+ return TOKEN_INT;
{LETTER}+ return TOKEN_ID;
"," return TOKEN_COMMA;
"]" return TOKEN_RBRACKET;
"[" return TOKEN_LBRACKET;
"==" return TOKEN_EQUAL_EQUAL;
"!=" return TOKEN_NOT_EQUAL;
"<=" return TOKEN_LESS_THAN_OR_EQUAL;
">=" return TOKEN_GREATER_THAN_OR_EQUAL;
"<" return TOKEN_LESS_THAN;
">" return TOKEN_GREATER_THAN;
\= return TOKEN_ASSIGNMENT;
\* return TOKEN_MUL;
\+ return TOKEN_PLUS;
\- return TOKEN_MINUS;
\/ return TOKEN_DIV;
\( return TOKEN_LPAREN;
\) return TOKEN_RPAREN;
\; return TOKEN_SEMI;
. { printf("scan error: bad token: %c\n", yytext[0]); }
%%
(" "|\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; }
/*
flex calls yywrap() whenever it reaches the end of the current file.
If yywrap returns false to indicate the end of the program.
It could alternatively open up another file and return true,
so that flex would keep going.
*/
{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; }