Files
cs5/05-parsing/main.rkt
T
2025-10-17 14:47:26 -04:00

152 lines
2.7 KiB
Racket

#lang pl
#|
"{{{2 + 5}} * {5 * {{3 + 6}}}}"
The parenthesis ^here & ^here are necessary because otherwise it would be an AE, not a Prod as R3 requires. It requires this to maintain order of operations.
"{{{2 + 5}} * {5 * {{3 * 6}}}}"
The parenthesis are no longer needed, as {3 * 6} is itself a prod satisfying R3.
If you have a grammar language with easy precedence, it's nice. Otherwise, it's cursed.
In Yacc:
%left ADD SUB
%left MUL DIV
%precedence NEG
exp:
...
| NUM {...}
| GROUPSTART exp GROUPEND { ... }
| SUB exp {...}
| exp SUM exp {...}
| exp SUB exp {...}
| exp MUL exp {...}
| exp DIV exp {...}
|#
(define-type AE
[R1 Prod AE]
[R2 Prod])
(define-type Prod
[R3 Atom Prod]
[R4 Atom])
(define-type Atom
[R5 Number]
[R6 AE])
#|
<AE> ::= <PROD> + <AE> (1)
| <PROD> (2)
<PROD> ::= <ATOM> * <PROD> (3)
| <ATOM> (4)
<ATOM> ::= <num> (5)
| { <AE> } (6)
|#
; Symbols:
; 'sum
; 'mul
; 'groups
; 'groupe
(: parseae : (Sexpr -> AE))
(define (parseae s)
(match s
[(list prod '+ ae) (R1 (parseprod prod) (parseae ae))]
[prod (R2 (parseprod prod))]))
(: parseprod : (Sexpr -> Prod))
(define (parseprod s)
(match s
[(list atom '* prod) (R3 (parseatom atom) (parseprod prod))]
[ atom (R4 (parseatom atom))]))
(: parseatom : (Sexpr -> Atom))
(define (parseatom s)
(match s
[ (number: n) (R5 n)]
[(list ae) (R6 (parseae ae))]))
(: parse : (String -> AE))
(define (parse s) (parseae (string->sexpr s)))
(test (parse "5") => (R2 (R4 (R5 5))))
(test (parse "{2 + 5}") => (R1 (R4 (R5 2)) (R2 (R4 (R5 5)))))
(test (parse "{{{2 + 5}} * {5 * {{3 + 6}}}}") => (R2 (R3 (R6 (R1 (R4 (R5 2)) (R2 (R4 (R5 5))))) (R3 (R5 5) (R4 (R6 (R1 (R4 (R5 3)) (R2 (R4 (R5 6)))))))))
)
; parse-ae/h: s: Sexpr, ae: AE → AE
#|
<AE> ::= <PROD> + <AE> (1)
| <PROD> (2)
<PROD> ::= <ATOM> * <PROD> (3)
| <ATOM> (4)
<ATOM> ::= <num> (5)
| { <AE> } (6)
These are not wrapped in the few rules at the top level to convert them to AEs
"5"
<atom> (5)
<num> 5
"{5}"
<atom> (6)
<ae> (2)
<prod> (4)
<atom> (5)
<num> 5
"{2 + 5}"
<atom> (6)
<ae> (1)
<prod> (4)
<atom> (5)
<num> 2
<ae> (2)
<prod> (4)
<atom> (5)
<num> 5
"{{{2 + 5}} * {5 * {{3 + 6}}}}"
<atom> (6)
<ae> (2)
<prod> (3)
<atom> (6)
<atom> (6)
<ae> (1)
<prod> (4)
<atom> (5)
<num> 2
<ae> (2)
<prod> (4)
<atom> (5)
<num> 5
<prod> (4)
<atom> (6)
<prod> (3)
<atom> (5)
<num> 5
<prod> (4)
<atom> (6)
<atom> (6)
<ae> (1)
<prod> (4)
<atom> (5)
<num> 3
<ae> (2)
<prod> (4)
<atom> (5)
<num> 6
|#