CSE 340 Fall 2018 – Project 4Due on November 30, 2018 by 11:59 pmAbstractThe goal of this project is to give you some hands-on experience with implementing asmall compiler. You will write a compiler for a simple language. You will not be generatingassembly code. Instead, you will generate an intermediate representation (a data structurethat represents the program). The execution of the program will be done after compilation byinterpreting the generated intermediate representation.1 IntroductionYou will write a small compiler that will read an input program and represent it in an internaldata structure. The data structure consists of two parts: (1) a representation of instructionsto be executed and (2) a representation of the memory of the program (locations for variables).Instructions are represented by a data structure that includes the operand(s) of the instruction (ifany) and that specify the next instruction to be executed. After the data structures are generated byyour compiler, your compiler will execute the generated instructions representation by interpretingit. This means that the program will traverse the data structure and at every node it visits, itwill execute the node by changing the content of memory locations corresponding to operands anddeciding what is the next instruction to execute (program counter). The output of your compileris the output that the input program should produce. These steps are illustrated in the followingfigure1The remainder of this document is organized as follows:1. Grammar Defines the programming language syntax including grammar.2. Execution Semantics Describe statement semantics for if, while, switch and print statements.3. How to generate the intermediate representation Explains step by step how to generatethe intermediate representation (data structure). You should read this sequentially andnot skip around.4. Executing the intermediate representation Basically, you have two options: (1) If youare using C/C++, you should use the code we provide to execute the intermediate representation;(2) If you are using Java, this section describes the strict rules to follow in executingthe intermediate representation. Those rules will be enforced by inspecting your code.5. Requirements Lists the programming languages you are allowed to use in your solution(C/C++ or Java) and other requirements.6. Grading Describes the grading scheme.7. Second Chance Project Describes the requirements for a bonus project.2 GrammarThe grammar for this project is a simplified form of the grammar from the previous project, butthere are a couple extensions.program → var section bodyvar section → id list SEMICOLONid list → ID COMMA id list | IDbody → LBRACE stmt list RBRACEstmt list → stmt stmt list | stmtstmt → assign stmt | print stmt | while stmt | if stmt | switch stmt | for stmtassign stmt → ID EQUAL primary SEMICOLONassign stmt → ID EQUAL expr SEMICOLONexpr → primary op primaryprimary → ID | NUMop → PLUS | MINUS | MULT | DIVprint stmt → print ID SEMICOLONwhile stmt → WHILE condition bodyif stmt → IF condition bodycondition → primary relop primaryrelop → GREATER | LESS | NOTEQUALswitch stmt → SWITCH ID LBRACE case list RBRACEswitch stmt → SWITCH ID LBRACE case list default case RBRACE2for stmt → FOR LPAREN assign stmt condition SEMICOLON assign stmt RPAREN bodycase list → case case list | casecase → CASE NUM COLON bodydefault case → DEFAULT COLON bodySome highlights of the grammar:1. Expressions are greatly simplified and are not recursive.2. There is no type declaration section.3. Division is integer division and the result of the division of two integers is an integer.4. if statement is introduced. Note that if stmt does not have else.5. for statement is introduced. Note that for has a very general syntax similar to that of the Clanguage for loop.6. A print statement is introduced. Note that the print keyword is in lower case, but otherkeywords are all upper-case letters.7. There is no variable declaration list. There is only one id list in the global scope and thatcontains all the variables.8. There is no type specified for variables. All variables are int by default.3 Execution SemanticsAll statements in a statement list are executed sequentially according to the order in which theyappear. Exception is made for body of if stmt, while stmt and switch stmt as explained below. Inwhat follows, I will assume that all values of variables as well as constants are stored in locations.This assumption is used by the execution procedure that we provide. This is not a restrictiveassumption. For variables, you will have locations associated with them. For constants, you canreserve a location in which you store the constant (this is like having an unnamed immutablevariable).3.1 Assignment StatementTo execute an assignment statement, the expression on the lefthand side of the equal sign is evaluatedand the result is stored in the location associated with the righthand side of the expression.3.2 ExpressionTo evaluate an expression, the values in the locations associated with the two operands are obtainedand the expression operator is applied to these values resulting in a value for the expression.33.3 Boolean ConditionA boolean condition takes two operands as parameters and returns a boolean value. It is used tocontrol the execution of while and if statements. To evaluate a condition, the values in the locationsassociated with the operands are obtained and the relational operator is applied to these valuesresulting in a true or false value. For example, if the values of the two operands a and b are 3 and4 respectively, a 3.4 If statementif stmt has the standard semantics:1. The condition is evaluated.2. If the condition evaluates to true, the body of the if stmt is executed, then the next statement(if any) following the if stmt in the stmt list is executed.3. If the condition evaluates to false, the statement following the if stmt in the stmt list isexecutedThese semantics apply recursively to nested if stmt.3.5 While statementwhile stmt has the standard semantics.1. The condition is evaluated.2. If the condition evaluates to true, the body of the while stmt is executed. The next statementto execute is the while stmt itself.3. If the condition evaluates to false, the body of the while stmt is not executed. The nextstatement to execute is the next statement (if any) following the while stmt in the stmt list.These semantics apply recursively to nested while stmt. The code block:WHILE condition{stmt list}is equivalent to:label: IF condition{stmt listgoto label}4Note that goto statements do not appear in the input program, but our intermediate representationincludes GotoStatement which is used in conjunction with IfStatement to represent whileand switch statements.3.6 For statementThe for stmt is very similar to the for statement in the C language. The semantics are defined bygiving an equivalent construct.FOR ( assign stmt 1 condition ; assign stmt 2 ){stmt list}is equivalent to:assign stmt 1WHILE condition{stmt listassign stmt 2}For example, the following snippet of code:FOR ( a = 0; a {print a;}is equivalent to:a = 0;WHILE a {print a;a = a + 1;}3.7 Switch statementswitch stmt has the following semantics1:1The switch statement in the C language has different syntax and semantics. It is also dangerous!51. The value of the switch variable is checked against each case number in order.2. If the value matches the number, the body of the case is executed, then the statement followingthe switch stmt in the stmt list is executed.3. If the value does not match the number, next case is evaluated.4. If a default case is provided and the value does not match any of the case numbers, then thebody of the default case is executed and then the statement following the switch stmt in thestmt list is executed.5. If there is no default case and the value does not match any of the case numbers, then thestatement following the switch stmt in the stmt list is executed.These semantics apply recursively to nested switch stmt. The code block:SWITCH var {CASE n1 : { stmt list 1 }...CASE nk : { stmt list k }}is equivalent to:IF var == n1 {stmt list 1goto label}...IF var == nk {stmt list kgoto label}label:And for switch statements with default case, the code block:SWITCH var {CASE n1 : { stmt list 1 }...CASE nk : { stmt list k }DEFAULT : { stmt list default }}is equivalent to:6IF var == n1 {stmt list 1goto label}...IF var == nk {stmt list kgoto label}stmt list defaultlabel:3.8 Print statementThe statementprint a;prints the value of variable a at the time of the execution of the print statement.4 How to generate the codeThe intermediate code will be a data structure (a graph) that is easy to interpret and execute. Iwill start by describing how this graph looks for simple assignments then I will explain how to dealwith while statements.Note that in the explanation below I start with incomplete data structures then I explainwhat is missing and make them more complete. You should read the whole explanation.4.1 Handling simple assignmentsA simple assignment is fully determined by: the operator (if any), the id on the left-hand side, andthe operand(s). A simple assignment can be represented as a node:struct AssignmentStatement {struct ValueNode* left_hand_side;struct ValueNode* operand1;struct ValueNode* operand2;ArithmeticOperatorType op; // operator}For assignment without an expression on the right-hand side, the operator is set to OPERATOR NONEand there is only one operand. To execute an assignment, you need the values of the operand(s),apply the operator, if any, to the operands and assign the resulting value of the right-hand sideto the left hand side. For literals (NUM), the value is the value of the number. For variables, thevalue is the last value stored in the location associated with the variable. Initially, all variablesare initialized to 0. In this representation, the locations associated with variables as well as the7locations in which constants are stored are value nodes ( struct valueNode), a node that containsa value. The assignment statement contains pointers to the value nodes of the left-hand side andthe operand(s).Multiple assignments are executed one after another. So, we need to allow multiple assignmentnodes to be linked to each other. This can be achieved as follows:struct AssignmentStatement {struct ValueNode* left_hand_side;struct ValueNode* operand1;struct ValueNode* operand2;ArithmeticOperatorType op; // operatorstruct AssignmentStatement* next;}This structure only accepts ValueNode as operands. To handle literal constants (NUM), you needto create ValueNode for them and initialize the value stored in these value nodes to the constantvalue. This initialization, as well as the initialization of values in locations associated with variableis done while parsing.This will now allow us to execute a sequence of assignment statements represented in a linkedlist:we start with the head of the list, then we execute every assignment in the list one after theother.Begin Note It is important to distinguish between compile-time initialization and runtimeexecution. For example代写CSE 340留学生作业、代做C/C++、Java编程语言作业、代写data structure作业 代做留学生Pr, consider the programa b;{a = 3;b = 5;}The intermediate representation for this program will have have two assignment statements:one to copy the value in the location that contains the value 3 to the location associated with aand one to copy the value in the location that contains the value 5 to the location associated withb. The values 3 and 5 will not be copied to the locations of a and b at compile-time. The values3 and 5 will be copied during execution by the interpreter that we provided (for C/C++) or thatyou will write (for Java)End NoteThis is simple enough, but does not help with executing other kinds of statements. We considerthem one at a time.4.2 Handling print statementsThe print statement is straightforward. It can be represented asstruct PrintStatement{struct ValueNode* id;}8Now, we ask: how can we execute a sequence of statements that are either assignment or printstatement (or other types of statements)? We need to put both kinds of statements in a list and notjust the assignment statements as we did above. So, we introduce a new kind of node: a statementnode. The statement node has a field that indicates which type of statement it is. It also has fieldsto accommodate the remaining types of statements. It looks like this:struct StatementNode {StatementType type; // NOOP_STMT, GOTO_STMT, ASSIGN_STMT, IF_STMT, PRINT_STMTunion {struct AssignmentStatement* assign_stmt;struct PrintStatement* print_stmt;struct IfStatement* if_stmt;struct GotoStatement* goto_stmt;};struct StatementNode* next;}This way we can go through a list of statements and execute one after the other. To execute aparticular node, we check its type. If the type is PRINT STMT, we execute the print stmt field, ifthe type is ASSIGN STMT, we execute the assign stmt field and so on. With this modification, wedo not need a next field in the AssignmentStatement structure (as we explained above), instead,we put the next field in the statement node.This is all fine, but we do not yet know how to generate the list to execute later. The idea is tohave the functions that parses non-terminals return the code that corresponds to the non-terminals.For example for a statement list, we have the following pseudecode (missing many checks):struct StatementNode* parse_stmt_list(){struct StatementNode* st; // statementstruct StatementNode* stl; // statement listst = parse_stmt();if (nextToken == start of a statement list){stl = parse_stmt_list();append stl to st; // this is pseudecodereturn st;}else{ungetToken();return st;}}9And to parse body we have the following pseudecode:struct StatementNode* parse_body(){struct StatementNode* stl;match LBRACEstl = parse_stmt_list();match RBRACEreturn stl;}4.3 Handling if and while statementsMore complications occur with if and while statements. The structure for an if statement can beas follows:struct IfStatement {ConditionalOperatorType condition_op;struct ValueNode* condition_operand1;struct ValueNode* condition_operand2;struct StatementNode* true_branch;struct StatementNode* false_branch;}The condition op, condition operand1 and condition operand2 fields are the operator andoperands of the condition of the if statement. To generate the node for an if statement, we need toput together the condition, and stmt list that are generated in the parsing of the if statement.The true branch and false branch fields are crucial to the execution of the if statement. Ifthe condition evaluates to true then the statement specified in true branch is executed otherwisethe one specified in false branch is executed. We need one more type of node to allow loop backfor while statements. This is a GotoStatement.struct GotoStatement {struct StatementNode* target;}To generate code for the while and if statements, we need to put a few things together. The outlinegiven above for stmt list needs to be modified as follows (this is missing details and shows only themain steps).10struct StatementNode* parse_stmt(){...create statement node stif next token is IF{st->type = IF_STMT;create if-node; // note that if-node is pseudecode and is not// a valid identifier in C, C++ or Javast->if_stmt = if-node;parse the condition and set if-node->condition_op, if-node->condition_operand1 and if-node->condition_operand2if-node->true_branch = parse_body(); // parse_body returns a pointer to a list of statementscreate no-op node // this is a node that does not result// in any action being takenappend no-op node to the body of the if // this requires a loop to get to the end of// if-node->true_branch by following the next field// you know you reached the end when next is NULL// it is very important that you always appropriately// initialize fields of any data structures// do not use uninitialized pointersset if-node->false_branch to point to no-op nodeset st->next to point to no-op node...} else ...}The following diagram shows the desired structure for the if statement:11The stmt list code should be modified because of the extra no-op node:struct StatementNode* parse_stmt_list(){struct StatementNode* st; // statementstruct StatementNode* stl; // statement listst = parse_stmt();if (nextToken == start of a statement list){stl = parse_stmt_list();if st->type == IF_STMT{append stl to the no-op node that follows st// st// |// V// no-op// |// V// stl}else{append stl to st;// st// |// V// stl}return st;}else{ungetToken();return st;}}Handling while statement is similar. Here is the outline for parsing a while statement and creatingthe data structure for it:...create statement node stif next token is WHILE{st->type = IF_STMT; // handling WHILE using if and goto nodescreate if-node // if-node is not a valid identifier see// corresponding comment abovest->if_stmt = if-nodeparse the condition and set if-node->condition_op, if-node->condition_operand1 and if-node->condition_operand2if-node->true_branch = parse_body();create a new statement node gt // This is of type StatementNodegt->type = GOTO_STMT;create goto-node // This is of type GotoStatementgt->goto_stmt = goto-node;goto-node->target = st; // to jump to the if statement after// executing the body12append gt to the body of the while // append gt to the body of the while// this requires a loop. check the comment// for the if above.create no-op nodeset if-node->false_branch to point to no-op nodeset st->next to point to no-op node}...The following diagram shows the desired structure for the while statement:4.4 Handling switch and for statementsYou can handle the switch and for statements similarly, but you should figure that yourself. Usea combination of IfStatement and GotoStatement to support the semantics of the switch and forstatements. See sections 3.7 and 3.6 for the semantics of the switch and for statements.5 Executing the intermediate representationAfter the graph data structure is built, it needs to be executed. Execution starts with the firstnode in the list. Depending on the type of the node, the next node to execute is determined. Thegeneral form for execution is illustrated in the following pseudo-code.13pc = first nodewhile (pc != NULL){switch (pc->type){case ASSIGN_STMT: // code to execute pc->assign_stmt ...pc = pc->nextcase IF_STMT: // code to evaluate condition ...// depending on the result// pc = pc->if_stmt->true_branch// or// pc = pc->if_stmt->false_branchcase NOOP_STMT: pc = pc->nextcase GOTO_STMT: pc = pc->goto_stmt->targetcase PRINT_STMT: // code to execute pc->print_stmt ...pc = pc->next}}C/C++ implementations If you are developing in C/C++, we have provided you with the datastructures and the code to execute the graph and you must use it. There are two files compiler.hand compiler.cc, you need to write your code in separate file(s) and #include compiler.h. Theentry point of your code is a function declared in compiler.h:struct StatementNode* parse_generate_intermediate_representation();You need to implement this function.The main() function is provided in compiler.cc:int main(){struct StatementNode * program;program = parse_generate_intermediate_representation();execute_program(program);return 0;}It calls the function that you will implement which is supposed to parse the program andgenerate the intermediate representation, then it calls the execute program function to executethe program. You should not modify any of the given code. In fact if you write your program inC/C++, you should only submit the file(s) that contain your own code and we will add the givenpart and compile the code before testing. If you write your program in Java, you should strictlyfollow the guidelines for executing the intermediate representation.JAVA Implementation: If you write your solution in Java, executing the graph shouldbe done non-recursively and without any function calls. Even helper functions are not14allowed for the execution of the graph. This is a requirement that will be checked byinspecting your code. Little credit will be assigned if this requirement is not met.6 Requirements1. Write a compiler that generates intermediate representation for the code and write an interpreterto execute the intermediate representation. The interpreter is provided for C/C++implementations.2. Language: You can use Java, C, or C++ for this assignment.3. Any language other than Java, C or C++ is not allowed for this project.4. If you use C/C++ for this project, you should use the provided code and only implement therequired functions.5. If you use Java, you will need to write everything yourself but the requirements on how toexecute the intermediate representation will be checked manually when grading.6. Platform: As previous projects, the reference platform is CentOS 6.77. You can assume that there are no syntax or semantic errors in the input program.7 GradingThe test cases provided with the assignment, do not contain any test case for switch and forstatements. However, test cases with switch and for statements will be added for grading theproject. Make sure you test your code extensively with input programs that contain switch and forstatements.The test cases (there will be multiple test cases in each category, each with equal weight) willbe broken down in the following way (out of 100 points): Assignment statements: 20 If statements: 25 While statements: 30 Switch: 15 All statements not including For statement: 10 For statement: 5 (bonus) Total: 105Note that all test cases depend on successful implementation of print statements (otherwiseyour program cannot generate correct output). Also, assignment statements are needed for if,while, switch, statement test cases all depend on assignment statements.158 Second Chance ProjectFor this option you are given another chance to submit project 1 or 2. The grade you obtain willbe reduced by 35% and replaces the grade you already obtained on project 1 or 2. For example, So,if your grade for project 2 was 20 and your grade for the replacement is 90, the grade for project 2will be changed from 20 to 58.5 (58.5 = 90 reduced by 30%). The new grade for the replacementcannot count for more than 10% of the project grade. It cannot count for 13% of the project grade.转自:http://ass.3daixie.com/2018120769114152.html