是否存在基于行级字符串Token而非字符的Scala解析解决方案?
解决方案
你可以直接使用FastParse的序列解析能力实现需求,无需在语法规则中处理换行,所有换行符仅在预分词阶段处理即可,完整实现如下:
实现步骤
1. 预分词处理
先把原始输入按换行符拆分,得到每行内容组成的序列,换行符在此步骤完全处理,不会进入后续解析逻辑:
// 原始输入示例 val rawInput = """Pizza Is Great 12 14 17 red blue buckle my shoe PS. I <3 🐈🐈🐈""" // 按行拆分得到Token序列,每个元素对应原始输入的一行 val lineTokens = rawInput.split("\\R", -1).toSeq // \\R匹配任意类型换行符,-1参数保留末尾空行
2. 定义解析规则
完全和你给出的伪代码逻辑对齐,不需要任何换行相关的处理:
import fastparse._ import fastparse.NoWhitespace._ // 匹配非空文本行 def text[_: P] = P(AnyChar.!.filter(_.nonEmpty)) // 匹配纯数字行 def int[_: P] = P(CharsWhileIn("0-9").!.map(_.toInt)) // 匹配空行 def blank[_: P] = P(AnyChar.!.filter(_.isEmpty)) // 完整文档解析规则,和伪代码定义完全一致 def Document[_: P] = P( text ~ blank ~ int.rep ~ blank ~ text.rep ~ blank ~ text ~ End )
3. 执行解析
直接把拆分好的行序列作为输入传入解析器即可:
val parseResult = parse(lineTokens, Document(_)) // 解析成功会返回结构化结果:(首行文本, 数字列表, 中间文本行列表, 末尾文本行)
方案说明
- 所有换行处理仅在预分词阶段完成,语法规则里完全不需要感知换行的存在
- 每个Token对应原始输入的一行,完全符合你的需求
- 若你更倾向使用scala-parser-combinators,也可以将输入封装为行序列的Reader实现相同效果
内容的提问来源于stack exchange,提问作者Sasgorilla
相关产品推荐
相关产品推荐

