Advertisement
Guest User

Untitled

a guest
Dec 18th, 2014
263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 5.60 KB | None | 0 0
  1. #lang racket
  2. (require scheme/mpair)
  3. (define ns (make-base-namespace))
  4.  
  5. (define (tokenize expr)
  6.   (string-split (regexp-replace* #rx"([\\(\\)\\+\\-\\^%\\*/])" expr " & ")))
  7.  
  8. (define (eval-string s)
  9.   (eval (with-input-from-string s read) ns))
  10.  
  11. (define make-stack
  12.   (lambda ()
  13.     (let ((ls '()))
  14.       (lambda (msg . args)
  15.         (cond
  16.           ((eqv? msg 'empty?) (null? ls))
  17.           ((eqv? msg 'push!) (set! ls (cons (car args) ls)))
  18.           ((eqv? msg 'top) (car ls))
  19.           ((eqv? msg 'pop!) (set! ls (cdr ls)))
  20.           ((eqv? msg '->list) ls)
  21.           (else "oops"))))))
  22.  
  23.  
  24.  
  25. (define make-queue
  26.   (lambda ()
  27.     (let ((end (mcons 'ignored '())))
  28.       (mcons end end))))
  29.  
  30. (define (fillq! q lst)
  31.   (cond
  32.     ((null? lst) #t)
  33.     (else (begin
  34.             (putq! q (car lst))
  35.             (fillq! q (cdr lst))))))
  36.  
  37. (define putq!
  38.   (lambda (q v)
  39.     (let ((end (mcons 'ignored '())))
  40.       (set-mcar! (mcdr q) v)
  41.       (set-mcdr! (mcdr q) end)
  42.       (set-mcdr! q end))))
  43.  
  44. (define getq
  45.   (lambda (q)
  46.     (mcar (mcar q))))
  47.  
  48. (define delq!
  49.   (lambda (q)
  50.     (set-mcar! q (mcdr (mcar q)))))
  51.  
  52. (define (right-assoc? op)
  53.   (equal? op "^"))
  54.  
  55. (define (left-assoc? op)
  56.   (not (right-assoc? op)))
  57.  
  58. (define (precedence op)
  59.   (cond
  60.     ((or (equal? op "+") (equal? op "-")) 1)
  61.     ((or (equal? op "%") (equal? op "*") (equal? op "/")) 2)
  62.     ((equal? op "^") 3)
  63.     (else (raise-user-error "Not a valid operator" op))))
  64.  
  65. (define (shunting-yard expr)
  66.   (let ((main_loop #f) (token #f) (ops '("+" "-" "/" "*" "^" "%")) (inq (make-queue)) (outstack (make-stack)) (auxstack (make-stack)))
  67.     (begin
  68.       (fillq! inq (reverse expr))
  69.       (call/cc (lambda (k) (set! main_loop k)))
  70.       (cond
  71.          ((and (eqv? 'ignored (getq inq))
  72.                (not (auxstack 'empty?))) (begin
  73.                                            (outstack 'push! (auxstack 'top))
  74.                                            (auxstack 'pop!)
  75.                                            (main_loop #t)))
  76.          ((and (eqv? 'ignored (getq inq))
  77.                (auxstack 'empty?)) outstack)
  78.          (else (begin
  79.                  (set! token (getq inq))
  80.                  (delq! inq)
  81.                  (cond
  82.                    ((string->number token) (begin
  83.                                              (outstack 'push! token)
  84.                                              (main_loop #t)))
  85.                    ((member token ops) (let ((operator_loop #f))
  86.                                          (begin
  87.                                            (call/cc (lambda (k) (set! operator_loop k)))
  88.                                            (cond
  89.                                              ((and (not (auxstack 'empty?))
  90.                                                    (member (auxstack 'top) ops)
  91.                                                    (or (and (right-assoc? token)
  92.                                                             (< (precedence token) (precedence (auxstack 'top))))
  93.                                                        (and (left-assoc? token)
  94.                                                             (<= (precedence token) (precedence (auxstack 'top))))))
  95.                                              (begin
  96.                                                (outstack 'push! (auxstack 'top))
  97.                                                (auxstack 'pop!)
  98.                                                (operator_loop #t)))
  99.                                            (else (begin
  100.                                                    (auxstack 'push! token)
  101.                                                    (main_loop #t)))))))
  102.                    ((equal? token "(") (let ((parentheses_loop #f))
  103.                                        (begin
  104.                                          (call/cc (lambda (k) (set! parentheses_loop k)))
  105.                                          (cond
  106.                                            ((equal? ")" (auxstack 'top)) (begin
  107.                                                                          (auxstack 'pop!)
  108.                                                                          (main_loop #t)))
  109.                                            ((member (auxstack 'top) ops) (begin
  110.                                                                            (outstack 'push! (auxstack 'top))
  111.                                                                            (auxstack 'pop!)
  112.                                                                            (parentheses_loop #t)))))))
  113.                    ((equal? token ")") (begin
  114.                                        (auxstack 'push! token)
  115.                                        (main_loop #t))))))))))
  116.                  
  117.  
  118. (define (eval-pn expr)
  119.   (let ((q (make-queue)) (outstack (make-stack)) (loop #f) (ops '("+" "-" "/" "*" "^" "%")))
  120.     (begin
  121.       (fillq! q (reverse expr))
  122.       (call/cc (lambda (k) (set! loop k)))
  123.       (cond
  124.         ((eqv? 'ignored (getq q)) (outstack 'top))
  125.         ((member (getq q) ops)
  126.          (let* ((n1 (outstack 'top)) (n2 (begin (outstack 'pop!) (outstack 'top))))
  127.            (begin
  128.              (outstack 'pop!)
  129.              (outstack 'push! (number->string (eval-string (string-append "(" (getq q) " " n1 " " n2 ")"))))))
  130.          (delq! q)
  131.          (loop #t))
  132.         (else (begin
  133.                 (outstack 'push! (getq q))
  134.                 (delq! q)
  135.                 (loop #t)))))))
  136.      
  137.  
  138.                  
  139. (define expr "3*(4+5)/3")                                        
  140. (set! expr (tokenize expr))  
  141. (set! expr ((shunting-yard expr) '->list))
  142. (eval-pn expr)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement