Parsing: String to AST
The Problem
Given a concrete string like a|b*c, produce the abstract syntax tree.
Precedence Resolution
The string a|b*c should parse as a∣(b∗c), not (a∣b)∗c.
This is implemented by a parsing relation with precedence levels.
Parsing Relation
Levels
Define parsing at different precedence levels:
parseUnion: handles |
parseConcat: handles concatenation
parseStar: handles *
parseAtom: handles atoms and parentheses
Grammar (Simplified)
Union ::= Concat ('|' Concat)*
Concat ::= Star+
Star ::= Atom '*'*
Atom ::= ε | ∅ | symbol | '(' Union ')'
Rules for Parsing
Atoms:
parseAtom(a,Syma)parseAtom(ε,Null)parseAtom((s),R)parseUnion(s,R)
Star:
parseStar(s,R)parseAtom(s,R)parseStar(s∗,Star(R))parseStar(s,R)
Concatenation:
parseConcat(s,R)parseStar(s,R)parseConcat(s1s2,Concat(R1,R2))parseConcat(s1,R1)parseStar(s2,R2)
Union:
parseUnion(s,R)parseConcat(s,R)parseUnion(s1∣s2,Union(R1,R2))parseUnion(s1,R1)parseConcat(s2,R2)
Example Parse
String: a|b*
- Parse as Union
- Left part:
a parses as Syma
- Right part:
b*
b parses as Symb
b* parses as Star(Symb)
- Result: Union(Syma, Star(Symb))
Union
/ \
a Star
|
b
Parentheses Disambiguate
With Parentheses
(a|b)*c parses as:
Concat
/ \
Star c
|
Union
/ \
a b
Without Parentheses
a|b*c parses as a|(b*c):
Union
/ \
a Concat
/ \
Star c
|
b
Pretty Printing: AST to String
The Problem
Given an AST, produce a readable concrete string.
Strategy
- Recursively convert subtrees to strings
- Add parentheses when child has lower precedence than parent
- Minimize parentheses for readability
Precedence Table
| Constructor | Precedence |
|---|
| Star | 3 (highest) |
| Concat | 2 |
| Union | 1 (lowest) |
Rules
pprint(R,p)=pretty print R at precedence level p
Add parentheses if p>prec(R).
Atoms: Never need parentheses around themselves.
Star: pprint(R∗,p)=pprint(R,3)+∗
Concat: pprint(RS,p)=pprint(R,2)+pprint(S,2), parenthesise if p>2.
Union: pprint(R∣S,p)=pprint(R,1)+∣+pprint(S,1), parenthesise if p>1.
Example Pretty Prints
Simple
- pprint(a)=a
- pprint(a∗)=a∗
- pprint(ab)=ab
- pprint(a∣b)=a∣b
With Parentheses
- pprint((a∣b)∗)=(a∣b)∗ (union under star needs parens)
- pprint(a∗b∗)=a∗b∗ (no parens needed)
- pprint((a∣b)(c∣d))=(a∣b)(c∣d) (unions in concat need parens)
Round-Trip Property
Parsing then Pretty Printing
For any string s that parses to AST R:
parse(s)=R⇒pprint(R)=s′
where s′ is semantically equivalent and may be s or a normalised form.
Pretty Printing then Parsing
For any AST R:
parse(pprint(R))=R
The pretty-printed string should re-parse to the same AST.
Summary
- Parsing converts concrete strings to abstract syntax trees
- Precedence determines how strings are structured into trees
- Pretty printing converts ASTs back to readable strings
- Parentheses are added only when necessary for correctness