def to_if(tokens: tc.TokenSeq) -> tp.Union[stmt.IfStmt, stmt.ErrorStmt]: paren = next(tu.token_find_index(tokens, {tt.RIGHT_PAREN}), len(tokens)) condition = ep.conditional(tokens[:paren + 1]) if condition.has_error(): return stmt.ErrorStmt() else_index = next(tu.token_find_index(tokens, {tt.ELSE}), len(tokens)) then_stmt = to_meta_dec(tokens[paren + 1:else_index]) else_stmt = to_meta_dec( tokens[else_index:]) if tokens[else_index:] else None return stmt.IfStmt(condition, then_stmt, else_stmt)
def to_while(tokens: tc.TokenSeq) -> tp.Union[stmt.WhileStmt, stmt.ErrorStmt]: right_paren = next(tu.token_find_index(tokens, {tt.RIGHT_PAREN}), len(tokens)) condition = ep.conditional(tokens[:right_paren + 1]) if condition.has_error(): return stmt.ErrorStmt() body = to_meta_dec(tokens[right_paren + 1:]) return stmt.WhileStmt(condition, body)
def call(tokens: tc.TokenSeq) -> ae.Expr: last_paren = next(tu.token_find_index(tokens, {tt.LEFT_PAREN, tt.DOT}), len(tokens)) if last_paren == 0: return primary(tokens) if tokens[last_paren - 1].type is tt.SUPER: lox_function = primary(tokens[:last_paren + 2]) else: lox_function = primary(tokens[:last_paren]) for paren_index in tu.token_find_index(tokens, {tt.RIGHT_PAREN, tt.DOT}): if tokens[paren_index].type is tt.RIGHT_PAREN: args = tuple( function_call_args( tokens[last_paren + CallIncrements[tokens[last_paren]. type]:paren_index], )) lox_function = expr.Call(lox_function, tokens[paren_index], args) elif tokens[paren_index - 1].type is not tt.SUPER: lox_function = expr.Get(lox_function, tokens[paren_index + 1]) last_paren = paren_index return lox_function
def assignment(tokens: tc.TokenSeq) -> ae.Expr: equal_index = next(tu.token_find_index(tokens, {tt.EQUAL}), None) if equal_index is None or not lu.is_lox_identifier(tokens[:equal_index]): return logic_or(tokens) var = call(tokens[:equal_index]) if not isinstance(var, (expr.Variable, expr.Get)): error(tokens[equal_index].line, "Invalid assignment target.") return expr.ErrorExpr() value = equality(tokens[equal_index + 1:]) if isinstance(var, expr.Get): return expr.Set(var, value) return expr.Assign(var.name, value)
def to_var( tokens: tp.Sequence[tc.Token] ) -> tp.Union[stmt.ErrorStmt, stmt.VarStmt]: relevant_tokens = tu.token_find_index(tokens, {tt.IDENTIFIER, tt.EQUAL}) index = next(relevant_tokens, None) name = tokens[index] if index is not None else tc.sentinel_token if name.type is not tt.IDENTIFIER: error(name.line, "Expect variable name.") return stmt.ErrorStmt() equal_index = next(relevant_tokens, None) if equal_index is None and index != len(tokens) - 1: error(name.line, "Expect nothing between the variable name and the equals sign.") return stmt.ErrorStmt() initializer = (ep.expression(tokens[equal_index + 1:]) if equal_index is not None else None) return stmt.VarStmt(name, initializer)