#toy.g #externs.g /* * parseUtil.d - some routines useful for parsing. */ /* * checkUndef - check a variable to make sure it is defined. */ proc checkUndef(*SymbolEntry_t se)void: if se*.se_kind = sk_empty then se*.se_kind := sk_undefined; se*.se_type := rt_error; errorHereThree("'", se*.se_name, "' not defined"); elif se*.se_kind = sk_undefined then errorHereThree("'", se*.se_name, "' not defined (subsequent use)"); fi; corp; /* * checkAssign - make sure that the given symbol is an assignable variable. */ proc checkAssign(register *SymbolEntry_t se)void: if se*.se_kind ~= sk_globalVariable and se*.se_kind ~= sk_parameter and se*.se_kind ~= sk_localVariable then if se*.se_kind ~= sk_undefined then errorHereThree("cannot assign to '", se*.se_name, "'"); fi; se*.se_kind := sk_globalVariable; se*.se_value := 0; fi; corp; /* * isStatement - return 'true' if the current token can appear after a * semicolon - i.e. it can start a new statement or it is the * closing reserved word of a compound statement. */ proc isStatement()bool: register TokenKind_t tk; tk := getSimpleToken(); tk = tk_id or tk = tk_number or tk = tk_if or tk = tk_elif or tk = tk_else or tk = tk_fi or tk = tk_while or tk = tk_od or tk = tk_readln or tk = tk_write or tk = tk_corp or tk = tk_semicolon or tk = tk_do corp; /* * findStatement - find something that can start a statement. */ proc findStatement()void: while skipToken(); getSimpleToken() ~= tk_eof and not isStatement() do od; corp; /* * findClose - skip tokens upto a statement, a comma or a right paren. */ proc findClose()void: register TokenKind_t tk; while skipToken(); tk := getSimpleToken(); tk ~= tk_comma and tk ~= tk_rightParen and tk ~= tk_eof and not isStatement() do od; if tk = tk_comma then nextToken(); fi; corp;