中缀表达式计算器球拍

时间:2016-05-07 12:02:23

标签: racket typed-racket

所以我得到了这段代码:

#lang pl

  #| BNF for the AE language:
     <AE> ::= <num>
            | { + <AE> <AE> }
            | { - <AE> <AE> }
            | { * <AE> <AE> }
            | { / <AE> <AE> }
  |#

  ;; AE abstract syntax trees
  (define-type AE
    [Num Number]
    [Add AE AE]
    [Sub AE AE]
    [Mul AE AE]
    [Div AE AE])

  (: parse-sexpr : Sexpr -> AE)
  ;; to convert s-expressions into AEs
  (define (parse-sexpr sexpr)
    (match sexpr
      [(number: n) (Num n)]
      [(list '+ lhs rhs)
       (Add (parse-sexpr lhs) (parse-sexpr rhs))]
      [(list '- lhs rhs)
       (Sub (parse-sexpr lhs) (parse-sexpr rhs))]
      [(list '* lhs rhs)
       (Mul (parse-sexpr lhs) (parse-sexpr rhs))]
      [(list '/ lhs rhs)
       (Div (parse-sexpr lhs) (parse-sexpr rhs))]
      [else
      (error 'parse-sexpr "bad syntax in ~s" sexpr)]))

  (: parse : String -> AE)
  ;; parses a string containing an AE expression to an AE AST
  (define (parse str)
    (parse-sexpr (string->sexpr str)))

  (: eval : AE -> Number)
  ;; consumes an AE and computes the corresponding number
  (define (eval expr)
    (cases expr
      [(Num n)   n]
      [(Add l r) (+ (eval l) (eval r))]
      [(Sub l r) (- (eval l) (eval r))]
      [(Mul l r) (* (eval l) (eval r))]
      [(Div l r) (/ (eval l) (eval r))]))

  (: run : String -> Number)
  ;; evaluate an AE program contained in a string
  (define (run str)
    (eval (parse str)))

您可以使用run (+ 3 5)进行测试和运行,然后您将获得8。

我的任务是更改代码,以便我可以run (3 + 5)

所以我改变了自己构建树的parse-sexpr函数:

  (: parse-sexpr : Sexpr -> AE)
  ;; to convert s-expressions into AEs
  (define (parse-sexpr sexpr)
    (match sexpr
      [(number: n) (Num n)]
      [(list lhs '+ rhs)
       (Add (parse-sexpr lhs) (parse-sexpr rhs))]
      [(list lhs '- rhs)
       (Sub (parse-sexpr lhs) (parse-sexpr rhs))]
      [(list lhs '* rhs)
       (Mul (parse-sexpr lhs) (parse-sexpr rhs))]
      [(list lhs '/ rhs)
       (Div (parse-sexpr lhs) (parse-sexpr rhs))]
      [else
      (error 'parse-sexpr "bad syntax in ~s" sexpr)]))

我仍然可以编译代码,但如果我会run (+ 5 3)我会得到8,如果我尝试run (5 + 3)我得到:

  

Type Checker:不能应用Positive-Byte类型的表达式,因为   它不是函数类型:(5 + 3)

为什么会发生这种情况?

2 个答案:

答案 0 :(得分:1)

你有没有写过

 (run (+ 5 3))

而不是

 (run '(+ 5 3))

如果你写(run (+ 5 3)),那么Racket将首先计算(+ 5 3),然后拨打(run 8)。如果您编写(run (5 + 3)),那么Racket将尝试评估(5 + 3),并且会出现您看到的错误:数字5不是函数类型,因此无法用作(5 ...) 1}}

答案 1 :(得分:1)

这是类型球拍中表达式的问题,而不是您的语言中的表达式。在您的语言中,(5 + 3)是一个表达式,但在键入的球拍中,这是一个类型错误。因此,您需要在键入的球拍中将(5 + 3)表示为数据

正如@soegaard指出的那样,一种常见的方法是将quote放在前面,如下所示:'(5 + 3)。虽然我讨厌这样写。 真正的含义是(list 5 '+ 3)。因此,您可以将其传递给新的parse-sexpr函数以获取

> (parse-sexpr (list 5 '+ 3))
- : AE
(Add (Num 5) (Num 3))

然后您可以将该值传递给eval函数以获取

> (eval (Add (Num 5) (Num 3)))
- : Number
8

组成:

> (eval (parse-sexpr (list 5 '+ 3)))
- : Number
8

但是您的run函数接受一个字符串,将其传递给string->sexpr,然后将其传递给parse-sexpr,然后传递给eval函数。所以你一直想做的就是:

> (eval (parse-sexpr (string->sexpr "{5 + 3}")))
- : Number
8
> (run "{5 + 3}")
- : Number
8

假设string->sexpr采用类似花括号的表达式。您正在做的是(run (5 + 3)),它将(5 + 3)视为类型化的球拍表达式。您想要的是(run "{5 + 3}"),它将(5 + 3)视为您所用语言的表达式,在表格中表示为数据。