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

自制编程语言编译器:识别变量路径并生成树构建指令

解决变量路径识别与指令序列生成的方案

核心思路:基于状态机的路径解析

既然你的语言是缩进语法(类似CoffeeScript)且已实现词法令牌流,可通过状态机模式跟踪变量路径的构建过程,同步输出对应指令。

定义解析状态

先明确几个关键状态:

  • START:初始状态,等待路径起始标识符
  • IN_PATH:正在解析变量路径,处理.、[等嵌套符号
  • IN_BRACKET:处于方括号内的索引表达式(如[baz])
  • PATH_END:路径结束,准备输出终止指令

令牌类型映射

先将词法输出的令牌归类,方便后续判断:

  • IDENTIFIER:标识符(如foo、bar)
  • DOT:.
  • LBRACKET:[
  • RBRACKET:]
  • INDENT:缩进
  • DEDENT:缩进减少
  • NEWLINE:换行
  • OPERATOR:运算符(如=、+)
  • SEPARATOR:分隔符(如,)

状态流转与指令生成逻辑

以解析foo.bar[baz].hello[and][goodday].there为例,详细说明流转过程:

  1. 遇到第一个IDENTIFIER(foo):
    • 输出term-start(foo)
    • 状态切换为IN_PATH,路径层级+1
  2. 遇到DOT:
    • 不输出指令,保持IN_PATH状态,等待下一个标识符
  3. 遇到IDENTIFIER(bar):
    • 输出term-nest(bar)(表示嵌套在foo下的子项)
    • 保持IN_PATH状态,路径层级+1
  4. 遇到LBRACKET:
    • 输出term-bracket-start
    • 状态切换为IN_BRACKET
  5. 遇到IDENTIFIER(baz):
    • 输出term-index(baz)
    • 保持IN_BRACKET状态
  6. 遇到RBRACKET:
    • 输出term-bracket-end
    • 状态切回IN_PATH
  7. 后续.hello、[and]等重复上述逻辑,直到触发路径终止条件
  8. 路径终止的判断场景:
    • 遇到INDENT/DEDENT:缩进变化说明当前路径属于其他块,输出term-nest-end
    • 遇到NEWLINE+非缩进令牌:换行后开启新语句,输出term-nest-end
    • 遇到OPERATOR/SEPARATOR:比如foo.bar = 123中的=,说明路径是赋值左值,输出term-nest-end

缩进语法的特殊处理

因为是缩进驱动的语法,需额外注意:

  • 缩进增加时,若当前处于路径解析状态,必须先结束当前路径,再处理块的开启
  • 缩进减少时,需闭合所有未终止的路径嵌套,对应输出term-nest-end或term-bracket-end

伪代码实现示例

current_state = "START"
path_stack = []  # 用栈替代层级计数,更精准跟踪嵌套结构

for token in token_stream:
    if current_state == "START":
        if token.type == "IDENTIFIER":
            emit(f"term-start({token.value})")
            path_stack.append("dot")
            current_state = "IN_PATH"
    elif current_state == "IN_PATH":
        if token.type == "DOT":
            continue
        elif token.type == "IDENTIFIER":
            emit(f"term-nest({token.value})")
            path_stack.append("dot")
        elif token.type == "LBRACKET":
            emit("term-bracket-start")
            path_stack.append("bracket")
            current_state = "IN_BRACKET"
        elif token.type in ["INDENT", "DEDENT", "NEWLINE", "OPERATOR", "SEPARATOR"]:
            # 结束当前路径,逐层输出终止指令
            while path_stack:
                nested_type = path_stack.pop()
                emit("term-nest-end" if nested_type == "dot" else "term-bracket-end")
            current_state = "START"
            # 处理当前非路径令牌
            process_non_path_token(token)
    elif current_state == "IN_BRACKET":
        if token.type == "IDENTIFIER":
            emit(f"term-index({token.value})")
        elif token.type == "RBRACKET":
            emit("term-bracket-end")
            path_stack.pop()
            current_state = "IN_PATH"
        elif token.type in ["NEWLINE", "INDENT", "DEDENT"]:
            # 非法语法,强制终止并抛出错误
            emit("term-bracket-end")
            while path_stack:
                emit("term-nest-end" if path_stack.pop() == "dot" else "term-bracket-end")
            current_state = "START"
            process_error("Unexpected token inside bracket expression")

验证与调试技巧

  • 同时打印令牌流和生成的指令序列,逐行对比定位遗漏或错误的指令
  • 编写复杂路径测试用例,比如a[b.c].d[e][f.g],验证嵌套逻辑的正确性
  • 用栈结构跟踪路径层级,比单纯的计数变量更能精准处理嵌套关系

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:30:42