Handle invalid Lisp expression parsing
Company: Uber
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Take-home Project
Quick Answer: This question evaluates the ability to parse and evaluate nested Lisp-like expressions, manage variable bindings and scope resolution, and detect malformed input and syntax errors.
Constraints
- 1 <= expression length (an empty string is treated as invalid -> 'ERROR').
- Valid expressions follow the let/add/mult grammar described above.
- All intermediate and final integer values for valid inputs fit in a 32-bit signed integer.
- Invalid inputs (mismatched parentheses, unknown tokens, undefined variables, malformed integers, trailing characters) must return the string 'ERROR' rather than raising.
- Variable names are lowercase-letter-initial; 'let', 'add', 'mult' are reserved keywords.
Examples
Input: ("(let x 2 (mult x (let x 3 y 4 (add x y))))",)
Expected Output: 14
Explanation: Outer x=2; inner let rebinds x=3, y=4, inner (add x y)=7; (mult 2 7)=14.
Input: ("(let x 3 x 2 x)",)
Expected Output: 2
Explanation: x is bound to 3, then rebound to 2; the trailing expression x evaluates to the latest binding, 2.
Hints
- Use a recursive-descent parser with a single moving index into the string; evaluate `(add ...)`, `(mult ...)`, and `(let ...)` by their leading operator token after consuming '('.
- For `let`, scan variable/value pairs left to right, layering bindings into a copy of the enclosing scope; the final token (or parenthesized sub-expression) before ')' is the result expression — distinguish it by peeking whether the next non-space char is ')'.
- Wrap the whole evaluation in a try/except (or explicit error path): any structural problem — missing ')', unknown operator, unbound variable, leftover characters after the top-level expression — should produce the 'ERROR' sentinel instead of crashing.