使用pyparsing使用类似Python的if块解析模板

使用pyparsing使用类似Python的if块解析模板,python,regex,parsing,abstract-syntax-tree,pyparsing,Python,Regex,Parsing,Abstract Syntax Tree,Pyparsing,我正在尝试用pyparsing解析一种简单的模板语言,它看起来有点像这样: 如果: 埃利夫: 如果: 其他: 其中的语句要么是带有有效Python代码的if块,要么是其他任何文本。如果字符串以“If”关键字开头,则表示它立即是If块。事实上,文本行也可以包含{variable}类型的插值,但仅此而已 此语法的完整有效示例: if a == b: do some {interpolation} stuff elif a.x > b.y: if True: some

我正在尝试用pyparsing解析一种简单的模板语言,它看起来有点像这样:

如果:
埃利夫:
如果:
其他:
其中的语句要么是带有有效Python代码的if块,要么是其他任何文本。如果字符串以“If”关键字开头,则表示它立即是If块。事实上,文本行也可以包含
{variable}
类型的插值,但仅此而已

此语法的完整有效示例:

if a == b: do some {interpolation} stuff
elif a.x > b.y:
    if True:
        some {more} interpolation
        and some more text
    else: foo {bar}
    arbitrary {text} here
lorem {ipsum}
为了检测Python表达式,我对
pyparsing.Token进行了子类化,它似乎可以工作:

导入ast
从pyparsing导入*
类PythonExpression(令牌):
名称='PythonExpression'
def parseImpl(self、s、loc、doActions=True):
max_loc=s.find('\n')如果'\n'在s else len中
最佳位置=无
对于范围内的n(位置+1,最大位置+1):
尝试:
tree=ast.parse(s[loc:n])
除:
持续
如果isinstance(树,ast.Module):
如果len(树体)为1:
如果isinstance(tree.body[0],ast.Expr):
最佳位置=n
如果最佳位置不是无:
返回最佳位置,s[位置:最佳位置]
引发解析异常(s,loc,“无效Python表达式”)
expr='if foo[1:bar:baz]==1:passqwe'
print(关键字('if')+PythonExpression()).parseString(expr.asList())
导致

['if','foo[1:“bar:baz”]==1']
但是,使用
pyparsing.indentedBlock
,我有点不知所措,似乎无法让它解析整个语法。我的最后一次尝试是这样的(注意,它只包含
if
语句实现;还有可选的
elif
else
块):

parseRelation.setDefaultWhitespaceChars('\t')
冒号=文字(':')。抑制()
if_子句=PythonExpression()+冒号
if_语句=组(关键字('if')+if_子句)
non_white=Regex(r'\S+')
任何东西=联合收割机(非白色+剩余线)
语句=转发()
缩进堆栈=[1]
if_块=组(if_语句+((任何内容)|缩进块(语句,缩进堆栈)))
other=~关键字('if')+任何内容

语句是沿着编译时宏行的插值模式,类似于C预处理器宏或运行时替换。如果与预处理器宏类似,请参见pyparsing wiki上的宏示例。如果它们是运行时的,那么您必须将它们的语法作为解析器的一部分。@PaulMcGuire感谢您的评论;我在原来的帖子中添加了一个简短的例子。我想如果我足够努力,我可以让它自己工作,但不能与整个缩进if块语法一起工作。@PaulMcGuire我还在文章顶部添加了一个完整的语法示例。@PaulMcGuire似乎仍然无法理解它。。。我唯一的希望就是你的建议:)