I spent too long on the tokenizer and ran out of steam by the time we got to error handling.
Start by clarifying the language's scope and requirements, then outline a classic interpreter pipeline: tokenizer, parser, evaluator, and error handling. Walk through each stage with a simple example, emphasizing modular design and robust error reporting.
Pro tip: Demonstrate how you'd structure the code for extensibility, such as using a visitor pattern for the AST or a pluggable error handler, and mention how you'd test each component independently.
Ask about the language's features, error handling expectations, and performance constraints to tailor your design. Confirm the basic operations: assignment, arithmetic, and print.
Define token types (identifiers, numbers, operators, keywords) and implement a lexer that converts input into a token stream, handling whitespace and invalid characters.
Choose a parsing strategy (e.g., recursive descent) and define AST node types for statements and expressions. Parse tokens into an AST, ensuring correct precedence and associativity.
Create an environment (e.g., a map) for variable storage. Traverse the AST to evaluate expressions and execute statements, updating the environment and producing output for print.
Detect and report errors like undefined variables, type mismatches, and syntax errors with clear messages and line numbers. Consider error recovery strategies.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.