cmcs 430 project 4

profileManix
Project4_CMSC4302.zip

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;

__MACOSX/Project 4 Test Data/._semantic1.txt