How PMAP Works
The .pmap file is the bridge between any writing style and Pseudo's internal canonical structures.
.pmap is a data file, not code. It maps text patterns to canonical structure names. The compiler reads it, resolves each line, then processes the canonical AST.Canonical Internal Structures
These are fixed - they never change. They are the core of Pseudo, built into the compiler:
| Canonical | Meaning |
|---|---|
FUNC_DEF | Function definition |
FOR_LOOP | Counted iteration with variable |
FOR_EACH | Element iteration over collection |
WHILE_LOOP | Condition-based loop |
UNTIL_LOOP | Inverted while - loop until condition true |
IF | Condition check |
ELSE_IF | Chained condition |
ELSE | Fallback block |
RETURN | Exit function with value |
BREAK | Exit loop |
CONTINUE | Skip to next iteration |
ASSIGN | Variable assignment |
PRINT | Output to terminal |
INPUT | Get value from user ($input) |
TRY / CATCH / FINALLY | Error handling blocks |
RAISE | Throw error |
GLOBAL | Declare variable as global |
SWAP | Exchange two values |
Pattern Matching - No Regex
Pattern matching uses a custom token matcher, not regex. This prevents catastrophic backtracking entirely.
Algorithm
token_match(pattern_tokens, input_tokens):
while pattern not exhausted and input not exhausted:
if current pattern token is LITERAL:
if it matches input token → advance both
else → NO_MATCH (fail fast)
if current pattern token is PLACEHOLDER:
collect tokens until next literal or stop-token
save to captures
if all pattern tokens consumed → MATCH(captures)
else → NO_MATCHTime: O(tokens in line). No backtracking possible.
Pattern Specificity
More specific patterns (more literal tokens) are tried first automatically:
# specificity = 4 (for, from, to, step) - tried first
for {var:name} from {start:expr} to {end:expr} step {step:expr}
# specificity = 3 (for, from, to) - tried second
for {var:name} from {start:expr} to {end:expr}Resolution Order (per line)
- Is it a comment? → COMMENT, done
- Is it a function DEF? → check name(args) + indented body below
- Is it a function CALL? → check symbol table from pass 1
- Is it a builtin call? → check builtin name list
- Run .pmap lookup → canonical structure match
- Is it an expression? → expression evaluator
- Nothing matched → error with suggestions
A .pmap File
@pmap-version 1.0
@pseudo-version >=1.0 <2.0
@language "English"
@author "Sanay"
[FOR_LOOP]
for {var:name} from {start:expr} to {end:expr} step {step:expr}
for {var:name} from {start:expr} to {end:expr}
loop {var:name} from {start:expr} to {end:expr}
[PRINT]
print {value:expr}
show {value:expr}
say {value:expr}Metadata Headers
| Header | Required | Description |
|---|---|---|
@pmap-version 1.0 | yes | pmap format version |
@pseudo-version >=1.0 <2.0 | optional | Compatible compiler version range |
@language "English" | optional | Human-readable label |
@author "name" | optional | Attribution |
@inherit default.pmap | optional | Inherit and extend another pmap |
@ignore-default | optional | Ignore all default.pmap mappings |
Fallback Chain
When no pattern matches, Pseudo falls through:
- @inherit chain - custom.pmap → default.pmap → core
- Expression fallback - try expression evaluator if operators/calls found
- Name resolution - single identifier → look up → auto-print or NameError
- Helpful error - suggests matching patterns
Trie + Cache
For performance, Pseudo builds a prefix trie from the first literal token of each pattern. Only patterns starting with the same token as the input line are checked - O(1) trie lookup + O(small subset) pattern check.
The compiled trie is cached as .pmap.cache and invalidated automatically when the .pmap SHA256 hash changes.