我正在尝试从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>
而从代表:
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]
它仅显示每秒的计算。看来,在等待用户输入之前,read-line返回了新行,我尝试使用(eof-object? input)
和(eq? input #\newline)
进行检查,但是现在我只得到每一秒钟的结果。
答案 0 :(得分:3)
有两个问题:
首先,您正在读取一行(let ((input (read-line)))
,但没有将输入发送到计算器,而是发送了另一行– (calc (read-line))
。
您应该将input
传递给calc
进行评估。
第二,您的输出中有很多#<void>
。
这是因为calc
假定您的解析器产生了可以打印的值:
(displayln result)
,但是解析器不产生任何值,它仅输出一个值。
要么删除result
的输出,要么重写解析器以将值返回给其调用者。