如何在PyPEG中处理所有可能的C类块注释样式



放弃简约后,我尝试了PyPEG。我已经取得了更大的成功,因为我已经实现了最初的目标,但似乎不能正确处理注释。

我将问题提炼成以下代码:

您可以看到,不是所有的测试用例都工作,如果块注释之前有代码(testcase 4和5),那么生成的是一行而不是一个BlockComment。

是否有一种方法可以让PyPEG自己做这件事,或者我需要对行进行后处理以找到存在于多行中的BlockComments。

import pypeg2 as pp
import re
import pprint
nl = pp.RegEx(r"[rn]+")
symbols = ""-[]\!#$%&'()¬*+£,./:;<=>?@^_‘{|}~"
text = re.compile(r"[w" + symbols + "]+", re.UNICODE)

# Partial definition as we use it before it's fully defined
class Code(pp.List):
pass

class Text(str):
grammar = text

class Line(pp.List):
grammar = pp.maybe_some(Text), nl

class LineComment(Line):
grammar = re.compile(r".*?//.*"), nl

class BlockComment(pp.Literal):
grammar = pp.comment_c, pp.maybe_some(Text)

Code.grammar = pp.maybe_some([BlockComment, LineComment, Line])

comments = """
/*
Block comment 1
*/
// Line Comment1
Test2 // EOL Comment2
/*
Block comment 2*/
/* Block
comment 3 */
Test4 start /*
Block comment 4
*/ Test4 end
Test5 start /* Block comment 5 */ Test5 end
/* Block comment 6 */
"""
parsed = pp.parse(comments, Code, whitespace=pp.RegEx(r"[ t]"))
pprint.pprint(list(parsed))

您的text模式也将匹配注释;由于它是贪婪地应用的,所以除非注释恰好在一行的开头,否则它是不可能匹配的。因此,您需要确保在遇到注释分隔符时匹配停止。

你可以试着这样做:

# I removed / from the list.
symbols = ""-[]\!#$%&'()¬*+£,.:;<=>?@^_‘{|}~"
text = re.compile(r"([w" + symbols + "]|/(?![/*]))+", re.UNICODE)

尽管我不得不说symbols的列表对我来说似乎有些武断。我应该直接用

text = re.compile(r"([^/rn]|/(?![/*]))+", re.UNICODE)

最新更新