cmcs 430 project 4
Project 4 - CMSC 430 7380 Compiler Theory and Design (2248) - UMGC Learning Management System.pdf
21.10.24, 21:05Project 4 - CMSC 430 7380 Compiler Theory and Design (2248) - UMGC Learning Management System
Page 1 of 2https://learn.umgc.edu/d2l/lms/dropbox/user/folder_submit_files.d2l?db=1686832&grpid=0&isprv=0&bp=0&ou=1277989
Project 4 Course: CMSC 430 7380 Compiler Theory and Design (2248)
Criteria Meets Does not Meet Criterion Score
Functionality / 160160 points
Generates semantic error
when list element types
do not match (15)
Generates semantic error
list type does not match
element types (15)
Generates semantic error
when list subscript is not
integer (15)
Generates semantic error
when character literals are
compared to numeric
expressions (15)
Generates semantic error
when remainder operator
has non-integer operands
(15)
Generates semantic error
when if-elsif-else types
don't match (15)
Generates semantic error
when fold contains a non-
numeric list (15)
Generates semantic on
narrowing variable
initialization and function
return (25)
Generates semantic error
when types do not match
on function return (15)
0 points
Does not generate
semantic error when list
element types do not
match (0)
Does not generate
semantic error when list
type does not match
element types (0)
Does not generate
semantic error when list
subscript is not integer (0)
Does not generates
semantic error when
character literals are
compared to numeric
expressions (0)
Does not generate
semantic error when
remainder operator has
non-integer operands (0)
Does not generate
semantic error when if-
elsif-else types don't
match (0)
Does not generate
semantic error when fold
contains a non-numeric
list (0)
Does not generate
semantic on narrowing
variable initialization and
21.10.24, 21:05Project 4 - CMSC 430 7380 Compiler Theory and Design (2248) - UMGC Learning Management System
Page 2 of 2https://learn.umgc.edu/d2l/lms/dropbox/user/folder_submit_files.d2l?db=1686832&grpid=0&isprv=0&bp=0&ou=1277989
Total / 225
Overall Score
Test Cases / 30
Documentation / 35
Generates semantic error
for duplicate variables (15)
function return (0)
Does not generate
semantic error when types
do not match on function
return (0)
Does not generate
semantic error for
duplicate variables (0)
30 points
Includes test cases that
test all type checking
errors (10)
Includes test cases that
test all symbol table errors
(10)
Includes test case with
multiple errors (10)
0 points
Does not Include test
cases that test all type
checking errors (0)
Does not include test
cases that test all symbol
table errors (0)
Does not include test case
with multiple errors (0)
35 points
Discussion of approach
included (10)
Lessons learned included
(15)
Comment blocks with
student name, project,
date and code description
included in each file (10)
0 points
Discussion of approach
not included (0)
Lessons learned not
included (0)
Comment blocks with
student name, project,
date and code description
not included in each file
(0)
Meets 150 points minimum
Does not Meet 0 points minimum
__MACOSX/._Project 4 - CMSC 430 7380 Compiler Theory and Design (2248) - UMGC Learning Management System.pdf
Project 4 Approach.pdf
Here is the recommended approach for project 4.
1) Although you have the option of keeping the interpreter from project 3 in the final project, it is
a more complicated approach. Unless you are an experienced C++ programmer, it will be
simpler to take your project 2 implementation and begin by incorporating what is in the project 4
skeleton, much like what you should have done for project 3. Because your project 2 has
additional productions, be sure to include them in your %type declaration. You are likely to have
some type clash warnings at this point. You initially should be able to ignore them. Once you
complete the project, they should all be resolved, however.
At this point, you should verify that the test cases provided with the project 4 skeleton,
semantic1.txt – semantic7.txt, produce the same output as before.
A good starting point would be to incorporate real types. To accomplish that you will need to
modify the Types enumeration in types.h, assign an attribute to real literal tokens in scanner.l
and modify the type production in parser.y. To verify that your program accepts real types,
use valid1.txt. Shown below is the output that should result when using that test case as input:
$ ./compile < valid1.txt
1 -- Program with a Real Variable
2
3 function main returns real;
4 a: real is 4.5;
5 begin
6 a;
7 end;
Compiled Successfully
The fact that it compiles successfully confirms that real types have been added.
2) Next ensure that hexadecimal literals are identified as type integer. Assigning an attribute to
hexadecimal integer literal in scanner.l is required. To verify that your program accepts
hexadecimal literals as integers, use valid2.txt. Shown below is the output that should result
when using that test case as input:
$ ./compile < valid2.txt
1 -- Program with a Hexadecimal Literals
2
3 function main returns integer;
4 a: integer is #A;
5 begin
6 a + #a;
7 end;
Compiled Successfully
The fact that it compiles successfully confirms that hexadecimal literals are treated as integers.
3) The next requirement to implement is to ensure that type coercion from an integer to a real
type is performed within arithmetic expressions. That will require that you modify the
checkArithmetic function so that it returns a real type when one operand is integer and the
other is real. It should, of course, still return an integer type when both types are integer. To
verify that your program performs type coercion, use valid3.txt. Shown below is the output
that should result when using that test case as input:
$ ./compile < valid3.txt
1 -- Program with a Real Variable
2
3 function main returns real;
4 a: real is 4 + 4.5;
5 begin
6 a;
7 end;
Compiled Successfully
The fact that it compiles successfully confirms that type coercion has been incorporated.
4) Next, include a check to ensure that lists contain elements that are all the same type. Adding a
semantic action to the expressions production is required. Creating a new function in types.cc
is a good idea. This check is similar to the check made to ensure all case statements have the
same type, but is somewhat simpler because all lists must contain at least one clement. Use
semantic8.txt to test this modification. Shown below is the output that should result when
using that test case as input:
$ ./compile < semantic8.txt
1 // List with Elements of Different Types
2
3 function main returns integer;
4 aList: list of integer is (1, 2, 3.5);
Semantic Error, List Element Types Do Not Match
5 begin
6 aList(1);
7 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
5) Next, include a check to ensure that the type of a list variable matches the type of its elements.
Adding a semantic action to the variable production whose right-hand side declares lists is
required. Creating a new function in types.cc is a good idea. Use semantic9.txt to test this
modification. Shown below is the output that should result when using that test case as input:
$ ./compile < semantic9.txt
1 // List Type Does Not Match Element Types
2
3 function main returns character;
4 aList: list of character is (1, 2, 3);
Semantic Error, List Type Does Not Match Element Types
5 begin
6 aList(1);
7 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
6) Include a check to ensure that the type of a list subscript is an integer expression. Adding a
semantic action to the primary production whose right-hand side defines subscripted lists is
required. Creating a new function in types.cc is a good idea. Use semantic10.txt to test this
modification. Shown below is the output that should result when using that test case as input:
$ ./compile < semantic10.txt
1 // List Subscript is not Integer
2
3 function main returns integer;
4 aList: list of integer is (1, 2, 3);
5 begin
6 aList(1.5);
Semantic Error, List Subscript Must Be Integer
7 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
7) Include a check to ensure that character literals can be compared to other character literals but
cannot be compared to numeric expressions. Adding a semantic action to the relation is
required. Creating a new function in types.cc is a good idea. Use semantic11.txt to test this
modification. Shown below is the output that should result when using that test case as input:
$ ./compile < semantic11.txt
1 -- Mixing Numeric and Character Types with Relational Operator
2
3 function main returns integer;
4 begin
5 if 'b' < 'c' then
6 1;
7 elsif 'b' < 1 then
Semantic Error, Character Literals Cannot be Compared to Numeric Expressions
8 2;
9 else
10 3;
11 endif;
12 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
8) Because the skeleton did not include productions for all operators, you need to add semantic
actions to those productions. The exponentiation operator and the arithmetic negation operators
both require additional checks. Use semantic12.txt to test this modification. Shown below is
the output that should result when using that test case as input:
$ ./compile < semantic12.txt
1 // Using Character Literal with Exponentiation Operator
2 // and Negation Operator
3
4 function main returns integer;
5 c: character is ~'c';
Semantic Error, Arithmetic Operator Requires Numeric Types
6 begin
7 5 ^ 'P';
Semantic Error, Arithmetic Operator Requires Numeric Types
8 end;
9
Lexical Errors 0
Syntax Errors 0
Semantic Errors 2
The fact that two error messages have been generated confirms that the productions have been
successfully modified.
9) Because the remainder operator was not in the skeleton, it is necessary to implement the test
that determines whether the types on the % operator are integers. Adding a new function to
types.cc is again a good idea, given that this check requires more than a single line of code.
Use semantic13.txt to test this modification. Shown below is the output that should result
when using that test case as input:
$ ./compile < semantic13.txt
1 // Mixing Real Literals with the Remainder Operator
2
3 function main returns integer;
4 begin
5 4 % 4.8;
Semantic Error, Remainder Operator Requires Integer Operands
6 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
10) The semantic check on the if statement would be a good next step. This check can be
accomplished by adding a semantic actions on the various productions that define the if
statement and ideally adding a new function in types.cc. Use semantic13.txt to test this
semantic check. Shown below is the output that should result when using that test case as input:
$ ./compile < semantic14.txt
1 -- If Elsif Else Mismatch
2
3 function main returns integer;
4 begin
5 if 9 < 10 then
6 1;
7 elsif 8 = 1 then
8 2;
9 else
10 3.7;
Semantic Error, If-Elsif-Else Type Mismatch
11 endif;
12 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
11) Next, implement the rule associated with the fold statement that requires that the type of the
list be numeric. Use semantic15.txt to test this modification. Shown below is the output that
should result when using that test case as input:
$ ./compile < semantic15.txt
1 // Folding a nonnumeric List
2
3 function main returns integer;
4 begin
5 fold left + ('a', 'b', 'c') endfold;
Semantic Error, Fold Requires A Numeric List
6 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
12) The next best pair of checks to implement are the ones that check whether a variable
initialization or function return are narrowing. Both require changing the checkAssignment
function. Use semantic16.txt to test the check for narrowing variable initialization. Shown
below is the output that should result when using that test case as input:
$ ./compile < semantic16.txt
1 -- Narrowing Variable Initialization
2
3 function main returns integer;
4 b: integer is 5 * 2.5;
Semantic Error, Illegal Narrowing Variable Initialization
5 begin
6 b + 1;
7 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
13) You should be able to use the same function to check a narrowing function return by adding
a similar semantic action on the top level production for the whole function. Be sure that you
have declared that the function_header and body productions carry a type attribute if your
receive an error indicating that they have no declared type. In addition both require semantic
actions that pass the type information up the parse tree. Use semantic17.txt to test the check
for a narrowing function return. Shown below is the output that should result when using that test
case as input:
$ ./compile < semantic17.txt
1 -- Narrowing Function Return
2
3 function main returns integer;
4 b: integer is 6 * 2;
5 begin
6 if 8 < 0 then
7 b + 3.0;
8 else
9 b * 4.6;
10 endif;
11 end;
Semantic Error, Illegal Narrowing Function Return
Lexical Errors 0
Syntax Errors 0
Semantic Errors 1
14) The check for duplicate scalar and list variables is a good one to incorporate next. Because
the symbol table already contains a function to look up identifiers, no modification to the symbol
table code is required. Instead the semantic action for variable declarations can be modified to
first check whether the identifier is in the symbol table, and if so, generate a duplicate identifier
error. Writing a separate function that can be passed which symbol table to use will avoid
duplicating code. Use semantic18.txt to test the check for a duplicate identifier. Shown below
is the output that should result when using that test case as input:
$ ./compile < semantic18.txt
1 -- Duplicate Scalar and List Variables
2
3 function main returns integer;
4 scalar: integer is 4 * 2;
5 scalar: character is 'b';
Semantic Error, Duplicate Scalar scalar
6 a_list: list of integer is (4, 2);
7 a_list: list of real is (2.3, 4.4);
Semantic Error, Duplicate List a_list
8 begin
9 1;
10 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 2
15) As a final test, use semantic19.txt to test a program that contains multiple semantic errors.
Shown below is the output that should result when using that test case as input:
$ ./compile < semantic19.txt
1 // Multiple Semantic Errors
2
3 function main returns integer;
4 value: integer is 4.5;
Semantic Error, Illegal Narrowing Variable Initialization
5 numbers: list of real is (1, 2, 3);
Semantic Error, List Type Does Not Match Element Types
6 one: integer is '1';
Semantic Error, Type Mismatch on Variable Initialization
7 begin
8 if value > 0 then
9 fold left + ('a', 'b') endfold;
Semantic Error, Fold Requires A Numeric List
10 elsif name = 'N' then
Semantic Error, Undeclared Scalar name
11 fold right * (1, 2.5) endfold;
Semantic Error, List Element Types Do Not Match
12 else
13 when value < 10, 1 : 1.5;
Semantic Error, When Types Mismatch
14 endif;
15 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 7
All of the test cases discussed above are included in the attached .zip file.
You are certainly encouraged to create any other test cases that you wish to incorporate in your
test plan. Keep in mind that your compiler should produce the correct semantic error for all
programs that contain them, so it is recommended that you choose some different test cases as a
part of your test plan. Your instructor may use a comparable but different set of test cases when
testing your project.
__MACOSX/._Project 4 Approach.pdf
Project 4 Requirements.pdf
CMSC 430 Project 4
The fourth project involves modifying the semantic analyzer for the attached compiler by adding
checks for semantic errors. The static semantic rules of this language are the following:
Variable and parameter names have local scope. The scope rules require that all names be
declared and prohibit duplicate names within the same scope. The type correspondence rules are
as follows:
Both expressions in the when statement must be the same type
The type of the switch expression must be Integer.
All the case statements in a switch statement must match in type. No coercion is
performed.
Arithmetic operators can only be used with numeric types.
All list elements must be of the same type.
In a list variable declaration, the type of the list must match the type of the elements.
List subscripts must be integer expressions.
Character literals can be compared to one another but they cannot be compared to
numeric expressions.
Only integer operands can be used with the remainder operator.
All the statements in an if statement must match in type. No coercion is performed.
In a fold statement, the list must be a numeric type.
A narrowing variable initialization or function return error occurs when a real value is
being forced into integer. Widening is permitted. In all other cases, the type must match.
Type coercion from an integer to a real type is performed within arithmetic expressions.
You must make the following semantic checks. Those highlighted in yellow are already
performed by the code that you have been provided, although you are must make minor
modifications to account for the addition of real types and the need to perform type coercion and
to handle the additional arithmetic, relational and logical operators.
Type Mismatch on Variable Initialization
When Types Mismatch
Switch Expression Not Integer
Case Types Mismatch
Arithmetic Operator Requires Numeric Types
Undeclared Scalar
Undeclared List
List Element Types Do Not Match
List Type Does Not Match Element Types
List Subscript Must Be Integer
Character Literals Cannot be Compared to Numeric Expressions
Remainder Operator Requires Integer Operands
If-Elsif-Else Type Mismatch
Fold Requires A Numeric List
Illegal Narrowing Variable Initialization
Illegal Narrowing Function Return
Type Mismatch on Function Return
Duplicate Scalar
Duplicate List
This project requires modification to the bison input file, so that it defines the additional
semantic checks necessary to produce these errors and addition of functions to the library of type
checking functions already provided in types.cc. You must also make some modifications to
the functions provided. You need to add a check to the checkAssignment function for
mismatched types in the case that nonnumeric and numeric types are mixed. You need to also
add code to the checkArithmetic function to coerce integers to reals when the types are mixed.
The provided code includes a template class Symbols that defines the symbol table. It already
includes a check for undeclared identifiers. You need to add a check for duplicate identifiers.
Like the lexical and syntax errors, the compiler should display the semantic errors in the
compilation listing, after the line in which they occur. An example of a compilation listing output
containing semantic errors is shown below:
1 // Multiple Semantic Errors
2
3 function main returns integer;
4 value: integer is 4.5;
Semantic Error, Illegal Narrowing Variable Initialization
5 numbers: list of real is (1, 2, 3);
Semantic Error, List Type Does Not Match Element Types
6 one: integer is '1';
Semantic Error, Type Mismatch on Variable Initialization
7 begin
8 if value > 0 then
9 fold left + ('a', 'b') endfold;
Semantic Error, Fold Requires A Numeric List
10 elsif name = 'N' then
Semantic Error, Undeclared Scalar name
11 fold right * (1, 2.5) endfold;
Semantic Error, List Element Types Do Not Match
12 else
13 when value < 10, 1 : 1.5;
Semantic Error, When Types Mismatch
14 endif;
15 end;
Lexical Errors 0
Syntax Errors 0
Semantic Errors 7
You are to submit two files.
1. The first is a .zip file that contains all the source code for the project. The .zip file
should contain the flex input file, which should be a .l file, the bison file, which should
be a .y file, all .cc and .h files and a makefile that builds the project.
2. The second is a Word document (PDF or RTF is also acceptable) that contains the
documentation for the project, which should include the following:
a. A discussion of how you approached the project
b. A test plan that includes test cases that you have created indicating what aspects
of the program each one is testing and a screen shot of your compiler run on that
test case
c. A discussion of lessons learned from the project and any improvements that could
be made
__MACOSX/._Project 4 Requirements.pdf
__MACOSX/._Project 4 Skeleton Code
Project 4 Skeleton Code/scanner.l
/* CMSC 430 Compiler Theory and Design Project 4 Skeleton UMGC CITE Summer 2023 */ /* This file contains flex input file */ %{ #include <cstdio> #include <string> #include <vector> using namespace std; #include "types.h" #include "listing.h" #include "tokens.h" %} %option noyywrap ws [ \t\r]+ comment "//".*\n line [\n] id [A-Za-z]([A-Za-z0-9])* digit [0-9] dec {digit}+ char '.' punc [\(\),:;] %% {ws} { ECHO; } {comment} { ECHO; nextLine(); } {line} { ECHO; nextLine(); } "+" { ECHO; return(ADDOP); } "*" { ECHO; return(MULOP); } "&" { ECHO; return(ANDOP); } "<" { ECHO; return(RELOP); } "=>" { ECHO; return(ARROW); } begin { ECHO; return(BEGIN_); } case { ECHO; return(CASE); } character { ECHO; return(CHARACTER); } end { ECHO; return(END); } endswitch { ECHO; return(ENDSWITCH); } function { ECHO; return(FUNCTION); } integer { ECHO; return(INTEGER); } is { ECHO; return(IS); } list { ECHO; return(LIST); } of { ECHO; return(OF); } others { ECHO; return(OTHERS); } returns { ECHO; return(RETURNS); } switch { ECHO; return(SWITCH); } when { ECHO; return(WHEN); } {id} { ECHO; yylval.iden = (CharPtr)malloc(yyleng + 1); strcpy(yylval.iden, yytext); return(IDENTIFIER);} {dec} { ECHO; yylval.type = INT_TYPE; return(INT_LITERAL); } {char} { ECHO; yylval.type = CHAR_TYPE; return(CHAR_LITERAL); } {punc} { ECHO; return(yytext[0]); } . { ECHO; appendError(LEXICAL, yytext); } %%
__MACOSX/Project 4 Skeleton Code/._scanner.l
Project 4 Skeleton Code/symbols.h
// CMSC 430 Compiler Theory and Design // Project 4 Skeleton // UMGC CITE // Summer 2023 // This file contains the template symbol table template <typename T> class Symbols { public: void insert(char* lexeme, T entry); bool find(char* lexeme, T& entry); private: map<string, T> symbols; }; template <typename T> void Symbols<T>::insert(char* lexeme, T entry) { string name(lexeme); symbols[name] = entry; } template <typename T> bool Symbols<T>::find(char* lexeme, T& entry) { string name(lexeme); typedef typename map<string, T>::iterator Iterator; Iterator iterator = symbols.find(name); bool found = iterator != symbols.end(); if (found) entry = iterator->second; return found; }
__MACOSX/Project 4 Skeleton Code/._symbols.h
Project 4 Skeleton Code/types.h
// CMSC 430 Compiler Theory and Design // Project 4 Skeleton // UMGC CITE // Summer 2023 // This file contains type definitions and the function // prototypes for the type checking functions typedef char* CharPtr; enum Types {MISMATCH, INT_TYPE, CHAR_TYPE, NONE}; void checkAssignment(Types lValue, Types rValue, string message); Types checkWhen(Types true_, Types false_); Types checkSwitch(Types case_, Types when, Types other); Types checkCases(Types left, Types right); Types checkArithmetic(Types left, Types right);
__MACOSX/Project 4 Skeleton Code/._types.h
Project 4 Skeleton Code/makefile
compile: scanner.o parser.o listing.o types.o g++ -o compile scanner.o parser.o listing.o types.o scanner.o: scanner.c types.h listing.h tokens.h g++ -c scanner.c scanner.c: scanner.l flex scanner.l mv lex.yy.c scanner.c parser.o: parser.c types.h listing.h symbols.h g++ -c parser.c parser.c tokens.h: parser.y bison -d -v parser.y mv parser.tab.c parser.c cp parser.tab.h tokens.h listing.o: listing.cc listing.h g++ -c listing.cc types.o: types.cc types.h g++ -c types.cc
__MACOSX/Project 4 Skeleton Code/._makefile
Project 4 Skeleton Code/types.cc
Project 4 Skeleton Code/types.cc
// CMSC 430 Compiler Theory and Design
// Project 4 Skeleton
// UMGC CITE
// Summer 2023
// This file contains the bodies of the type checking functions
#include
<
string
>
#include
<
vector
>
using
namespace
std
;
#include
"types.h"
#include
"listing.h"
void
checkAssignment
(
Types
lValue
,
Types
rValue
,
string message
)
{
if
(
lValue
!=
MISMATCH
&&
rValue
!=
MISMATCH
&&
lValue
!=
rValue
)
appendError
(
GENERAL_SEMANTIC
,
"Type Mismatch on "
+
message
);
}
Types
checkWhen
(
Types
true_
,
Types
false_
)
{
if
(
true_
==
MISMATCH
||
false_
==
MISMATCH
)
return
MISMATCH
;
if
(
true_
!=
false_
)
appendError
(
GENERAL_SEMANTIC
,
"When Types Mismatch "
);
return
true_
;
}
Types
checkSwitch
(
Types
case_
,
Types
when
,
Types
other
)
{
if
(
case_
!=
INT_TYPE
)
appendError
(
GENERAL_SEMANTIC
,
"Switch Expression Not Integer"
);
return
checkCases
(
when
,
other
);
}
Types
checkCases
(
Types
left
,
Types
right
)
{
if
(
left
==
MISMATCH
||
right
==
MISMATCH
)
return
MISMATCH
;
if
(
left
==
NONE
||
left
==
right
)
return
right
;
appendError
(
GENERAL_SEMANTIC
,
"Case Types Mismatch"
);
return
MISMATCH
;
}
Types
checkArithmetic
(
Types
left
,
Types
right
)
{
if
(
left
==
MISMATCH
||
right
==
MISMATCH
)
return
MISMATCH
;
if
(
left
==
INT_TYPE
&&
right
==
INT_TYPE
)
return
INT_TYPE
;
appendError
(
GENERAL_SEMANTIC
,
"Integer Type Required"
);
return
MISMATCH
;
}
__MACOSX/Project 4 Skeleton Code/._types.cc
Project 4 Skeleton Code/listing.cc
Project 4 Skeleton Code/listing.cc
// CMSC 430 Compiler Theory and Design
// Project 4 Skeleton
// UMGC CITE
// Summer 2023
// This file contains the bodies of the functions that produces the
// compilation listing
#include
<
cstdio
>
#include
<
string
>
#include
<
vector
>
using
namespace
std
;
#include
"listing.h"
static
int
lineNumber
;
static
int
lexicalErrors
;
static
int
syntaxErrors
;
static
int
semanticErrors
;
static
vector
<
string
>
errors
;
static
void
displayErrors
();
void
firstLine
()
{
lexicalErrors
=
0
;
syntaxErrors
=
0
;
semanticErrors
=
0
;
lineNumber
=
1
;
printf
(
"\n%4d "
,
lineNumber
);
}
void
nextLine
()
{
displayErrors
();
lineNumber
++
;
printf
(
"%4d "
,
lineNumber
);
}
int
lastLine
()
{
printf
(
"\r"
);
displayErrors
();
printf
(
" \n"
);
int
totalErrors
=
lexicalErrors
+
syntaxErrors
+
semanticErrors
;
if
(
totalErrors
>
0
)
{
printf
(
"Lexical Errors %d\n"
,
lexicalErrors
);
printf
(
"Syntax Errors %d\n"
,
syntaxErrors
);
printf
(
"Semantic Errors %d\n"
,
semanticErrors
);
}
else
printf
(
"Compiled Successfully\n\n"
);
return
totalErrors
;
}
void
appendError
(
ErrorCategories
errorCategory
,
string message
)
{
string messages
[]
=
{
"Lexical Error, Invalid Character "
,
"Syntax Error, U"
,
"Semantic Error, "
,
"Semantic Error, Duplicate "
,
"Semantic Error, Undeclared "
};
switch
(
errorCategory
)
{
case
LEXICAL
:
lexicalErrors
++
;
break
;
case
SYNTAX
:
message
=
message
.
substr
(
15
);
syntaxErrors
++
;
break
;
case
GENERAL_SEMANTIC
:
case
DUPLICATE_IDENTIFIER
:
case
UNDECLARED
:
semanticErrors
++
;
break
;
}
errors
.
push_back
(
messages
[
errorCategory
]
+
message
);
}
void
displayErrors
()
{
for
(
int
i
=
0
;
i
<
errors
.
size
();
i
++
)
printf
(
"%s\n"
,
errors
[
i
].
c_str
());
errors
.
clear
();
}
__MACOSX/Project 4 Skeleton Code/._listing.cc
Project 4 Skeleton Code/parser.y
/* CMSC 430 Compiler Theory and Design Project 4 Skeleton UMGC CITE Summer 2023 Project 4 Parser with semantic actions for static semantic errors */ %{ #include <string> #include <vector> #include <map> using namespace std; #include "types.h" #include "listing.h" #include "symbols.h" int yylex(); Types find(Symbols<Types>& table, CharPtr identifier, string tableName); void yyerror(const char* message); Symbols<Types> scalars; Symbols<Types> lists; %} %define parse.error verbose %union { CharPtr iden; Types type; } %token <iden> IDENTIFIER %token <type> INT_LITERAL CHAR_LITERAL %token ADDOP MULOP RELOP ANDOP ARROW %token BEGIN_ CASE CHARACTER ELSE END ENDSWITCH FUNCTION INTEGER IS LIST OF OTHERS RETURNS SWITCH WHEN %type <type> list expressions body type statement_ statement cases case expression term primary %% function: function_header optional_variable body ; function_header: FUNCTION IDENTIFIER RETURNS type ';' ; type: INTEGER {$$ = INT_TYPE;} | CHARACTER {$$ = CHAR_TYPE; }; optional_variable: variable | %empty ; variable: IDENTIFIER ':' type IS statement ';' {checkAssignment($3, $5, "Variable Initialization"); scalars.insert($1, $3);} | IDENTIFIER ':' LIST OF type IS list ';' {lists.insert($1, $5);} ; list: '(' expressions ')' {$$ = $2;} ; expressions: expressions ',' expression | expression ; body: BEGIN_ statement_ END ';' {$$ = $2;} ; statement_: statement ';' | error ';' {$$ = MISMATCH;} ; statement: expression | WHEN condition ',' expression ':' expression {$$ = checkWhen($4, $6);} | SWITCH expression IS cases OTHERS ARROW statement ';' ENDSWITCH {$$ = checkSwitch($2, $4, $7);} ; cases: cases case {$$ = checkCases($1, $2);} | %empty {$$ = NONE;} ; case: CASE INT_LITERAL ARROW statement ';' {$$ = $4;} ; condition: condition ANDOP relation | relation ; relation: '(' condition')' | expression RELOP expression ; expression: expression ADDOP term {$$ = checkArithmetic($1, $3);} | term ; term: term MULOP primary {$$ = checkArithmetic($1, $3);} | primary ; primary: '(' expression ')' {$$ = $2;} | INT_LITERAL | CHAR_LITERAL | IDENTIFIER '(' expression ')' {$$ = find(lists, $1, "List");} | IDENTIFIER {$$ = find(scalars, $1, "Scalar");} ; %% Types find(Symbols<Types>& table, CharPtr identifier, string tableName) { Types type; if (!table.find(identifier, type)) { appendError(UNDECLARED, tableName + " " + identifier); return MISMATCH; } return type; } void yyerror(const char* message) { appendError(SYNTAX, message); } int main(int argc, char *argv[]) { firstLine(); yyparse(); lastLine(); return 0; }
__MACOSX/Project 4 Skeleton Code/._parser.y
Project 4 Skeleton Code/listing.h
// CMSC 430 Compiler Theory and Design // Project 4 Skeleton // UMGC CITE // Summer 2023 // This file contains the function prototypes for the functions that produce the // compilation listing enum ErrorCategories {LEXICAL, SYNTAX, GENERAL_SEMANTIC, DUPLICATE_IDENTIFIER, UNDECLARED}; void firstLine(); void nextLine(); int lastLine(); void appendError(ErrorCategories errorCategory, string message);
__MACOSX/Project 4 Skeleton Code/._listing.h
__MACOSX/._Project 4 Test Data
Project 4 Test Data/valid3.txt
-- Program with a Real Variable function main returns real; a: real is 4 + 4.5; begin a; end;
__MACOSX/Project 4 Test Data/._valid3.txt
Project 4 Test Data/semantic19.txt
// Multiple Semantic Errors function main returns integer; value: integer is 4.5; numbers: list of real is (1, 2, 3); one: integer is '1'; begin if value > 0 then fold left + ('a', 'b') endfold; elsif name = 'N' then fold right * (1, 2.5) endfold; else when value < 10, 1 : 1.5; endif; end;
__MACOSX/Project 4 Test Data/._semantic19.txt
Project 4 Test Data/semantic18.txt
-- Duplicate Scalar and List Variables function main returns integer; scalar: integer is 4 * 2; scalar: character is 'b'; a_list: list of integer is (4, 2); a_list: list of real is (2.3, 4.4); begin 1; end;
__MACOSX/Project 4 Test Data/._semantic18.txt
Project 4 Test Data/valid2.txt
-- Program with a Hexadecimal Literals function main returns integer; a: integer is #A; begin a + #a; end;
__MACOSX/Project 4 Test Data/._valid2.txt
Project 4 Test Data/semantic9.txt
// List Type Does Not Match Element Types function main returns character; aList: list of character is (1, 2, 3); begin aList(1); end;
__MACOSX/Project 4 Test Data/._semantic9.txt
Project 4 Test Data/semantic8.txt
// List with Elements of Different Types function main returns integer; aList: list of integer is (1, 2, 3.5); begin aList(1); end;
__MACOSX/Project 4 Test Data/._semantic8.txt
Project 4 Test Data/valid1.txt
-- Program with a Real Variable function main returns real; a: real is 4.5; begin a; end;
__MACOSX/Project 4 Test Data/._valid1.txt
Project 4 Test Data/semantic5.txt
// Using Character Variable with Arithmetic Operator function main returns integer; b: character is 'b'; begin b + 10; end;
__MACOSX/Project 4 Test Data/._semantic5.txt
Project 4 Test Data/semantic16.txt
-- Narrowing Variable Initialization function main returns integer; b: integer is 5 * 2.5; begin b + 1; end;
__MACOSX/Project 4 Test Data/._semantic16.txt
Project 4 Test Data/semantic17.txt
-- Narrowing Function Return function main returns integer; b: integer is 6 * 2; begin if 8 < 0 then b + 3.0; else b * 4.6; endif; end;
__MACOSX/Project 4 Test Data/._semantic17.txt
Project 4 Test Data/semantic4.txt
// Case Types Mismatch function main returns integer; b: character is 'b'; begin switch 1 is case 1 => 2; case 2 => b; others => 6; endswitch; end;
__MACOSX/Project 4 Test Data/._semantic4.txt
Project 4 Test Data/semantic6.txt
// Undeclared Scalar Variable function main returns integer; begin 2 * b + 3; end;
__MACOSX/Project 4 Test Data/._semantic6.txt
Project 4 Test Data/semantic15.txt
// Folding a nonnumeric List function main returns integer; begin fold left + ('a', 'b', 'c') endfold; end;
__MACOSX/Project 4 Test Data/._semantic15.txt
Project 4 Test Data/semantic14.txt
-- If Elsif Else Mismatch function main returns integer; begin if 9 < 10 then 1; elsif 8 = 1 then 2; else 3.7; endif; end;
__MACOSX/Project 4 Test Data/._semantic14.txt
Project 4 Test Data/semantic7.txt
// Undeclared List Variable function main returns integer; begin primes(1) + 1; end;
__MACOSX/Project 4 Test Data/._semantic7.txt
Project 4 Test Data/semantic3.txt
// Non Integer Switch Expression function main returns integer; b: character is 'A'; begin switch b is case 1 => 2; case 2 => 4; others => 6; endswitch; end;
__MACOSX/Project 4 Test Data/._semantic3.txt
Project 4 Test Data/semantic10.txt
// List Subscript is not Integer function main returns integer; aList: list of integer is (1, 2, 3); begin aList(1.5); end;
__MACOSX/Project 4 Test Data/._semantic10.txt
Project 4 Test Data/semantic11.txt
-- Mixing Numeric and Character Types with Relational Operator function main returns integer; begin if 'b' < 'c' then 1; elsif 'b' < 1 then 2; else 3; endif; end;
__MACOSX/Project 4 Test Data/._semantic11.txt
Project 4 Test Data/semantic2.txt
// When Types Mismatch function main returns integer; begin when 2 < 1, 1 : 'a'; end;
__MACOSX/Project 4 Test Data/._semantic2.txt
Project 4 Test Data/semantic13.txt
// Mixing Real Literals with the Remainder Operator function main returns integer; begin 4 % 4.8; end;
__MACOSX/Project 4 Test Data/._semantic13.txt
Project 4 Test Data/semantic12.txt
// Using Character Literal with Exponentiation Operator // and Negation Operator function main returns integer; c: character is ~'c'; begin 5 ^ 'P'; end;
__MACOSX/Project 4 Test Data/._semantic12.txt
Project 4 Test Data/semantic1.txt
// Variable Initialization Mismatch function main returns integer; value: integer is 'A'; begin 1; end;