Python 使用命名值通过pyparsing获取字符串中的标记位置
我试图在使用pyparsing时获取字符串中的标记位置。我想在C文件中报告include guard问题的位置:Python 使用命名值通过pyparsing获取字符串中的标记位置,python,pyparsing,Python,Pyparsing,我试图在使用pyparsing时获取字符串中的标记位置。我想在C文件中报告include guard问题的位置: import pyparsing as pp m = None n = None #a sample C header file lines = "\ #ifndef HEADER_FILE_H\n\ #define HEADER_FILE_H 1\n\ \n\ \n\ /* code is here */\n\ \n\ #endif /* HEADER_FILE_H */\ "
import pyparsing as pp
m = None
n = None
#a sample C header file
lines = "\
#ifndef HEADER_FILE_H\n\
#define HEADER_FILE_H 1\n\
\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)
将pyparsing导入为pp
m=无
n=无
#示例C头文件
行=”\
#ifndef头文件\u H\n\
#定义头文件\u H 1\n\
\n\
\n\
/*代码在这里*/\n\
\n\
#endif/*头文件*/\
"
LBRACE,RBRACE,LBRACK,RBRACK,LT,GT,LPAREN,RPAREN,DQ,SEMI=map(pp.Suppress,“{}[]”(“;”)
CIDENT=pp.Word(pp.alphanums+“”)#任何C标识符
LCOMMENT=pp.Suppress(“/*”)
RCOMMENT=pp.Suppress(“*/”)
最后一行=行。拆分(“\n”)[-1]#获取最后一行
pound=pp.Literal(“#”)+pp.Suppress(pp.Optional(pp.White(“\t”))
ifndef=磅+pp.Literal(“ifndef”)
ifnotdefined=pound+pp.Literal(“如果”)+pp.Literal(“定义”)
定义=磅+pp.Literal(“定义”)
endif=磅+pp.Literal(“endif”)
注释=pp.可选(LCOMMENT+CIDENT(“guardname\u endif”)+RCOMMENT)(“guard\u end\u comment”)
includeguardifndef=pp.Or([ifndef,ifnotdefined])+pp.Optional(LPAREN)+CIDENT(“guardname\u ifndef\u val”)+pp.Optional(RPAREN)
includeguard=define+CIDENT(“guardname\u define\u val”)+pp.Optional(pp.Literal(“1”)(“guard\u是一个”))
includeguard\U top=includeguardifndef+includeguard
includeguardendif=endif(“includeguardendif”)+注释
尝试:
m=includeguard\u top.parseString(行)
除pp.ParseException外:
通过
尝试:
n=includeguardendif.parseString(最后一行)
除pp.ParseException外:
通过
打印(m)
打印(n)
现在,当我得到匹配项“m”时,我可以得到m.guardname\u define\u value,最终我想要得到类似于m.guardname\u define\u value.pos的东西,这是匹配项在“行”中的位置
我做到了这一点,这让我几乎达到了目标,但我不知道如何仍然用标记获得命名范围?我不想在比赛结束时使用幻数获得位置
我对regex并不陌生,但我对pyparsing还不熟悉,对它的强大和清晰感到非常惊讶。真的很喜欢它。如果有人对我上面所做的事情提出建议,我也会接受
m.guardname\u define\u value[0][0]
之类的神秘操作来获取位置#ifdef…#endif
(如果opener是'#ifdef',closer是'#endif'?)“*(FOO)。*”
会消耗并丢弃任何东西,直到找到并捕获FOO,然后再消耗并丢弃任何东西,我很难复制它谢谢。这是您的示例代码,稍作修改。(我真的不喜欢反斜杠,在脚本中嵌入文本示例时,您可能会发现使用三重引号更容易。)值得注意的是,我展示了
locatedExpr
的用法。这可能是您真正想看到的。另外,请参见以下问题:
1.通常,语法中不必包含
White
元素,pyparsing会隐式跳过空格。2.代码示例未运行,您遗漏了一些位,如LCOMMENT和RCOMMENT。(您还可以查看一些预定义的注释表达式,如cStyleComment
和cppStyleComment
)3.您可以包括一些您试图解析的文本吗?4.搜索任何内容"可能是使用SkipTo处理的,不确定您正在解析什么。5.很高兴听到您的pyparsing体验是积极的,尽管存在一些挑战!谢谢@PaulMcG,我已经更新了一个更完整的示例,应该可以运行感谢@PaulMcG,我已经让它工作了,但我将仔细看看您在这里做了什么,并看看如何改进w我做了什么!
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']