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

Yecc语法解析问题:将ChordPro文件转换为结构化数据

ChordPro转结构化数据的yecc解析问题解决方法

问题背景

用leex和yecc实现ChordPro文件转结构化数据,lexer生成的Token序列符合预期,但yecc解析器输出未达到目标格式,无法生成包含标题、创作者、和弦及歌词行的结构化Map,核心问题是对yecc的Token读取逻辑及语法规则推导机制理解不足。


示例ChordPro输入

@songexample """
{title:Take It Easy}
{st:Eagles}

Well I'm a [G]runnin' down the road try'n to loosen my load

I've got seven women [D]on my [C]mind

"""

当前yecc输出

{:ok,
 {:song,
  {:properties,
   [
     title: ~c"Take It Easy",
     st: ~c"Eagles",
     text: ~c"Well I'm a ",
     chord: ~c"[G]",
     text: ~c"runnin' down the road try'n to loosen my load",
     text: ~c"I've got seven women ",
     chord: ~c"[D]",
     text: ~c"on my ",
     chord: ~c"[C]",
     text: ~c"mind"
   ]}}}

期望输出格式

%{
      title: "Take it Easy",
      by: "Eagles",
      chords: ["G", "D", "C"],
      lines: [
        %{
          line: [
            %{
              linetype: "lyric",
              content: "Well I'm a"
            },
            %{
              linetype: "chord",
              content: "G"
            },
            %{
              linetype: "lyric",
              content: "runnin' down the road try'n to loosen my load"
            }
          ]
        },
        %{
          line: [
            %{
              linetype: "lyric",
              content: "I've got seven women"
            },
            %{
              linetype: "chord",
              content: "D"
            },
            %{
              linetype: "lyric",
              content: "on my"
            },
            %{
              linetype: "chord",
              content: "C"
            },
            %{
              linetype: "lyric",
              content: "mind"
            }
          ]
        }
      ]
    }

核心解决思路

1. 重构语法规则层级,区分元数据与歌词行

当前输出把所有内容混在properties里,说明语法规则没有分层。要明确划分结构:

  • 顶层规则:song -> metadata_section lyric_lines
  • metadata_section专门处理{key:value}格式的元数据指令,比如将{title:xxx}映射到title字段,{st:xxx}映射到by字段
  • lyric_lines处理多行歌词,每行对应一个line结构,包含交替的歌词和和弦片段

2. 优化Token处理细节

  • 和弦Token:在lexer或语法规则中移除[],直接提取内部和弦名(比如将[G]转为"G"),避免后续处理冗余符号
  • 文本与换行:lexer要识别换行符为LINE_END Token,用来分割歌词行,防止多行文本被合并成一个文本Token

3. 在语法动作中直接构建目标Map

  • 处理元数据时,将键值对转换为Map的键值(如st转by)
  • 处理每一行歌词时,收集交替的lyric和chord片段,构建成%{line: [...]},再将所有行存入lines数组
  • 同时收集所有和弦到chords数组中(可按需去重或按顺序存储)

4. 理解yecc的推导逻辑

  • yecc是LALR(1)解析器,规则要从高层到低层定义,先定义整体结构,再拆分细节
  • 规则优先级:元数据指令要优先于歌词行处理,避免把指令误判为文本
  • 结果聚合:在规则的动作部分({:ok, ...})要正确收集子规则的输出,比如把多行歌词用列表拼接,把元数据合并到同一个Map里

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:20:18