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

如何使用language-javascript模块遍历AST并提取字面量

解决方案

你可以借助Haskell的泛型编程能力自动遍历AST的所有子节点,无需手动为每个Statement、Expression构造子写匹配分支,常用的实现方式有两种:

方案1:基于Data.Data的泛型遍历(无额外依赖)

只要你使用的JS AST类型派生了Data和Typeable类(主流JS AST库如language-javascript默认都支持),就可以用base自带的泛型遍历能力实现:

  1. 首先导入依赖模块:
import Data.Data (Data, gmapQ, extQ)
import Data.Monoid (mconcat)
  1. 定义通用的全节点遍历函数,递归遍历所有子节点并聚合结果:
everything :: (Data a, Monoid m) => (a -> m) -> a -> m
everything f x = f x <> mconcat (gmapQ (everything f) x)
  1. 仅定义你需要的字面量匹配逻辑,不需要的节点直接返回空列表即可:
extractStrLiteral :: Data a => a -> [String]
extractStrLiteral = flip extQ [] $ \case
  -- 匹配字符串字面量,提取值
  JSStringLiteral _ str -> [str]
  -- 如果需要提取其他类型字面量,加对应分支即可
  -- JSNumberLiteral _ num -> [show num]
  -- 非目标节点返回空列表
  _ -> []
  1. 最终的literals函数实现非常简洁:
literals :: JSAST -> [String]
literals (JSAstProgram statements) = everything extractStrLiteral statements
literals _ = []

该实现会自动遍历所有嵌套节点:不管字面量在变量声明、数组、循环体还是函数调用中,都会被自动提取。

方案2:使用AST库自带的遍历接口

如果你使用的AST库提供了现成的语句/表达式折叠接口,直接复用接口即可,只需要实现表达式层面的字面量匹配逻辑,不需要处理语句的所有构造子:
比如假设库提供了foldStmt :: ([String] -> JSExpression -> [String]) -> JSStatement -> [String]这类折叠函数,你可以直接写:

literals (JSAstProgram statements) = concatMap (foldStmt extractFromExpr) statements
  where
    extractFromExpr acc expr = case expr of
      JSStringLiteral _ str -> str : acc
      JSArrayLiteral _ exprs _ -> concatMap (foldExpr extractFromExpr) exprs ++ acc
      _ -> acc

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:54:07