You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

扩展SLLGEN的Scheme语法时嵌套列表解析错误的解决求助

问题描述

我是Scheme语言新手,尝试扩展EoPL开发者提供的原始SLLGEN的语法规则,以支持解释器识别嵌套列表。我在lang.scm中添加了如下语法规则:

(expression 
  ("cons" "("
          (arbno expression (arbno",")) 
          ")")        
  lst-exp)

同时在interp.scm中添加了适配函数。平级列表运行正常,但嵌套列表出现问题,例如执行命令:

(run "cons (1 ,cons(3 2))")

时,Racket解释器报错:

*cases: not a expval: (3 2)*

看起来解释器未将“3”和“2”识别为数字,而是将整个表达式视为字符串。附上data-structure.scm中相关的expval数据类型定义:

(define-datatype expval expval?
  (num-val
    (value number?))
  (bool-val
    (boolean boolean?))
  (lst-val
   (lst pair?)))
问题分析

当前语法规则中的(arbno expression (arbno","))存在逻辑错误:

  • 该规则会匹配一个表达式后跟任意多个逗号的重复模式,无法正确识别用单个逗号分隔的多个表达式。比如嵌套调用cons(3 2)里没有逗号时,语法解析会把(3 2)当成一个整体,而非两个独立的表达式。
  • SLLGEN内置的separated-list才是处理分隔符分隔元素列表的正确工具,专门用于实现逗号分隔的表达式列表场景。
解决方案

1. 修改lang.scm中的语法规则

将原cons表达式语法替换为separated-list版本:

(expression 
  ("cons" "("
          (separated-list expression ",") 
          ")")        
  lst-exp)

separated-list expression ","会正确识别用单个逗号分隔的多个表达式,包括嵌套的cons调用,同时支持列表末尾无逗号的写法。

2. 修正interp.scm中的lst-exp处理函数

确保处理函数对每个子表达式求值,再将结果组成合法列表并包装为lst-val:

(define (eval-exp exp env)
  (cases expression exp
    ;; ... 其他表达式处理规则 ...
    (lst-exp (exps)
      (lst-val (map (lambda (e) (expval->value (eval-exp e env))) exps)))
    ;; ...
    ))

;; 辅助函数:提取expval中的实际值
(define (expval->value v)
  (cases expval v
    (num-val (num) num)
    (bool-val (bool) bool)
    (lst-val (lst) lst)
    (else (error "Unknown expval type"))))

核心逻辑:

  • 对每个子表达式e调用eval-exp求值,得到expval类型结果。
  • 用expval->value提取出实际值(数字、布尔值或列表)。
  • 用map将所有值组成列表,再包装为lst-val。

3. 修正测试输入的语法

测试输入中嵌套的cons(3 2)缺少逗号,应改为cons(3 , 2),正确的测试命令为:

(run "cons (1 , cons(3 , 2))")
验证

修改后,解释器会正确解析嵌套表达式:

  • 先求值3得到num-val 3,2得到num-val 2,组成列表(3 2)并包装为lst-val。
  • 再将1的num-val和嵌套列表的lst-val组成新列表(1 (3 2)),最终返回对应的lst-val。

内容的提问来源于stack exchange,提问作者DBM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 19:27:33