我试图在使用pyparsing时获取字符串中的标记位置。我想报告C文件中包含保护问题的位置:
import pyparsing as pp
m = None
n = None
#a sample C header file
lines = "
#ifndef HEADER_FILE_Hn
#define HEADER_FILE_H 1n
n
n
/* code is here */n
n
#endif /* HEADER_FILE_H */
"
LBRACE,RBRACE,LBRACK,RBRACK,LT,GT,LPAREN,RPAREN,DQ,SEMI = map(pp.Suppress,'{}[]<>()";')
CIDENT = pp.Word(pp.alphanums + "_") #any C identifier
LCOMMENT = pp.Suppress("/*")
RCOMMENT = pp.Suppress("*/")
last_line = lines.split("n")[-1] #get last line
pound = pp.Literal("#") + pp.Suppress(pp.Optional(pp.White(" t")))
ifndef = pound + pp.Literal("ifndef")
ifnotdefined = pound + pp.Literal("if") + pp.Literal("!defined")
define = pound + pp.Literal("define")
endif = pound + pp.Literal("endif")
comment = pp.Optional(LCOMMENT + CIDENT("guardname_endif") + RCOMMENT)("guard_end_comment")
includeguardifndef = pp.Or([ifndef, ifnotdefined]) + pp.Optional(LPAREN) + CIDENT("guardname_ifndef_val") + pp.Optional(RPAREN)
includeguard = define + CIDENT("guardname_define_val") + pp.Optional(pp.Literal("1")("guard_is_one"))
includeguard_top = includeguardifndef + includeguard
includeguardendif = endif("includeguardendif") + comment
try:
m = includeguard_top.parseString(lines)
except pp.ParseException:
pass
try:
n = includeguardendif.parseString(last_line)
except pp.ParseException:
pass
print(m)
print(n)
现在,当我得到我的匹配"m"时,我可以得到m.guardname_define_value,最终我想得到类似m.guardname _define_value.pos的东西,这是匹配在"行"中的位置。
我想到了这个问题,这让我几乎做到了,但我不知道如何仍然使用令牌获得命名范围?我不想在比赛结束时用神奇的数字来获得位置。
我对regex并不陌生,但我是pyparsing的新手,对它的强大和清晰感到非常惊讶。真的很喜欢它。如果有人对我上面所做的事情提出建议,我也会接受。
- 主要问题是获得带有命名结果的令牌位置,而不是使用幻数。例如:我不想做一些像
m.guardname_define_value[0][0]
这样神秘的事情来获得这个职位 - 我是否需要像上面所做的那样尝试/捕获pp.ParseException?如果我不这样做,我会得到一个例外。我真的不在乎比赛是否失败,我只是检查结果是否为"无">
- 我想nestedExpr可能会做我想做的事情,但更好的一步是,我可以自动让它查找神奇匹配的
#ifdef ... #endif
?(如果开启符是"#ifdef",关闭符是"#endif"?( - 在不太贪婪的情况下,说"寻找任何东西"的正确方式是什么?也就是说,这个regex:
".*(FOO).*"
会消耗和丢弃任何东西,直到它找到并捕获FOO,然后消耗和丢弃它之后的任何东西,我很难复制它
谢谢。
这是您的示例代码,稍作修改。(我真的不喜欢反斜杠,当在脚本中嵌入文本示例时,你可能会发现使用三引号更容易。(值得注意的是,我展示了locatedExpr
的使用。这可能是你真正想看到的。另外,请参阅这个SO问题:Pyparsing:在结果名称中获取令牌位置
import pyparsing as pp
#a sample C header file
lines = """
#ifndef HEADER_FILE_H
#define HEADER_FILE_H 1
/* code is here */
#endif /* HEADER_FILE_H */
"""
LBRACE,RBRACE,LBRACK,RBRACK,LT,GT,LPAREN,RPAREN,DQ,SEMI = map(pp.Suppress,'{}[]<>()";')
CIDENT = pp.Word(pp.alphas + "_", pp.alphanums + "_") #any C identifier
LCOMMENT = pp.Suppress("/*")
RCOMMENT = pp.Suppress("*/")
def make_directive(s, pound=pp.Literal("#")):
return pp.Combine(pound + s, adjacent=False)
ifndef = make_directive("ifndef")
ifnotdefined = make_directive("if") + pp.Literal("!defined")
define = make_directive("define")
endif = make_directive("endif")
comment = pp.Optional(LCOMMENT
+ CIDENT("guardname_endif")
+ RCOMMENT)("guard_end_comment")
includeguardifndef = ((ifndef | ifnotdefined)
+ pp.Optional(LPAREN)
+ CIDENT("guardname_ifndef_val")
+ pp.Optional(RPAREN))
includeguard = (define
+ CIDENT("guardname_define_val")
+ pp.Optional(pp.Literal("1")("guard_is_one")))
includeguard_top = includeguardifndef + includeguard
includeguardendif = endif("includeguardendif") + comment
# parse the header
parser = includeguard_top + pp.SkipTo(includeguardendif).suppress() + includeguardendif
print(parser.parseString(lines).dump())
# parse the header, with locns
loc = pp.locatedExpr
parser = loc(includeguard_top) + pp.SkipTo(includeguardendif).suppress() + loc(includeguardendif)
print(parser.parseString(lines).dump())
打印:
['#ifndef', 'HEADER_FILE_H', '#define', 'HEADER_FILE_H', '1', '#endif', 'HEADER_FILE_H']
- guard_end_comment: ['HEADER_FILE_H']
- guard_is_one: '1'
- guardname_define_val: 'HEADER_FILE_H'
- guardname_endif: 'HEADER_FILE_H'
- guardname_ifndef_val: 'HEADER_FILE_H'
- includeguardendif: '#endif'
[[1, '#ifndef', 'HEADER_FILE_H', '#define', 'HEADER_FILE_H', '1', 46], [69, '#endif', 'HEADER_FILE_H', 95]]
[0]:
[1, '#ifndef', 'HEADER_FILE_H', '#define', 'HEADER_FILE_H', '1', 46]
- guard_is_one: '1'
- guardname_define_val: 'HEADER_FILE_H'
- guardname_ifndef_val: 'HEADER_FILE_H'
- locn_end: 46
- locn_start: 1
- value: ['#ifndef', 'HEADER_FILE_H', '#define', 'HEADER_FILE_H', '1']
[1]:
[69, '#endif', 'HEADER_FILE_H', 95]
- guard_end_comment: ['HEADER_FILE_H']
- guardname_endif: 'HEADER_FILE_H'
- includeguardendif: '#endif'
- locn_end: 95
- locn_start: 69
- value: ['#endif', 'HEADER_FILE_H']