问题描述
我一直在研究Python的另一种编译器前端,其中所有语法都通过宏进行解析.我终于到了开发的地步,我可以开始研究Python语言的超集,其中宏是不可或缺的组成部分.
I've been working on an alternative compiler front-end for Python where all syntax is parsed via macros. I'm finally to the point with its development that I can start work on a superset of the Python language where macros are an integral component.
我的问题是我无法提出pythonic宏定义语法.我在下面的答案中以两种不同的语法发布了一些示例.任何人都可以提出更好的语法吗?不必以任何方式构建我提出的语法-我在这里完全打开了.任何评论,建议等都会有帮助,显示我发布的示例的替代语法也将有所帮助.
My problem is that I can't come up with a pythonic macro definition syntax. I've posted several examples in two different syntaxes in answers below. Can anyone come up with a better syntax? It doesn't have to build off the syntax I've proposed in any way -- I'm completely open here. Any comments, suggestions, etc would be helpful, as would alternative syntaxes showing the examples I've posted.
关于宏结构的注释,如我所发布的示例所示:MultiLine/MLMacro和Partial/PartialMacro的使用告诉解析器如何应用宏.如果是多行,则宏将匹配多个行列表;否则,宏将匹配多个行列表.通常用于构造.如果是局部代码,则宏将匹配列表中间的代码;否则,宏将与列表中间的代码匹配.通常用于运营商.
A note about the macro structure, as seen in the examples I've posted: The use of MultiLine/MLMacro and Partial/PartialMacro tell the parser how the macro is applied. If it's multiline, the macro will match multiple line lists; generally used for constructs. If it's partial, the macro will match code in the middle of a list; generally used for operators.
推荐答案
几天前考虑了一下,没有提出任何值得发表的内容,现在我又回到了它,并提出了一些我宁愿使用的语法之类的,因为它几乎类似于python:
After thinking about it a while a few days ago, and coming up with nothing worth posting, I came back to it now and came up with some syntax I rather like, because it nearly looks like python:
macro PrintMacro:
syntax:
"print", OneOrMore(Var(), name='vars')
return Printnl(vars, None)
- 使所有宏关键字"看起来像创建python对象(
Var()
而不是简单的Var
) -
将元素名称作为关键字参数"传递给我们要为其命名的项目.仍然很容易在解析器中找到所有名称,因为无论如何都需要以某种方式解释此语法定义以填充宏类语法变量.
- Make all the macro "keywords" look like creating python objects (
Var()
instead of simpleVar
) Pass the name of elements as a "keyword parameter" to items we want a name for.It should still be easy to find all the names in the parser, since this syntax definition anyway needs to be interpreted in some way to fill the macro classes syntax variable.
需要进行转换以填充结果宏类的语法变量.
needs to be converted to fill the syntax variable of the resulting macro class.
内部语法表示也可能看起来相同:
The internal syntax representation could also look the same:
class PrintMacro(Macro): syntax = 'print', OneOrMore(Var(), name='vars') ...
内部语法类(例如
OneOrMore
)将遵循此模式以允许子项目和可选名称:The internal syntax classes like
OneOrMore
would follow this pattern to allow subitems and an optional name:class MacroSyntaxElement(object): def __init__(self, *p, name=None): self.subelements = p self.name = name
当宏匹配时,您只需收集所有具有名称的项并将它们作为关键字参数传递给处理函数:
When the macro matches, you just collect all items that have a name and pass them as keyword parameters to the handler function:
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)
然后将定义处理程序函数,如下所示:
The handler function would then be defined like this:
class PrintMacro(Macro): ... def handle(self, syntaxtree, vars): return Printnl(vars, None)
我添加了语法树作为始终传递的第一个参数,因此,如果您只想在语法树上做非常基本的事情,就不需要任何命名项.
I added the syntaxtree as a first parameter that is always passed, so you wouldn't need to have any named items if you just want to do very basic stuff on the syntax tree.
此外,如果您不喜欢装饰器,为什么不像基类"那样添加宏类型呢?
IfMacro
会看起来像这样:Also, if you don't like the decorators, why not add the macro type like a "base class"?
IfMacro
would then look like this: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) )
我认为这将提供一个非常灵活的系统.主要优点:
I think this would give a quite flexible system. Main advantages:
- 易于学习(看起来像标准的python)
- 易于解析(类似于标准python的解析)
- 可选项目易于处理,因为您可以在处理程序中使用默认参数
None
- 灵活使用命名项:
- 如果不需要,您无需命名任何项目,因为语法树始终会传入.
- 您可以在大型宏定义中命名任何子表达式,因此很容易挑选出您感兴趣的特定内容
- Easy to learn (looks like standard python)
- Easy to parse (parses like standard python)
- Optional items can be easily handled, since you can have a default parameter
None
in the handler - Flexible use of named items:
- You don't need to name any items if you don't want, because the syntax tree is always passed in.
- You can name any subexpressions in a big macro definition, so it's easy to pick out specific stuff you're interested in
我不确定带有"quote:"和"$"的quote/unquote语法,但是需要一些语法,因为如果您不必手动编写语法树,它将使工作变得更加轻松.要求(或只是允许?)"$"括号可能是个好主意,因此,如果需要,您可以插入更复杂的语法部分.就像
$(Stmt(a, b, c))
.I'm not sure about the quote/unquote syntax with "quote:" and "$", but some syntax for this is needed, since it makes life much easier if you don't have to manually write syntax trees. Probably its a good idea to require (or just permit?) parenthesis for "$", so that you can insert more complicated syntax parts, if you want. Like
$(Stmt(a, b, c))
.ToMacro看起来像这样:
The ToMacro would look something like this:
# 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, ')']]
这篇关于Pythonic宏语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
- Make all the macro "keywords" look like creating python objects (