Lisp Expression Parser
Reported by candidates from Amazon's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
The Amazon OA reported in September 2026 hands you a Lisp string like " (add 1 (mul 2 3)) " and wants it back as ["add","1",["mul","2","3"]], with no evaluation and no number conversion. It's a tokenizer plus a nesting problem, and the stack is the whole game. The input is guaranteed valid, so there's no error handling to sweat. The risk is sloppy output formatting, not hard logic. If you blank on the live assessment, StealthCoder sits invisibly on your screen and gives you a working solution in real time. Know the shape first.
The problem
Parse expression as one Lisp-style expression and return the canonical JSON serialization of its syntax tree as a string. An atom is a nonempty maximal sequence of ASCII letters, digits, underscore, plus, minus, asterisk or slash. Preserve its exact characters and case, including leading zeros and signs. A list consists of an opening parenthesis, zero or more expressions, and a closing parenthesis. Lists may nest. ASCII space, tab, line feed and carriage return separate tokens and may occur before or after the root. Parentheses are standalone tokens even when adjacent to atoms or other parentheses. The input is valid and contains exactly one root expression. Adjacent atoms must be separated by whitespace; parentheses already provide token boundaries. Serialize every atom as a JSON string and every list as a JSON array of its children, preserving their order and nesting. Use commas between children and no whitespace outside quoted atom strings. The allowed atom characters never contain a quote or backslash. An empty list becomes []. Do not evaluate operators, resolve names, change numeric-looking atoms into numbers, or flatten nested lists. For example, the atom 001 remains the JSON string "001". The function returns the serialized text, not a native nested array. Function parseLispExpression(expression: String) → String Examples Example 1 expression = " (add 1 (mul 2 3)) " return = "[\"add\",\"1\",[\"mul\",\"2\",\"3\"]]" The outer list has three children. Its last child is another list. Operator names and numbers are all strings; no multiplication or addition is performed. Example 2 expression = "(a (b) ())" return = "[\"a\",[\"b\"],[]]" The nested one-element list and the empty list remain distinct child arrays. Whitespace outside atoms is not part of the canonical output. Constraints 1 <= expression.length <= 5000. There are at most 2000 tokens, counting each parenthesis and each atom once. At most 100 lists are open at the same time. The expression follows the stated grammar and contains exactly one root.
Reported by candidates. Source: FastPrep
Pattern and pitfall
The trick is a single left-to-right scan with a stack of lists, or a recursive descent with an index pointer. Both run in linear time. On '(' push a new list or emit '['. On ')' pop and emit ']'. On an atom, read the maximal run of allowed characters and emit it wrapped in quotes. The pitfall is commas. You need one between siblings but not after an open bracket or before a close bracket. Track a 'needs comma' flag per depth level, or build child strings and join them with commas. Don't touch atoms like 001, keep case, and skip whitespace entirely. Depth is capped at 100, so recursion is safe, but an explicit stack avoids any worry. If the OA clock is ticking and the comma logic won't click, StealthCoder is your hedge for the live assessment. Test it on the empty list () and on nested empties.
The honest play: practice the pattern, and have StealthCoder ready for the one you didn't see coming.
You can drill Lisp Expression Parser cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Amazon's OA.
Amazon reuses patterns across OAs. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Lisp Expression Parser FAQ
What's the trick to the Amazon Lisp Expression Parser?+
Treat parentheses as standalone tokens and use a stack or recursion to track nesting. Open paren starts an array, close paren ends it, atoms become quoted strings. Build children into a list and join with commas. That's the entire algorithm, and it runs in O(n).
How hard is this problem really?+
Easier than it looks. There's no evaluation, no error handling, and the input is guaranteed valid. It's a tokenizer plus bracket matching. Most failures come from comma placement and whitespace handling, not from the algorithm itself.
Should I use recursion or an explicit stack?+
Either works. Depth is capped at 100 open lists, so recursion won't overflow. Recursive descent with a shared index is cleaner to write. An explicit stack of child lists is safer if you're nervous. Pick whichever you can write without bugs in one pass.
What edge cases should I test?+
Test a lone atom as root, the empty list (), nested empties like (()), adjacent parens like ((a)(b)), atoms with leading zeros or signs such as 001 and -5, and extra tabs, newlines, or carriage returns around the root. Output must have no whitespace outside quoted atoms.
How do I prepare in 48 hours?+
Write this parser from scratch twice, once recursive and once with a stack. Then do a couple of bracket-matching and nested-structure problems like decoding strings. Focus on clean tokenization and comma logic. Don't memorize it, understand why the stack mirrors the nesting.