180 likes | 333 Views
5. Phase 2 : Syntax Analysis Part III. Parsing expressions. The expression data structures. Parsing an expression. synExpression . synBasicExp . synTerm . synFactor . The demos. Parsing Expressions. synAssignSt , synIfSt and synWhileSt must parse C-- expressions.
E N D
5. Phase 2 : Syntax Analysis Part III • Parsing expressions. • The expression data structures. • Parsing an expression. • synExpression. • synBasicExp. • synTerm. • synFactor. • The demos.
Parsing Expressions • synAssignSt, synIfSt and synWhileSt must parse C-- expressions. • Currently synExpression only parses literal constants. • Need to define four subprograms : synFactor, synTerm, synBasicExp and synExpression. • They are mutually recursive as a factor may contain a bracketed expression or a negated factor. • Therefore synFactor may call synExpression or synFactor. • That’s why synExpression is forward declared in the template.
Expressions • C-- syntax : expression ::= basic_exp [ rel_op basic_exp ] basic_exp ::= term { add_op basic_exp } term ::= factor {mul_op term } factor ::= literal | identifier | ‘(‘ expression ‘)’ | ‘!’ factor • Example expressions : 22 + 4 < b z != y a !true
Expressions II • In syner.h : struct Expression { BasicExp *be1 ; string relOp ; BasicExp *be2 ; } ; struct BasicExp { Term *term ; string addOp ; BasicExp *bexp ; } ; struct Term { Factor *fact ; string mulOp ; Term *term ; } Unused fields set to ““ or NULL as appropriate.
Factors • In syner.h : struct Factor { bool literal ; // Tag field DataType type ; // Type field string litBool ; // Boolean literal string litString ; // String literal int litInt ; // Integer literal SymTab *ident ; // Identifier Expression *bexp ; // Bracket expression Factor *nFactor ; // Negated factor } ; • Literal is short for literal constant. • Note that C-- does not allow negative integer literals. • Makes things a lot simpler. • Unused fields are ignored. • Set to ““ or 0 or NULL as appropriate.
be1 : relOp : ““ be2 : NULL term : addOp : ““ bexp : NULL fact : mulOp : ““ term : NULL literal : true type : intData litBool : ““ litString : ““ litInt : 42 ident : NULL bexp : NULLnFactor : NULL Example Expressions • Example C-- expression : 42 • Schematic diagram :
be1 : * relOp : “<“ be2 : term : addOp : ““ bexp : NULL fact : mulOp : ““ term : NULL literal : false type : intData litBool : ““ litString : ““ litInt : 0 ident : bexp : NULLnFactor : NULL Symbol table entry for a Example Expressions II * as from be1 on last slide. • Example C-- expression : 42 < a • Schematic diagram :
Parsing An Expression • Subprogram header : void synExpression(SymTab *st, Expression *&expr, LexToken &lexToken, DataType &type) • Pointer to AST for the expression is returned via expr. • lexToken holds the first token of the expression. • When synExpression terminates will return the token after the expression in lexToken. • Lookahead. • type is the type of the expression parsed. • Used in type checking. • st is the symbol table. • Value parameter.
Top Level Code For synExpression synExpression(...) { Declarations. Create an Expression for expr and initialise it. Initialise type. synBasicExp(st, expr->be1, lexToken, type1) ; if (lexToken.tag == RELOP) { Store the RELOP in expr. lexAnal(lexToken) ; synBasicExp(st, expr->be2, lexToken, type2) ; Check for errors 204, 218 - 223. type1 = BOOLDATA ; } type = type1 ; } // synExpression
Top Level Code For synBasicExp • A basic expression is a term potentially followed by a list of ADDOPs and basic expressions. • Handle the list by calling synBasicExprecursively. void synBasicExp(SymTab *st, BasicExp *&bexp, LexToken &lexToken, DataType &type) { Declarations. Create a BasicExp for bexp and initialise it. Initialise type. synTerm(st, bexp->term, lexToken, type1) ;
Top Level Code For synBasicExp II if (lexToken.tag == ADDOP) { Store the ADDOP in bexp. lexAnal(lexToken) ; synBasicExp(st, bexp->bexp, lexToken, type2) ; Check for errors 206, 207, 208, 209. } type = type1 ; } // synBasicExp • We check for possible type conflicts between the term and the list of basic expressions as we go. • If an error is detected it is reported via error as usual.
Top Level Code For synTerm • A term is a factor potentially followed by a list of MULOPs and terms. • Handle the list by calling synTermrecursively. void synTerm(SymTab *st, Term *&term, LexToken &lexToken, DataType &type) { Declarations. Create a Term for term and initialise it. Initialise type. synFactor(st,term->fact, lexToken) ; type1 = term->fact->type ; • synFactor has no type parameter. Get the value for type1 from term->fact->type.
Top Level Code For synTerm II if (lexToken.tag == MULOP) { Store the MULOP in term. lexAnal(lexToken) ; synTerm(st, term->term, lexToken, type2) ; Check for errors 210, 211, 212, 213, 214. } type = type1 ; } // synTerm • We check for possible type conflicts between the factor and the list of terms as we go. • If an error is detected it is reported via error as usual.
Top Level Code For synFactor • A factor is a literal, an identifier, a bracketed expression or a negated factor. • Handle a bracketed expression by calling synExpressionrecursively. • Handle a negated factor by calling synFactorrecursively. void synFactor(SymTab *st, Factor *&fact, LexToken &lexToken) { Declarations. Create a Factor for fact and initialise it. if (lexToken.tag == BOOLIT) { Code to parse a bool literal. } else if (lexToken.tag == STRINGLIT) { Code to parse a string literal. } else if (lexToken.tag == INTLIT) { Code to parse an int literal. }
Top Level Code For synFactor II else if (lexToken.tag == IDENT) { Use lookup to check for error 102 and store SymTab entry in fact->ident. fact->literal = false ; fact->type = fact->ident->type ; lexAnal(lexToken) ; } else if (lexToken.tag == LPAREN) { lexAnal(lexToken) ; fact->literal = false ; synExpression(st, fact->bExp, lexToken, fact->type) ; Check for error 17. lexAnal(lexToken) ; }
Top Level Code For synFactor III else if (lexToken.tag == NOTOP) { lexAnal(lexToken) ; synFactor(st, fact->nFactor, lexToken) ; Check for error 215. fact->literal = false ; fact->type = BOOLDATA ; } } // synFactor
The Demos • As before there are two testing shell scripts. • testphase2 which will run your checker against a suite of test programs and print the results to the screen. • demophase2 which will be the same as testphase2 except that it will dump the results from your program to a file and compare them with the results produced by my program. • The demos will be during the scheduled practicals in weeks 9 and 10. • Procedure will be the same as for phase 1. • You book a slot. If you wish to do the demo outside the scheduled time come and get me. If I’m free you can do your demo. • E-mail bookings will not be accepted.
Summary • Currently your synExpression should only contain code to parse literal constants. • Move that code to synFactor where it belongs. • Change synExpression so that it merely calls synBasicExp. • Change synBasicExp so that it merely calls synTerm. • Change synTerm so that it merely calls synFactor. • synTerm will also have to check the type field of the factor to set the type field of the term. • Complete synFactor and test it. • Complete synTerm and test it. • Complete synBasicExp and test it. • Complete synExpression and test it.