PrepStack · Markdown HTML

Parsing / token state machine

Geometry, sweep, simulation, and parsing · HTML

Formal shape

At position i, choose a rule by character class; the rule consumes one nonempty maximal prefix and returns (type,value,next_i).

Recognition signals

False friends

SignalWhy it is different
Splitting on individual charactersMulti-digit numbers, escapes, and unary symbols are cut incorrectly.
Expecting tokenization to solve nestingLexing recognizes words; precedence and parentheses still need a parser or stack.

Core invariant

Before each loop, s[:i] has been completely and non-overlappingly tokenized; the next rule consumes at least one character or reports an error.

State, transition, and processing order

ItemDefinition
StatePointer i, output tokens, current character class, and optional quote/escape mode.
TransitionSkip whitespace; maximally extend digits or names; emit known symbols; reject unknown characters.
Frontier / orderi is the sole boundary between parsed prefix and unknown suffix, and every successful branch advances it.

Python skeleton

def tokenize(s):
    tokens, i = [], 0
    while i < len(s):
        ch = s[i]
        if ch.isspace():
            i += 1
        elif ch.isdigit():
            j = i + 1
            while j < len(s) and s[j].isdigit(): j += 1
            tokens.append(('INT', int(s[i:j])))
            i = j
        elif ch.isalpha() or ch == '_':
            j = i + 1
            while j < len(s) and (s[j].isalnum() or s[j] == '_'): j += 1
            tokens.append(('NAME', s[i:j]))
            i = j
        elif ch in '+-*/()':
            tokens.append((ch, ch)); i += 1
        else:
            raise ValueError(f'unexpected character at {i}: {ch!r}')
    return tokens

Correctness sketch

  1. Every rule starts at current i, so emitted tokens do not overlap.
  2. Digit and name loops consume the longest contiguous prefix in their class.
  3. Every branch advances i or throws, ensuring termination without silent skips.
  4. Induction shows the returned tokens reconstruct the non-whitespace input.

Complexity

TimeSpaceParameters
O(n)O(k) outputn characters and k emitted tokens

Edge cases

Error patterns

PatternWhy it fails / fix
A branch does not advance iThe scanner loops forever.
Always attaching minus to numbersSubtraction and unary negation require grammar context.
Silently ignoring unknown charactersThis shifts error location and fabricates valid-looking output.

Selection and exclusion rules

RelationTemplateBoundary
lexical predecessorBalanced-delimiter stackDelimiter characters inside string literals must be tokenized correctly first.
state foundationExplicit simulation / state machineQuotes, comments, and escapes create modes
syntactic successorStack-based state simulationTokens are parsed with parentheses or operators

Original micro-example

PartDetail
ResultTokens are NAME, +, INT, *, (, NAME, -, INT, ).
ScenarioInput sum_2 + 17*(x-3).
WalkthroughNames and integers use maximal runs; symbols consume one character and whitespace is explicitly skipped.

Recall prompts

My notes