#toy.g #externs.g /* * expression.d - routines for parsing, etc. expressions. */ /* * parseProcCall - parse a call to a procedure. */ proc parseProcCall(register *SymbolEntry_t se)void: register uint parCount; register TokenKind_t tk; register ResultType_t typ; bool errorFlagged; if getSimpleToken() = tk_leftParen then nextToken(); else errorHere("expecting '(' to start proc parameters"); fi; parCount := 0; errorFlagged := se*.se_kind ~= sk_procedure; while tk := getSimpleToken(); tk ~= tk_eof and tk ~= tk_rightParen and (tk = tk_id or tk = tk_number or not isStatement()) do typ := parseExpression(); if typ = rt_void then errorHere("expecting expression as proc parameter"); else if typ = rt_bool then errorHere("parameters must be of type 'int'"); fi; pushParameter(); fi; parCount := parCount + 1; if not errorFlagged and parCount > se*.se_parCount then errorFlagged := true; errorHere("too many parameters supplied"); fi; tk := getSimpleToken(); if tk = tk_comma then nextToken(); elif tk ~= tk_rightParen then errorHere("expecting ',' between proc parameters"); findClose(); fi; od; if parCount < se*.se_parCount and se*.se_kind = sk_procedure then errorHere("too few parameters supplied"); fi; if getSimpleToken() = tk_rightParen then nextToken(); else errorHere("expecting ')' to end proc parameters"); fi; callProc(se); corp; /* * parseUnit - bottom level of recursive descent expression parsing. */ proc parseUnit()ResultType_t: register TokenKind_t tk; *SymbolEntry_t se; ulong number; register ResultType_t typ; tk := getToken(&se, nil, &number); if tk = tk_id then checkUndef(se); nextToken(); tk := getSimpleToken(); if tk = tk_assign then parseAssignmentStatement(se); typ := rt_void; elif tk = tk_leftParen then parseProcCall(se); typ := if se*.se_kind = sk_procedure then se*.se_type else rt_error fi; elif se*.se_kind = sk_undefined then typ := rt_error; pushConstant(0); else /* sk_globalVariable, sk_parameter or sk_localVariable */ typ := se*.se_type; pushVariable(se); fi; elif tk = tk_number then nextToken(); typ := rt_int; pushConstant(number); elif tk = tk_true or tk = tk_false then nextToken(); typ := rt_bool; pushConstant(if tk = tk_true then 1 else 0 fi); elif tk = tk_leftParen then nextToken(); typ := parseExpression(); if getSimpleToken() = tk_rightParen then nextToken(); else errorHere("missing matching ')' in expression"); fi; else errorHere("syntax error - statement or expression needed"); if not isStatement() then skipToken(); fi; typ := rt_error; pushConstant(0); fi; typ corp; /* * parseUnary - parse the unary '+' or '-' operators. */ proc parseUnary()ResultType_t: register TokenKind_t tk; register ResultType_t typ; bool hadMinus; tk := getSimpleToken(); if tk = tk_plus or tk = tk_minus then hadMinus := tk = tk_minus; nextToken(); typ := parseUnary(); if typ = rt_void then errorHere("can't use statement as operand"); else if typ ~= rt_int and typ ~= rt_error then errorHere("operand to unary '+' or '-' must be int"); fi; if hadMinus then unaryOp(tk); fi; fi; rt_int else parseUnit() fi corp; /* * parseMulDiv - parse the binary '*' and '/' operators. */ proc parseMulDiv()ResultType_t: register TokenKind_t tk; register ResultType_t typ; typ := parseUnary(); while tk := getSimpleToken(); tk = tk_star or tk = tk_slash do if typ = rt_void then errorHere("can't use statement as operand"); pushConstant(0); elif typ ~= rt_int and typ ~= rt_error then errorHere("operand to binary '*' or '/' must be int"); fi; nextToken(); typ := parseUnary(); if typ = rt_void then errorHere("can't use statement as operand"); else if typ ~= rt_int and typ ~= rt_error then errorHere("operand to binary '*' or '/' must be int"); fi; binaryOp(tk); fi; typ := rt_int; od; typ corp; /* * parseAddSub - parse the binary '+' and '-' operators. */ proc parseAddSub()ResultType_t: register TokenKind_t tk; register ResultType_t typ; typ := parseMulDiv(); while tk := getSimpleToken(); tk = tk_plus or tk = tk_minus do if typ = rt_void then errorHere("can't use statement as operand"); pushConstant(0); elif typ ~= rt_int and typ ~= rt_error then errorHere("operand to binary '+' or '-' must be int"); fi; nextToken(); typ := parseMulDiv(); if typ = rt_void then errorHere("can't use statement as operand"); else if typ ~= rt_int and typ ~= rt_error then errorHere("operand to binary '+' or '-' must be int"); fi; binaryOp(tk); fi; typ := rt_int; od; typ corp; /* * parseComparison - parse the comparison operators. */ proc parseComparison()ResultType_t: register TokenKind_t tk; register ResultType_t typ; typ := parseAddSub(); tk := getSimpleToken(); if tk = tk_equal or tk = tk_notEqual or tk = tk_less or tk = tk_lessEqual or tk = tk_greater or tk = tk_greaterEqual then if typ = rt_void then errorHere("can't use statement as operand"); pushConstant(0); elif typ ~= rt_int and typ ~= rt_error then errorHere("operand to comparison must be int"); fi; nextToken(); typ := parseAddSub(); if typ = rt_void then errorHere("can't use statement as operand"); else if typ ~= rt_int and typ ~= rt_error then errorHere("operand to comparison must be int"); fi; compareValues(tk); fi; rt_bool else typ fi corp; /* * parseExpression - top level of recursive descent expression parser. * This could have been just 'parseComparison', but doing it this * way allows better nameing and easier expansion. */ proc parseExpression()ResultType_t: parseComparison() corp;