| Paste number 53681: | macro |
| Pasted by: | |Agent |
| 6 months, 2 weeks ago | |
| #dylan | Context in IRC logs | |
| Paste contents: |
| 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: |
| 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: |
| 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. |