Синтаксис макроса Pythonic

Использовать 1 a float и float division

public static void main(String d[]){
    double g=1f/3;
    System.out.printf("%.2f",g);
}
20
задан Cody Brocious 20 January 2009 в 09:35
поделиться

9 ответов

После размышления об этом некоторое время несколько дней назад, и придумывающий ничто стоящее отправить, я возвратился к нему теперь и придумал некоторый синтаксис я скорее как, потому что это почти похоже на Python:

macro PrintMacro:
  syntax:
    "print", OneOrMore(Var(), name='vars')

  return Printnl(vars, None)
  • Заставляют все макро-"ключевые слова" быть похожими на создание объектов Python (Var() вместо простого Var)
  • Передача название элементов как "ключевой параметр" к объектам, которых мы хотим название. Должно все еще быть легко найти все имена в синтаксическом анализаторе, так как это определение синтаксиса так или иначе должно быть интерпретировано в некотором роде для заполнения макро-переменной синтаксиса классов.

    потребности, которые будут преобразованы для заполнения переменной синтаксиса получающегося макро-класса.

внутреннее представление синтаксиса могло также выглядеть одинаково:

class PrintMacro(Macro):
  syntax = 'print', OneOrMore(Var(), name='vars')
  ...

внутренние классы синтаксиса как [1 110] следовали бы за этим шаблоном для разрешения подэлементов и дополнительного имени:

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)

я добавил syntaxtree как первый параметр, который всегда передается, таким образом, у Вас не должно было бы быть именованных объектов, если Вы просто хотите сделать очень простой материал на синтаксическом дереве.

кроме того, если Вам не нравятся декораторы, почему бы не добавить макро-тип как "базовый класс"? 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 в обработчике
  • Гибкое использование именованных объектов:
    • Вы не должны называть объекты, если Вы не хотите, потому что синтаксическое дерево всегда передается в.
    • можно назвать любые подвыражения в большом макроопределении, таким образом, легко выбрать определенный материал, Вы интересуетесь [1 142]
  • Легко расширяемы, если Вы хотите добавить больше опций к макро-конструкциям. Например Several("abc", min=3, max=5, name="a"). Я думаю, что это могло также использоваться для добавления значений по умолчанию к дополнительным элементам как [1 114].

я не уверен в заключить в кавычки/закрыть кавычки синтаксисе с "кавычкой": и "$", но некоторый синтаксис для этого необходим, так как он делает жизнь намного легче, если Вы не должны вручную писать синтаксические деревья. Вероятно, это - хорошая идея потребовать (или просто разрешить?) круглая скобка за "$", так, чтобы можно было вставить более сложные части синтаксиса, если Вы хотите. Как [1 115].

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, ')']]
10
ответ дан 30 November 2019 в 01:08
поделиться

Вы должны взглянуть на MetaPython , чтобы увидеть, достигает ли он того, что вы ищете .

3
ответ дан 30 November 2019 в 01:08
поделиться

Вы могли бы рассмотреть взгляд на то, как Шиканье (основанный на.NET язык с синтаксисом, в основном вдохновленным Python), реализует макросы, как описано по телефону http://boo.codehaus.org/Syntactic+Macros .

3
ответ дан 30 November 2019 в 01:08
поделиться

Это - новый макро-синтаксис, который я придумал на основе идей Kent Fredric. Это анализирует синтаксис в список точно так же, как код анализируется.

макрос Печати:

macro PrintMacro:
    syntax:
      print $stmts

  if not isinstance(stmts, list):
    stmts = [stmts]
  return Printnl(stmts, None)

, Если макрос:

@MultiLine
macro IfMacro:
  syntax:
    @if_ = if $cond: $body
    @elifs = ZeroOrMore(elif $cond: $body)
    Optional(else: $elseBody)

  return If(
      [(cond, Stmt(body)) for cond, body in [if_] + elifs],
      elseBody != None and Stmt(elseBody) or None
    )

X к Y [содержащему] [шаг Z] макрос:

@Partial
macro ToMacro:
  syntax:
    $start to $end Optional(inclusive) Optional(step $step)

  if step == None:
    step = quote 1
  if inclusive:
    return quote:
      xrange($start, $end+1, $step)
  else:
    return quote:
      xrange($start, $end, $step)

Кроме незначительной проблемы использования декораторов для идентификации макро-типа моей единственной реальной проблемой с этим является способ, которым можно назвать группы, например, в если случай. Я использую @name =..., но это просто сильно пахнет Perl. Я не хочу просто использовать имя =..., потому что это могло конфликтовать с макро-шаблоном для соответствия. Какие-либо идеи?

1
ответ дан 30 November 2019 в 01:08
поделиться

Слияние BNF

class IfMacro(Macro):
    syntax: "if" expression ":" suite ("elif" expression ":" suite )* ["else" ":" suite] 

    def handle(self, if_, elifs, elseBody):
        return If(
            [(expression, Stmt(suite)) for expression, suite in [if_] + elifs],
            elseBody != None and Stmt(elseBody) or None
            )
2
ответ дан 30 November 2019 в 01:08
поделиться

Я отправляю немного плавающих идей видеть, вдохновляет ли это. Я не знаю много Python, и я не использую реальный синтаксис Python, но он ничего не бьет :p

macro PrintMacro:
  syntax:  
          print $a
  rules:  
        a: list(String),  as vars
  handle:
       # do something with 'vars' 

macro IfMacro:
  syntax: 
      if $a :
          $b
      $c 
   rules: 
        a: 1 boolean  as if_cond 
        b: 1 coderef     as if_code 
        c: optional macro(ElseIf) as else_if_block 

    if( if_cond ):
          if_code();
    elsif( defined else_if_block ): 
          else_if_block(); 
[еще 113] идеи:

стиль кавычки Perl Реализации, но в Python! (это - очень плохая реализация и примечание: пробел является значительным в правиле)

macro stringQuote:
  syntax:  
          q$open$content$close
  rules:  
        open:  anyOf('[{(/_') or anyRange('a','z') or anyRange('0','9');
        content: string
        close:  anyOf(']})/_') or anyRange('a','z') or anyRange('0','9');
  detect: 
      return 1 if open == '[' and close == ']' 
      return 1 if open == '{' and close == '}'
      return 1 if open == '(' and close  == ')'
      return 1 if open == close 
      return 0
  handle: 
      return content;
1
ответ дан 30 November 2019 в 01:08
поделиться

Если Вы только спрашиваете о синтаксисе (не реализация) макросов в рамках Python, то я полагаю, что ответ очевиден. Синтаксис должен тесно соответствовать тому, что Python уже имеет (т.е." def" ключевое слово).

, Реализуете ли Вы это, поскольку одно из следующего ваше дело:

def macro largest(lst):
defmac largest(lst):
macro largest(lst):

, но я полагаю, что это должно быть точно то же как нормальная функция относительно остальных так, чтобы:

def twice_second(a,b):
    glob_i = glob_i + 1
    return b * 2
x = twice_second (1,7);

и

defmac twice_second(a,b):
    glob_i = glob_i + 1
    return b * 2
x = twice_second (1,7);

функционально эквивалентны.

способ, которым я реализовал бы это, с препроцессором (а-ля C), который был бы:

  • замена весь defmac's с defs во входном файле.
  • передача это через Python для проверки синтаксиса (подлый бит, это).
  • откладывает defmac's в.
  • находят все использование каждого макроса и "встраивают" их, с помощью собственных зарезервированных переменных, таких как преобразование локального var a с __macro_second_local_a.
  • возвращаемое значение должно быть специальной переменной также (macro_second_retval).
  • глобальные переменные сохранили бы свои настоящие имена.
  • параметру можно дать имена _macro_second_param_XXX.
  • , после того как все встраивание сделано, удалите defmac 'функции' полностью.
  • передают результирующий файл через Python.

Несомненно будет некоторый nigglies для заботы о (как кортежи или несколько точек возврата), но Python достаточно устойчив для обработки этого, по-моему.

Так:

x = twice_second (1,7);

становится:

# These lines are the input params.
__macro_second_param_a = 1
__macro_second_param_b = 7

# These lines are the inlined macro.
glob_i = glob_i + 1
__macro_second_retval = __macro_second_param_b * 2

# Modified call to macro.
x = __macro_second_retval
1
ответ дан 30 November 2019 в 01:08
поделиться

Это - текущий механизм для определения синтаксиса при помощи стандартного класса Python.

макрос Печати:

class PrintMacro(Macro):
  syntax = 'print', Var
  def handle(self, stmts):
    if not isinstance(stmts, list):
      stmts = [stmts]
    return Printnl(stmts, None)

макро-класс If/elif/else:

class IfMacro(MLMacro):
  syntax = (
      ('if', Var, Var),
      ZeroOrMore('elif', Var, Var),
      Optional('else', Var)
    )
  def handle(self, if_, elifs, elseBody):
    return If(
        [(cond, Stmt(body)) for cond, body in [if_] + elifs],
        elseBody != None and Stmt(elseBody) or None
      )

X к Y [содержащему] [шаг Z] класс макроса:

class ToMacro(PartialMacro):
  syntax = Var, 'to', Var, Optional('inclusive'), Optional('step', Var)
  def handle(self, start, end, inclusive, step):
    if inclusive:
      end = ['(', end, '+', Number(1), ')']
    if step == None: step = Number(1)
    return ['xrange', ['(', start, end, step, ')']]

Мои проблемы с этим дизайном - то, что вещи являются очень подробными и не чувствуют pythonic ни в малейшей степени. Кроме того, отсутствие способности к цитате делает сложные макросы трудными.

0
ответ дан 30 November 2019 в 01:08
поделиться

Это - макро-синтаксис, который я придумал для своего надмножества Python.

макрос Печати:

macro PrintMacro:
    syntax:
        stmts = 'print', Var

  if not isinstance(stmts, list):
    stmts = [stmts]
  return Printnl(stmts, None)

, Если макрос:

@MultiLine
macro IfMacro:
  syntax:
    if_ = 'if', Var, Var
    elifs = ZeroOrMore('elif', Var, Var)
    else_ = Optional('else', Var)

  return If(
      [(cond, Stmt(body)) for cond, body in [if_] + elifs],
      elseBody != None and Stmt(elseBody) or None
    )

X к Y [содержащему] [шаг Z] макрос:

@Partial
macro ToMacro:
  syntax:
    start = Var
    'to'
    end = Var
    inclusive = Optional('inclusive')
    step = Optional('step', Var)

  if step == None:
    step = quote 1
  if inclusive:
    return quote:
      xrange($start, $end+1, $step)
  else:
    return quote:
      xrange($start, $end, $step)

Моя основная проблема с этим - то, что блок синтаксиса неясен, особенно 'к' строке в последнем примере. Я - также не большой поклонник использования декораторов для дифференциации макро-типов.

0
ответ дан 30 November 2019 в 01:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: