如何根据缩进解析代码块
我正在写一个工具,用来把类似Markdown的标记语言转换成HTML。我已经完成了大部分代码,除了有序和无序列表的转换部分。我想根据空格的数量来格式化列表(也就是所谓的“缩进规则”)。有效的输入示例如下:
:: List item
top level
:: List item level 2
:: List item level 2
:: List item level 3
:: List item level 4
:: List item level 2
:: List item top level
::
表示一个列表项。缩进的层级可以是任意的。制表符不算在内。我在纸上写了一些解决方案,但我还是没找到实现的方法。我该怎么做呢?
补充说明:只要空格超过一个,任何数量的空格就表示一个新的层级,就像在Python中那样。
我用Python来实现这个工具,但我不想要代码。我想要的是如何去做的解释。而且我希望自己能完整实现,不依赖任何库。我打算把这个标记语言用在我的Jekyll博客上,但这对我来说不仅仅是一个小工具,我想通过这个项目尽可能多地学习正则表达式和解析的知识。提前谢谢你们。
2 个回答
0
这不是一个答案,但我需要块格式。
这个列表应该解析成什么级别呢?
:: List item level
:: List item level ?
:: List item level ?
:: List item level ?
:: List item level ?
:: List item level ?
我觉得你在处理一些在列表中没有意义的特殊情况,其实你应该告诉用户写一些更合理的内容。
3
@delnan 提到的 Python 参考文档 提供了一种不错的方法,但正如文档所说,Python 允许的缩进方式虽然是正确的,但有时候会让人看得很困惑。而且如果你试图充分利用这种灵活性,可能会在调试时遇到麻烦。
为了你的应用,如果你要求每种不同数量的缩进空格表示不同的列表层级,可能会让用户更容易理解。用 Python 3,你可以在不超过四行的代码中找到列表的层级。虽然你不想看到代码解决方案(不过如果你想要,我很乐意分享),但我的大致思路是这样的:
- 计算列表中每行开头的空格数量(这不需要使用正则表达式)。
- 创建一个集合并对其进行排序,以列出每个层级使用的缩进空格数量,从少到多排列。
- 创建一个字典,将每种情况下使用的缩进空格数量与列表层级关联起来。
- 使用列表中每行开头的空格数量来查找这个字典,从而得到每行的列表层级。
(已编辑以包含代码并处理多行列表项)
给定:
:: List item
(this is the second line of the first list item)
:: List item level 2
:: List item level 2
:: List item level 3
:: List item level 4
:: List item level 2
:: List item top leve
... 下面的函数生成了这个列表:
:: List item (this is the second line of the first list item)
:: List item level 2
:: List item level 2
:: List item level 3
:: List item level 4
:: List item level 2
:: List item top level
... 我认为这是这个测试案例的预期结果。
以下是代码,设计为从标准输入接收列表:
import sys
def findIndent (lst):
# given a list of text strings, returns a list containing the
# indentation levels for each string
spcCount = [len(s)-len(s.lstrip(' ')) for s in lst]
indent = sorted(set(spcCount))
levelRef = {indent[i]:i for i in range(len(indent))}
return [levelRef[i]+1 for i in spcCount]
lst = []
for li in sys.stdin:
if li.lstrip(' ').find('::') == 0:
lst.append(li.rstrip())
else:
lst[-1] = lst[-1].rstrip() + ' ' + li.lstrip(' ').rstrip()
for i,li in zip(findIndent(lst),lst):
print (' '*i + li.lstrip())