几天前考虑了一下,没有什么值得发的东西,我现在回到它,想出了一些我比较喜欢的语法,因为它几乎看起来像 python:
macro PrintMacro:
syntax:
"print", OneOrMore(Var(), name='vars')
return Printnl(vars, None)
内部语法表示也可能看起来相同:
class PrintMacro(Macro):
syntax = 'print', OneOrMore(Var(), name='vars')
...
内部语法类 likeOneOrMore
将遵循此模式以允许子项和可选名称:
class MacroSyntaxElement(object):
def __init__(self, *p, name=None):
self.subelements = p
self.name = name
当宏匹配时,您只需收集所有具有名称的项目并将它们作为关键字参数传递给处理函数:
class Macro():
...
def parse(self, ...):
syntaxtree = []
nameditems = {}
# parse, however this is done
# store all elements that have a name as
# nameditems[name] = parsed_element
self.handle(syntaxtree, **nameditems)
然后处理函数将被定义如下:
class PrintMacro(Macro):
...
def handle(self, syntaxtree, vars):
return Printnl(vars, None)
我将语法树添加为始终传递的第一个参数,因此如果您只想在语法树上执行非常基本的操作,则不需要任何命名项。
此外,如果您不喜欢装饰器,为什么不添加宏类型,如“基类”?IfMacro
然后看起来像这样:
macro IfMacro(MultiLine):
syntax:
Group("if", Var(), ":", Var(), name='if_')
ZeroOrMore("elif", Var(), ":", Var(), name='elifs')
Optional("else", Var(name='elseBody'))
return If(
[(cond, Stmt(body)) for keyword, cond, colon, body in [if_] + elifs],
None if elseBody is None else Stmt(elseBody)
)
在内部表示中:
class IfMacro(MultiLineMacro):
syntax = (
Group("if", Var(), ":", Var(), name='if_'),
ZeroOrMore("elif", Var(), ":", Var(), name='elifs'),
Optional("else", Var(name='elseBody'))
)
def handle(self, syntaxtree, if_=None, elifs=None, elseBody=None):
# Default parameters in case there is no such named item.
# In this case this can only happen for 'elseBody'.
return If(
[(cond, Stmt(body)) for keyword, cond, body in [if_] + elifs],
None if elseNody is None else Stmt(elseBody)
)
我认为这将提供一个非常灵活的系统。主要优点:
- 易于学习(看起来像标准 python)
- 易于解析(像标准 python 一样解析)
- 可以轻松处理可选项目,因为您可以
None
在处理程序中有一个默认参数
- 灵活使用命名项目:
- 如果你不想,你不需要命名任何项目,因为语法树总是被传入。
- 您可以在大宏定义中命名任何子表达式,因此很容易挑选出您感兴趣的特定内容
- 如果您想向宏结构添加更多功能,则可以轻松扩展。例如
Several("abc", min=3, max=5, name="a")
. 我认为这也可以用于将默认值添加到可选元素,如Optional("step", Var(), name="step", default=1)
.
我不确定带有“quote:”和“$”的引用/取消引用语法,但是需要一些语法,因为如果您不必手动编写语法树,它会使生活变得更容易。要求(或只是允许?)“$”的括号可能是个好主意,这样您就可以根据需要插入更复杂的语法部分。喜欢$(Stmt(a, b, c))
。
ToMacro 看起来像这样:
# macro definition
macro ToMacro(Partial):
syntax:
Var(name='start'), "to", Var(name='end'), Optional("inclusive", name='inc'), Optional("step", Var(name='step'))
if step == None:
step = quote(1)
if inclusive:
return quote:
xrange($(start), $(end)+1, $(step))
else:
return quote:
xrange($(start), $(end), $(step))
# resulting macro class
class ToMacro(PartialMacro):
syntax = Var(name='start'), "to", Var(name='end'), Optional("inclusive", name='inc'), Optional("step", Var(name='step'))
def handle(syntaxtree, start=None, end=None, inc=None, step=None):
if step is None:
step = Number(1)
if inclusive:
return ['xrange', ['(', start, [end, '+', Number(1)], step, ')']]
return ['xrange', ['(', start, end, step, ')']]