Paste number 53681: macro

Index of paste annotations: 1 | 2

Paste number 53681: macro
Pasted by: |Agent
6 months, 2 weeks ago
#dylan | Context in IRC logs
Paste contents:
Raw Source | XML | Display As
Here are the macro definitions:

---------------------------
define macro tokenizer-definer
   {
      define tokenizer ?token-name:name
         rule ?rule => ?product-name:name;
         ?slots
      end
   } => {
      define class "<" ## ?token-name ## "-token>" (<token>)
         token-class-slots(?slots)
      end class;
      
      define method initialize (token :: "<" ## ?token-name ## "-token>",
            #key ?product-name)
         slot-initializers(?slots)
      end method;
      
      define method "parse-" ## ?token-name
         (stream :: <positionable-stream>, context)
      => (token :: "<" ## ?token-name ## "-token>")
         let production =
               block()
                  apply(?rule, stream, context)
               exception (err :: <parse-failure>)
                  err.expected := concatenate!(err.expected, " in " ## ?"token-name");
                  error(err)
               end;
         make("<" ## ?token-name ## "-token>",
              position: stream.position, ?product-name: production)
      end method;
      
      $rule-names["parse-" ## ?token-name] := "?token-name";
   }
rule:
   { ?:name(...) } => { ?name(...) }
   { ?:name, ...  } => { "parse-" ## ?name, ... }
   { } => { }
slots:
   { slot ?:variable = ?:expression; ... } => { ?variable = ?expression, ... }
   { slot ?:variable; ... } => { ?variable, ... }
   { } => { }
end macro;

define macro token-class-slots
   { token-class-slots (?:variable = ?:expression, ?more:*) }
      => { slot ?variable; token-class-slots(?more) }
   { token-class-slots (?:variable, ?more:*) }
      => { slot ?variable; token-class-slots(?more) }
   { token-class-slots () }
      => { }
end macro;

define macro slot-initializers
   { slot-initializers (?:variable = ?:expression, ?more:*) }
      => { ?variable := ?expression; slot-initializers(?more) }
   { slot-initializers (?:variable, ?more:*) }
      => { slot-initializers(?more) }
   { slot-initializers () }
      => { }
end macro;
---------------------------


Here is an example of use:

------------------------
define tokenizer topic
   rule seq(choice(topic-directive, topic-title), opt(topic-content)) => tokens;
   slot topic-spec = tokens[0];
   slot content = tokens[1];
end;
------------------------


That should result in:

------------------------
define class <topic-token> (<token>)
   slot topic-spec;
   slot content;
end class;
      
define method initialize (token :: <topic-token>, #key tokens)
   content := tokens[0];
   topic-spec := tokens[1];
end method;

define method parse-topic
   (stream :: <positionable-stream>, context)
=> (token :: <topic-token>)
   let production =
         block()
            apply(seq(choice(parse-topic-directive, parse-topic-title), opt(parse-topic-content)),
                  stream, context);
         exception (err :: <parse-failure>)
            err.expected := concatenate!(err.expected, " in topic");
            error(err)
         end;
   make(<topic-token>, position: stream.position, tokens: production)
end method;
      
$rule-names[parse-topic] := "topic";
-----------------------


Instead, compilation fails with the following:

Serious warning at tokenizers.dylan:9: Invalid syntax for rule in tokenizer-definer macro call.

tokenizers.dylan:9:             --------------------------------------------------------
tokenizers.dylan:9:    rule seq(choice(topic-directive, topic-title), opt(topic-content)) => tokens;
tokenizers.dylan:9:             --------------------------------------------------------

Serious warning at tokenizers.dylan:8:
  Skipping tokenizer-definer macro call due to previous syntax error.

tokenizers.dylan:8: ----------------------
tokenizers.dylan:8: define tokenizer topic
tokenizers.dylan:9:    rule seq(choice(topic-directive, topic-title), opt(topic-content)) => tokens;
tokenizers.dylan:11: [...]
tokenizers.dylan:12: end;
tokenizers.dylan:13: ---

Annotations for this paste:

Annotation number 1: slight improvement
Pasted by: |Agent
6 months, 2 weeks ago
Context in IRC logs
Paste contents:
Raw Source | Display As
I replaced the rule: aux-pattern with these three patterns:

-------
rule:
   { ?rule-op, ... } => { ?rule-op, ... }
   { ?rule-parser, ...  } => { ?rule-parser, ... }
   { } => { }
rule-op:
   { ?:name(?rule) } => { ?name(?rule) }
rule-parser:
   { ?:name } => { "parse-" ## ?name }
-------

This is slightly better. Now it recurses within the seq(...) calls, but I still get the following error:

-------
Serious warning at tokenizers.dylan:9: Invalid syntax for rule-op in tokenizer-definer macro call.

tokenizers.dylan:9:                    ---------------
tokenizers.dylan:9:    rule seq(choice(topic-directive, topic-title), opt(topic-content)) => tokens;
tokenizers.dylan:9:                    ---------------

Serious warning at tokenizers.dylan:8:
  Skipping tokenizer-definer macro call due to previous syntax error.

tokenizers.dylan:8: ----------------------
tokenizers.dylan:8: define tokenizer topic
tokenizers.dylan:9:    rule seq(choice(topic-directive, topic-title), opt(topic-content)) => tokens;
tokenizers.dylan:11: [...]
tokenizers.dylan:12: end;
tokenizers.dylan:13: ---
-------

It looks like it tries to match "topic-directive" against rule-op, but if that fails, it doesn't try to match it
against rule-parser:?

Annotation number 2: fixed macro
Pasted by: |Agent
6 months, 2 weeks ago
Context in IRC logs
Paste contents:
Raw Source | Display As
Here is the replacement for the original rule: aux pattern

----
rule:
   { seq(?nested-rule) ... } => { seq(?nested-rule) ... }
   { choice(?nested-rule) ... } => { choice(?nested-rule) ... }
   { many(?nested-rule) ... } => { many(?nested-rule) ... }
   { opt(?nested-rule) ... } => { opt(?nested-rule) ... }
   { opt-seq(?nested-rule) ... } => { opt-seq(?nested-rule) ... }
   { opt-choice(?nested-rule) ... } => { opt-choice(?nested-rule) ... }
   { opt-many(?nested-rule) ... } => { opt-many(?nested-rule) ... }
   { req-next(?nested-rule) ... } => { req-next(?nested-rule) ... }
   { not-next(?nested-rule) ... } => { not-next(?nested-rule) ... }
   { ?:name ... } => { "parse-" ## ?name ... }
   { ?:token ... } => { ?token ... }
   { } => { }
nested-rule:
   { ?rule } => { ?rule }
----

Aux patterns must match everything, and recursion into an expression can be done via nested-rule as I show here.

Colorize as:
Show Line Numbers
Index of paste annotations: 1 | 2

Ads absolutely not by Google

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.