37 lines
1.0 KiB
Racket
37 lines
1.0 KiB
Racket
#lang racket
|
|
|
|
(require parser-tools/yacc
|
|
parser-tools/lex
|
|
(prefix-in ~ parser-tools/lex-sre))
|
|
|
|
(define-tokens value-tokens (NUM))
|
|
(define-empty-tokens op-tokens (OPEN CLOSE + - * / EOF NEG))
|
|
|
|
(define lex
|
|
(lexer [(eof) 'EOF]
|
|
[whitespace (lex input-port)]
|
|
[(~or "+" "-" "*" "/") (string->symbol lexeme)]
|
|
["(" 'OPEN]
|
|
[")" 'CLOSE]
|
|
[(~: (~+ numeric) (~? (~: #\. (~* numeric))))
|
|
(token-NUM (string->number lexeme))]))
|
|
|
|
(define parse
|
|
(parser [start E] [end EOF]
|
|
[tokens value-tokens op-tokens]
|
|
[error void]
|
|
[precs (left - +) (left * /) (left NEG)]
|
|
[grammar (E [(NUM) $1]
|
|
[(E + E) (+ $1 $3)]
|
|
[(E - E) (- $1 $3)]
|
|
[(E * E) (* $1 $3)]
|
|
[(E / E) (/ $1 $3)]
|
|
[(- E) (prec NEG) (- $2)]
|
|
[(OPEN E CLOSE) $2])]))
|
|
|
|
(define (calc str)
|
|
(define i (open-input-string str))
|
|
(displayln (parse (λ () (lex i)))))
|
|
|
|
(calc "(1 + 2 * 3) - (1+2)*-3")
|