我正在Ruby中编写一个递归下降解析器,它使用regexp来匹配终端。终端实际上是regexp,并与字符串中的当前位置匹配。
问题是终端正则表达式可以包含任何内容,包括匹配换行符的正则表达式。例如,匹配括号/\([^\)]*\)/
之间的任何内容的终端将消耗空格,包括我需要计算的换行符。我想出了几个解决方案,但它们都有我不喜欢的缺点:
每当匹配终端时,计算匹配中\n
的所有出现次数。这实际上意味着每个字符串匹配两次而不是一次,
我可以存储字符串的当前位置,而不是存储当前行,只有在需要时才能通过遍历字符串获取行号和列号。显然有问题,因为每次需要行号时都会遍历整个字符串。
我没有允许regexp作为终端,而是允许更简单的匹配器形式,类似于ANTLR允许的,然后手动匹配字符串,计算换行符。但是,它不需要额外的工作量,也不会损失正则表达式的匹配能力。
我倾向于第三种解决方案,但是我想看看是否有人处理过类似的问题并且有更好的解决方案可以省去我的麻烦。
答案 0 :(得分:1)
您可以使用解决方案2,但使用源文件的“行索引”。
您进行第一阶段以获得行开始的位置数组。然后,您可以通过二分搜索获得O(log n)中位置的行号(n是行数)。
顺便说一下,它会让你知道在O(1)上知道pos - lines_start[line]
的行中的位置,这对于非常微不足道的代码行的错误报告是很宝贵的。