diff --git a/lab-3/main.c b/lab-3/main.c index 1187003..7e4a834 100644 --- a/lab-3/main.c +++ b/lab-3/main.c @@ -8,7 +8,7 @@ extern char *yytext; int main(int argc, char *argv[]) { FILE *file; - const char *filename = "samples/quadratic_snippet.cbl"; // Default filename + const char *filename = "samples/quadratic-snippet.cbl"; // Check if a filename is provided as a command-line argument if (argc > 1) { diff --git a/lab-3/main_test.c b/lab-3/main_test.c index 1eb729a..1dd60bd 100644 --- a/lab-3/main_test.c +++ b/lab-3/main_test.c @@ -20,7 +20,7 @@ struct token_st { UTEST(scanner, hello) { struct token_st tokens[] = { - {TOKEN_IDENTIFICATION, "IDENTIFICATION"}, + {TOKEN_KEYWORD_IDENTIFICATION, "IDENTIFICATION"}, {TOKEN_KEYWORD_DIVISION, "DIVISION"}, {TOKEN_DOT, "."}, {TOKEN_PROGRAM_ID, "PROGRAM-ID"}, @@ -56,7 +56,7 @@ UTEST(scanner, quadratic) { {TOKEN_COMMENT, "*> Code altered from https://www.quora.com/What-is-a-COBOL-program-that-will-solve-a-quadratic-equation"}, {TOKEN_COMMENT, "*> Program finds the roots to a simple quadratic equation"}, - {TOKEN_IDENTIFICATION, "IDENTIFICATION"}, + {TOKEN_KEYWORD_IDENTIFICATION, "IDENTIFICATION"}, {TOKEN_KEYWORD_DIVISION, "DIVISION"}, {TOKEN_DOT, "."}, {TOKEN_PROGRAM_ID, "PROGRAM-ID"}, @@ -316,7 +316,7 @@ UTEST(scanner, quadratic) { UTEST(scanner, sorting) { struct token_st tokens[] = { - {TOKEN_IDENTIFICATION, "IDENTIFICATION"}, + {TOKEN_KEYWORD_IDENTIFICATION, "IDENTIFICATION"}, {TOKEN_KEYWORD_DIVISION, "DIVISION"}, {TOKEN_DOT, "."}, {TOKEN_PROGRAM_ID, "PROGRAM-ID"}, diff --git a/lab-3/samples/quadratic-snippet.cbl b/lab-3/samples/quadratic-snippet.cbl index 18ba158..00eb26f 100644 --- a/lab-3/samples/quadratic-snippet.cbl +++ b/lab-3/samples/quadratic-snippet.cbl @@ -14,22 +14,21 @@ 77 square-root-discriminant PIC S9(5)V9(5) COMP-3. PROCEDURE DIVISION. *> program begins here - DISPLAY 'EQUATION: (1x^2) + 5x + 6 = 0' + 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 - + 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 + DISPLAY "The equation has one real root: " + DISPLAY "Root: " root1 ELSE - DISPLAY 'The equation has no real roots.' - + DISPLAY "The equation has no real roots." + END-IF STOP RUN. diff --git a/lab-3/scanner b/lab-3/scanner new file mode 100755 index 0000000..896da2e Binary files /dev/null and b/lab-3/scanner differ diff --git a/lab-3/scanner.flex b/lab-3/scanner.flex index cc22816..4b7a148 100644 --- a/lab-3/scanner.flex +++ b/lab-3/scanner.flex @@ -6,8 +6,8 @@ DIGIT [0-9]+ %% (" "|\t|\n) /* skip whitespace */ -\*>\ ?.* { return TOKEN_COMMENT; } -IDENTIFICATION { return TOKEN_IDENTIFICATION; } +\*>\ ?.* +IDENTIFICATION { return TOKEN_KEYWORD_IDENTIFICATION; } DIVISION { return TOKEN_KEYWORD_DIVISION; } PROGRAM-ID { return TOKEN_PROGRAM_ID; } PROCEDURE { return TOKEN_PROCEDURE; } @@ -27,8 +27,7 @@ PERFORM { return TOKEN_PERFORM; } END-PERFORM { return TOKEN_END_PERFORM; } IF { return TOKEN_IF; } END-IF { return TOKEN_END_IF; } -ELSE { return TOKEN_ELSE; } -SPACE { return TOKEN_SPACE; } +SPACE { return TOKEN_SPACE; } PIC { return TOKEN_PICTURE; } OCCURS { return TOKEN_KEYWORD_OCCURS; } VALUE { return TOKEN_KEYWORD_VALUE; } @@ -43,7 +42,6 @@ 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; } @@ -55,7 +53,6 @@ COMP-3 { return TOKEN_COMPUTATION_LEVEL_3; } \< { return TOKEN_LESS_THAN; } \= { return TOKEN_EQUAL;} - "\""[^"]*"\"" { return TOKEN_STRING; } "\'"[^']*"\'" { return TOKEN_STRING; } "(" { return TOKEN_LEFT_PARENTHESIS; } diff --git a/lab-3/token.h b/lab-3/token.h index e64609e..20c1ffa 100644 --- a/lab-3/token.h +++ b/lab-3/token.h @@ -1,6 +1,6 @@ typedef enum { TOKEN_EOF = 0, - TOKEN_IDENTIFICATION, + TOKEN_KEYWORD_IDENTIFICATION, TOKEN_KEYWORD_DIVISION, TOKEN_KEYWORD_DATA, TOKEN_KEYWORD_SECTION, diff --git a/lab-4/parser.bison b/lab-4/parser.bison index c24ae00..dfeb38e 100644 --- a/lab-4/parser.bison +++ b/lab-4/parser.bison @@ -93,49 +93,53 @@ simple_stmt : cbl_func_stmt cbl_func_stmt : cbl_function | cbl_function op_parms | cbl_function assignment_stmt - | cbl_function op_parms assignment_stmt + | cbl_function op_parm assignment_stmt ; assignment_stmt : TOKEN_EQUAL ext_function - | TOKEN_EQUAL function + | TOKEN_EQUAL op_parms | TOKEN_KEYWORD_TO op_parms ; -op_parms : mathmaticalexpr +op_parms : op_parm + | op_parms op_parm + ; +op_parm : mathmaticalexpr | booleanexpr - | otherexpr | type_expr ; -mathmaticalexpr : type_expr TOKEN_ADD type_expr - | type_expr TOKEN_SUB type_expr - | type_expr TOKEN_MULTIPLY type_expr - | type_expr TOKEN_DIVIDE type_expr - | type_expr TOKEN_EXPONENTIAL type_expr - | TOKEN_SUB type_expr +mathmaticalexpr : type_expr + | mathmaticalexpr TOKEN_ADD mathmaticalexpr + | mathmaticalexpr TOKEN_SUB mathmaticalexpr + | mathmaticalexpr TOKEN_MULTIPLY mathmaticalexpr + | mathmaticalexpr TOKEN_DIVIDE mathmaticalexpr + | mathmaticalexpr TOKEN_EXPONENTIAL mathmaticalexpr + | container_expr + | type_expr container_expr ; -booleanexpr : op_parms TOKEN_LESS_THAN op_parms - | op_parms TOKEN_GREATER_THAN op_parms - | op_parms TOKEN_EQUAL op_parms +container_expr : TOKEN_LEFT_PARENTHESIS op_parms TOKEN_RIGHT_PARENTHESIS ; -otherexpr : TOKEN_LEFT_PARENTHESIS op_parms TOKEN_RIGHT_PARENTHESIS - | op_parms op_parms +booleanexpr : mathmaticalexpr TOKEN_LESS_THAN mathmaticalexpr + | mathmaticalexpr TOKEN_GREATER_THAN mathmaticalexpr + | mathmaticalexpr TOKEN_EQUAL mathmaticalexpr ; type_expr : TOKEN_IDENT | TOKEN_INTEGER | TOKEN_STRING | TOKEN_SPACE - ; -function : op_parms + | TOKEN_SUB TOKEN_IDENT ; 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 +if_branch : if_start statements else_parts + ; +if_start : TOKEN_IF booleanexpr + ; +else_parts : + | TOKEN_ELSE_IF booleanexpr statements else_parts + | TOKEN_ELSE statements ; 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 diff --git a/lab-4/samples/quadratic-snippet.cbl b/lab-4/samples/quadratic-snippet.cbl index ab76e40..7f27b4d 100644 --- a/lab-4/samples/quadratic-snippet.cbl +++ b/lab-4/samples/quadratic-snippet.cbl @@ -24,12 +24,10 @@ 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. diff --git a/lab-4/samples/sorting-snippet.cbl b/lab-4/samples/sorting-snippet.cbl index 8324e47..07b2ebd 100644 --- a/lab-4/samples/sorting-snippet.cbl +++ b/lab-4/samples/sorting-snippet.cbl @@ -39,7 +39,6 @@ PROCEDURE DIVISION. 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 diff --git a/lab-5/parser.bison b/lab-5/parser.bison index 2139d87..dfeb38e 100644 --- a/lab-5/parser.bison +++ b/lab-5/parser.bison @@ -1,41 +1,14 @@ %{ #define YYDEBUG 1 #include - -#include -#include -#include -#include "expr.h" - -/* -YYSTYPE is the lexical value returned by each rule in a bison grammar. -By default, it is an integer. In this example, we are returning a pointer to an expression. -*/ - -#define YYSTYPE struct expr * - -/* -Clunky: Manually declare the interface to the scanner generated by flex. -*/ - -extern char *yytext; -extern int yylex(); extern int yylineno; 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 expr * parser_result = 0; +int yylex(); %} %debug %define parse.error detailed - %token TOKEN_EOF %token TOKEN_KEYWORD_IDENTIFICATION %token TOKEN_KEYWORD_DIVISION @@ -120,49 +93,53 @@ simple_stmt : cbl_func_stmt cbl_func_stmt : cbl_function | cbl_function op_parms | cbl_function assignment_stmt - | cbl_function op_parms assignment_stmt + | cbl_function op_parm assignment_stmt ; assignment_stmt : TOKEN_EQUAL ext_function - | TOKEN_EQUAL function + | TOKEN_EQUAL op_parms | TOKEN_KEYWORD_TO op_parms ; -op_parms : mathmaticalexpr +op_parms : op_parm + | op_parms op_parm + ; +op_parm : mathmaticalexpr | booleanexpr - | otherexpr | type_expr ; -mathmaticalexpr : type_expr TOKEN_ADD type_expr - | type_expr TOKEN_SUB type_expr - | type_expr TOKEN_MULTIPLY type_expr - | type_expr TOKEN_DIVIDE type_expr - | type_expr TOKEN_EXPONENTIAL type_expr - | TOKEN_SUB type_expr +mathmaticalexpr : type_expr + | mathmaticalexpr TOKEN_ADD mathmaticalexpr + | mathmaticalexpr TOKEN_SUB mathmaticalexpr + | mathmaticalexpr TOKEN_MULTIPLY mathmaticalexpr + | mathmaticalexpr TOKEN_DIVIDE mathmaticalexpr + | mathmaticalexpr TOKEN_EXPONENTIAL mathmaticalexpr + | container_expr + | type_expr container_expr ; -booleanexpr : op_parms TOKEN_LESS_THAN op_parms - | op_parms TOKEN_GREATER_THAN op_parms - | op_parms TOKEN_EQUAL op_parms +container_expr : TOKEN_LEFT_PARENTHESIS op_parms TOKEN_RIGHT_PARENTHESIS ; -otherexpr : TOKEN_LEFT_PARENTHESIS op_parms TOKEN_RIGHT_PARENTHESIS - | op_parms op_parms +booleanexpr : mathmaticalexpr TOKEN_LESS_THAN mathmaticalexpr + | mathmaticalexpr TOKEN_GREATER_THAN mathmaticalexpr + | mathmaticalexpr TOKEN_EQUAL mathmaticalexpr ; type_expr : TOKEN_IDENT | TOKEN_INTEGER | TOKEN_STRING | TOKEN_SPACE - ; -function : op_parms + | TOKEN_SUB TOKEN_IDENT ; 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 +if_branch : if_start statements else_parts + ; +if_start : TOKEN_IF booleanexpr + ; +else_parts : + | TOKEN_ELSE_IF booleanexpr statements else_parts + | TOKEN_ELSE statements ; 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 diff --git a/lab-5/samples/quadratic-snippet.cbl b/lab-5/samples/quadratic-snippet.cbl index ab76e40..7f27b4d 100644 --- a/lab-5/samples/quadratic-snippet.cbl +++ b/lab-5/samples/quadratic-snippet.cbl @@ -24,12 +24,10 @@ 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. diff --git a/lab-5/samples/sorting-snippet.cbl b/lab-5/samples/sorting-snippet.cbl index 8324e47..07b2ebd 100644 --- a/lab-5/samples/sorting-snippet.cbl +++ b/lab-5/samples/sorting-snippet.cbl @@ -39,7 +39,6 @@ PROCEDURE DIVISION. 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 diff --git a/lab-5/scanner.flex b/lab-5/scanner.flex index ca9acac..4b7a148 100644 --- a/lab-5/scanner.flex +++ b/lab-5/scanner.flex @@ -1,5 +1,5 @@ %{ -#include "parser.h" +#include "token.h" %} NAME [a-zA-Z]([a-zA-Z0-9_-]*[a-zA-Z0-9])? DIGIT [0-9]+ diff --git a/lab-5/token.h b/lab-5/token.h new file mode 100644 index 0000000..ebb85f5 --- /dev/null +++ b/lab-5/token.h @@ -0,0 +1,126 @@ +/* A Bison parser, made by GNU Bison 3.8.2. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, + especially those whose name start with YY_ or yy_. They are + private implementation details that can be changed or removed. */ + +#ifndef YY_YY_TOKEN_H_INCLUDED +# define YY_YY_TOKEN_H_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token kinds. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + YYEMPTY = -2, + YYEOF = 0, /* "end of file" */ + YYerror = 256, /* error */ + YYUNDEF = 257, /* "invalid token" */ + TOKEN_EOF = 258, /* TOKEN_EOF */ + TOKEN_KEYWORD_IDENTIFICATION = 259, /* TOKEN_KEYWORD_IDENTIFICATION */ + TOKEN_KEYWORD_DIVISION = 260, /* TOKEN_KEYWORD_DIVISION */ + TOKEN_KEYWORD_DATA = 261, /* TOKEN_KEYWORD_DATA */ + TOKEN_KEYWORD_SECTION = 262, /* TOKEN_KEYWORD_SECTION */ + TOKEN_PROGRAM_ID = 263, /* TOKEN_PROGRAM_ID */ + TOKEN_WORKING_STORAGE = 264, /* TOKEN_WORKING_STORAGE */ + TOKEN_PROCEDURE = 265, /* TOKEN_PROCEDURE */ + TOKEN_STOP = 266, /* TOKEN_STOP */ + TOKEN_RUN = 267, /* TOKEN_RUN */ + TOKEN_MOVE = 268, /* TOKEN_MOVE */ + TOKEN_KEYWORD_TO = 269, /* TOKEN_KEYWORD_TO */ + TOKEN_PERFORM = 270, /* TOKEN_PERFORM */ + TOKEN_VARYING = 271, /* TOKEN_VARYING */ + TOKEN_KEYWORD_FROM = 272, /* TOKEN_KEYWORD_FROM */ + TOKEN_KEYWORD_BY = 273, /* TOKEN_KEYWORD_BY */ + TOKEN_UNTIL = 274, /* TOKEN_UNTIL */ + TOKEN_END_PERFORM = 275, /* TOKEN_END_PERFORM */ + TOKEN_IF = 276, /* TOKEN_IF */ + TOKEN_ELSE_IF = 277, /* TOKEN_ELSE_IF */ + TOKEN_ELSE = 278, /* TOKEN_ELSE */ + TOKEN_END_IF = 279, /* TOKEN_END_IF */ + TOKEN_SPACE = 280, /* TOKEN_SPACE */ + TOKEN_KEYWORD_OCCURS = 281, /* TOKEN_KEYWORD_OCCURS */ + TOKEN_KEYWORD_VALUE = 282, /* TOKEN_KEYWORD_VALUE */ + TOKEN_KEYWORD_COMPUTE = 283, /* TOKEN_KEYWORD_COMPUTE */ + TOKEN_KEYWORD_FUNCTION = 284, /* TOKEN_KEYWORD_FUNCTION */ + TOKEN_IDENT = 285, /* TOKEN_IDENT */ + TOKEN_STRING = 286, /* TOKEN_STRING */ + TOKEN_INTEGER = 287, /* TOKEN_INTEGER */ + TOKEN_PICTURE = 288, /* TOKEN_PICTURE */ + TOKEN_ALPHANUMERIC = 289, /* TOKEN_ALPHANUMERIC */ + TOKEN_NUMERIC = 290, /* TOKEN_NUMERIC */ + TOKEN_SIGNED_NUMERIC = 291, /* TOKEN_SIGNED_NUMERIC */ + TOKEN_IMPLIED_DECIMAL = 292, /* TOKEN_IMPLIED_DECIMAL */ + TOKEN_COMPUTATION_LEVEL_0 = 293, /* TOKEN_COMPUTATION_LEVEL_0 */ + TOKEN_COMPUTATION_LEVEL_1 = 294, /* TOKEN_COMPUTATION_LEVEL_1 */ + TOKEN_COMPUTATION_LEVEL_2 = 295, /* TOKEN_COMPUTATION_LEVEL_2 */ + TOKEN_COMPUTATION_LEVEL_3 = 296, /* TOKEN_COMPUTATION_LEVEL_3 */ + TOKEN_LEFT_PARENTHESIS = 297, /* TOKEN_LEFT_PARENTHESIS */ + TOKEN_RIGHT_PARENTHESIS = 298, /* TOKEN_RIGHT_PARENTHESIS */ + TOKEN_DOT = 299, /* TOKEN_DOT */ + TOKEN_ADD = 300, /* TOKEN_ADD */ + TOKEN_SUB = 301, /* TOKEN_SUB */ + TOKEN_MULTIPLY = 302, /* TOKEN_MULTIPLY */ + TOKEN_DIVIDE = 303, /* TOKEN_DIVIDE */ + TOKEN_EQUAL = 304, /* TOKEN_EQUAL */ + TOKEN_GREATER_THAN = 305, /* TOKEN_GREATER_THAN */ + TOKEN_LESS_THAN = 306, /* TOKEN_LESS_THAN */ + TOKEN_EXPONENTIAL = 307, /* TOKEN_EXPONENTIAL */ + TOKEN_DISPLAY = 308 /* TOKEN_DISPLAY */ + }; + typedef enum yytokentype yytoken_kind_t; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + + +int yyparse (void); + + +#endif /* !YY_YY_TOKEN_H_INCLUDED */