Я пытаюсь написать переводчик для схемы. До сих пор я реализовал определение, если и некоторые арифметические выражения. Вот грамматика для моего переводчика:Применение «let» в схеме?
<s6> -> <expr>
| <define>
<expr> -> NUMBER
| IDENT
| <if>
| <let>
<define> -> (define IDENT <expr>)
<if> -> (if <expr> <expr> <expr>)
<let> -> (let (<var_binding_list>) <expr>)
<var_binding_list> -> (IDENT <expr>) <var_binding_list>
| (IDENT <expr>)
Вот код я написал до сих пор:
(define get-operator (lambda (op-symbol)
(cond
((equal? op-symbol '+) +)
((equal? op-symbol '-) -)
((equal? op-symbol '*) *)
((equal? op-symbol '/) /)
(else (error "s6-interpret: operator not implemented -->" op-symbol)))))
(define let-stmt? (lambda (e)
(and (list? e) (equal? (car e) 'let) (= (length e) 3))))
(define if-stmt? (lambda (e)
(and (list? e) (equal? (car e) 'if) (= (length e) 4))))
(define define-stmt? (lambda (e)
(and (list? e) (equal? (car e) 'define) (symbol? (cadr e)) (= (length e) 3))))
(define get-value (lambda (var env)
(cond
((null? env) (error "s6-interpret: unbound variable -->" var))
((equal? (caar env) var) (cdar env))
(else (get-value var (cdr env))))))
(define extend-env (lambda (var val old-env)
(cons (cons var val) old-env)))
(define repl (lambda (env)
(let* (
(dummy1 (display "cs305> "))
(expr (read))
(new-env (if (define-stmt? expr)
(extend-env (cadr expr) (s6-interpret (caddr expr) env) env)env))
(val (if (define-stmt? expr)
(cadr expr)
(s6-interpret expr env)))
(dummy2 (display "cs305: "))
(dummy3 (display val))
(dummy4 (newline))
(dummy4 (newline)))
(repl new-env))))
(define s6-interpret (lambda (e env)
(cond
((number? e) e)
((symbol? e) (get-value e env))
((not (list? e)) (error "s6-interpret: cannot evaluate -->" e))
((if-stmt? e) (if (eq? (cadr e) 0) (s6-interpret (cadddr e) env) (s6-interpret(caddr e) env)))
((let-stmt? e) (apply let (map s6-interpret (cdr e))))
(else
(let ((operands (map s6-interpret (cdr e) (make-list (length (cdr e)) env)))
(operator (get-operator (car e))))
(apply operator operands))))))
(define cs305-interpreter (lambda() (repl '())))
Все, что я написал, кроме «пусть» отлично работает. пусть-STMT? процедура также работает, как я хочу, но часть кода ((let-stmt? e) (применить let (map s6-interp (cdr e)))) в s6-интерпретации не работает нормально, это дает мне ошибку, говоря что «синтаксическое ключевое слово не может использоваться как выражение». Может ли кто-нибудь помочь мне с внедрением интерпретатора для выражения «let», как указано в грамматике?
Спасибо
Можете ли вы перекомпостировать после того, как вы получите выше, чтобы скомпилировать и запустить без ошибки счетчика аргументов? – GoZoner
@GoZoner хорошо, на самом деле я все еще думаю о том, как реализовать оператор let, я не мог его решить. Вы имеете в виду перепрограммирование после его решения? – yrazlik
Так же, как вы не можете подать заявку, если вы не можете применить let. let на самом деле просто синтаксический сахар для анонимной процедуры, поэтому сначала вы должны реализовать лямбда-вызовы, например ((lambda (x) x) 5), чтобы оценить значение 5. Тогда вы можете реализовать так, чтобы (let ((x 5)) x) является синонимом этого. – Sylwester