Pythonic 宏语法

时间:2023-02-14
本文介绍了Pythonic 宏语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我一直在为 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.

我的问题是我想不出一个 Python 宏定义语法.我在下面的答案中以两种不同的语法发布了几个示例.谁能想出更好的语法?它不必以任何方式构建我提出的语法——我在这里完全开放.任何评论、建议等都会有所帮助,显示我发布的示例的替代语法也会有所帮助.

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 simple Var)
    • 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
      • 灵活使用命名项:
        • 如果你不想,你不需要命名任何项目,因为语法树总是被传入.
        • 您可以在大宏定义中命名任何子表达式,以便轻松挑选出您感兴趣的特定内容

        我不确定quote:"和$"的引用/取消引用语法,但需要一些语法,因为如果您不必手动编写语法树,它会使生活变得更容易.要求(或只是允许?)$"的括号可能是个好主意,这样您就可以根据需要插入更复杂的语法部分.像 $(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 宏语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:你可以用 Lisp 宏做什么,而一流的函数却做不到? 下一篇:pandas.Series() 使用 DataFrame Columns 创建返回 NaN 数据条目

相关文章

最新文章