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-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 :: , context) => (token :: "<" ## ?token-name ## "-token>") let production = block() apply(?rule, stream, context) exception (err :: ) 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 () slot topic-spec; slot content; end class; define method initialize (token :: , #key tokens) content := tokens[0]; topic-spec := tokens[1]; end method; define method parse-topic (stream :: , context) => (token :: ) let production = block() apply(seq(choice(parse-topic-directive, parse-topic-title), opt(parse-topic-content)), stream, context); exception (err :: ) err.expected := concatenate!(err.expected, " in topic"); error(err) end; make(, 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: ---