使双方在DrRacket和(x)REPL脚本工作

问题描述 投票:2回答:2

我想从两个DrRacket和REPL使脚本工作,有这个作为我的出发点:Racket calculator

这里是我当前的代码:

#lang racket


(provide (all-defined-out))

(require parser-tools/lex
         (prefix-in re: parser-tools/lex-sre)
         parser-tools/yacc)


(define-tokens value-tokens (INT ANY))
(define-empty-tokens empty-tokens
  (PLUS MINUS MULTIPLY DIVIDE NEWLINE EOF))


(define basic-lexer
  (lexer
   ((re:+ numeric) (token-INT lexeme))
   (#\+ (token-PLUS))
   (#\- (token-MINUS))
   (#\* (token-MULTIPLY))
   (#\/ (token-DIVIDE))   
   ((re:or #\tab #\space) (basic-lexer input-port))
   (#\newline (token-NEWLINE))
   ((eof) (token-EOF))
   (any-char (token-ANY lexeme))))


(define (display-plus expr)
  (display "Result: ")
  (let ((left (string->number (first expr)))
        (right (string->number (last expr))))
    (display (+ left right)))
  (newline))


(define (display-minus expr)
  (display "Result: ")
  (let ((left (string->number (first expr)))
        (right (string->number (last expr))))
    (display (- left right)))
  (newline))


(define (display-multiply expr)
  (display "Result: ")
  (let ((left (string->number (first expr)))
        (right (string->number (last expr))))
    (display (* left right)))
  (newline))


(define (display-divide expr)
  (display "Result: ")
  (let ((left (string->number (first expr)))
        (right (string->number (last expr))))
    (display (/ left right)))
  (newline))


(define basic-parser
  (parser

   (start start)
   (end NEWLINE EOF)
   (tokens value-tokens empty-tokens)
   (error (lambda (ok? name value)
            (printf "Couldn't parse: ~a\n" name)))

   (grammar

    (start ((expr) $1)
           ((expr start) $2))

    (expr ((INT PLUS INT) (display-plus (list $1 $3)))
          ((INT MINUS INT) (display-minus (list $1 $3)))
          ((INT MULTIPLY INT) (display-multiply (list $1 $3)))
          ((INT DIVIDE INT) (display-divide (list $1 $3)))
          ((ANY) (displayln $1))))))


(define input1 (open-input-string "123 + 456")) 
(define input2 (open-input-string "123 *456")) 


(basic-parser (lambda() (basic-lexer input1)))
(basic-parser (lambda() (basic-lexer input2)))



;(define (my-repl)
;    (display ">>> ")
;    (let* ((input (read-line))
;           (input-port (open-input-string
;                          (list->string
;                           (drop-right
;                            (string->list input) 1)))))
;      (cond
;        ((not (equal? "\r" input)
;              (print (basic-parser
;                      (lambda () (basic-lexer input-port))))))))
;    (my-repl))



(define (calc str)
  (let* ([port (open-input-string str)]
         [result (basic-parser (lambda() (basic-lexer port)))])
    (displayln result)))


(define (repl)
  (display ">>> ")
  (let ((input (read-line)))
    (print input)
    (cond
      ((eof-object? input)  (displayln "eof"))
      ((eq? input #\newline) (displayln "new line"))
      (else (calc (read-line))))
    (newline))
  (repl))

从DrRacket测试如下所示:

Welcome to DrRacket, version 7.1 [3m].
Language: racket, with debugging; memory limit: 512 MB.
Result: 579
Result: 56088
> (repl)
>>> 1+1
"1+1"2+2
Result: 4
#<void>

>>> 3+3
"3+3"4+4
Result: 8
#<void>

而从REPL:

Welcome to Racket v7.1.
> (require "untitled7.rkt")
Result: 579
Result: 56088
> (repl)
>>> "\r"

#<void>

>>> 1+1
"1+1\r"2+2
Result: 4

#<void>

>>> 3+3
"3+3\r"4+4
Result: 8

#<void>

>>> #<eof>eof

>>> ; user break [,bt for context]

它只显示每秒计算。看来,读行等待用户输入,这点我想请与(eof-object? input)(eq? input #\newline)但现在我得到的只有每秒结果之前返回一个新的生产线。

parsing scheme racket lex
2个回答
3
投票

有两个问题:

首先,你读一行,(let ((input (read-line))),但你不发送该输入到计算器,找你发送一个又一个 - (calc (read-line))

你应该通过inputcalc进行评估,而不是。

其次,你必须在你的输出了很多#<void>s的。

这是因为calc假设您的解析器产生价值,它可以打印:

(displayln result)

但是解析器不产生任何价值,只打印一个。 或者删除result的输出,或重写解析器的值返回到它的调用者。


3
投票

(calc (read-line))更换(calc input)

© www.soinside.com 2019 - 2024. All rights reserved.