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

Scheme中使用sllgen解析自定义语法时caddr错误的解决方法

解决sllgen中try-catch-finally语法解析的caddr错误及列表操作问题

错误原因分析

你遇到的caddr错误,本质是试图对长度不足3的列表调用caddr。caddr等价于(car (cdr (cdr x))),要求输入列表至少有3个元素(即x是(a b c ...)的形式)。而错误信息里给出的参数是'(expression ("try" "{" expression "}" ... try-exp))——这个列表只有2个元素:第一个是符号expression,第二个是整个try语法的规则定义。显然你是误将语法规则本身当成了解析后的AST节点来操作,或者对解析后的AST结构判断错误。

语法定义的修正

先修正你的语法定义问题:

  1. 非终结符错误:你把异常类型的非终结符Except写成了字符串字面量"Except",这会导致解析器把[Except]中的Except当成固定字符串,而不是去匹配Except定义的异常类型。
  2. 语法规则不匹配规范:你的语法规范中catch块是catch [ Except ] : Expression ;,但当前规则里用:结尾,应该改成;;finally块的规则需确保和规范一致。

修正后的完整语法定义:

(expression
 ("try" "{" expression "}"
  (arbno "catch" "[" Except "]" ":" expression ";") 
  (arbno "finally:" expression ";") try-exp))

(Except
 ("general") Exception
 ("not a number") Exception
 ("not a boolean") Exception
 ("environment") Exception)

(expression
 ("throw" Except) throw-exp)

正确的列表操作方法

当sllgen解析生成AST后,try-exp节点的结构为(try-exp 主体表达式 catch子句列表 finally子句列表)。此时访问各部分的正确方式:

  • 主体表达式:(cadr try-exp-node)
  • catch子句列表:(caddr try-exp-node)(这里caddr合法,因为节点至少有4个元素)
  • finally子句列表:(cadddr try-exp-node)

更稳妥的实践

  1. 先确认AST结构:解析后打印AST,比如(display parsed-try-exp),直观看到节点的元素数量和顺序,避免凭想象操作。
  2. 用辅助函数替代直接调用caddr/cadddr:
    (define (try-exp-body te) (cadr te))
    (define (try-exp-catches te) (caddr te))
    (define (try-exp-finally te) (cadddr te))
    
    这样代码更可读,也不容易因结构变化出错。
  3. 使用模式匹配(如果用Racket):Racket的match可以更清晰地解构AST,避免手动列表操作:
    (match parsed-try-exp
      [`(try-exp ,body ,catches ,finally)
       (handle-try body catches finally)])
    

总结

  1. 先修正语法定义中的非终结符和规则匹配问题,确保解析出正确的AST结构。
  2. 区分语法规则定义和解析后的AST节点,不要对规则定义调用列表操作函数。
  3. 优先用辅助函数或模式匹配处理AST,减少直接使用caddr等函数带来的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:35:18