[climacs-devel] grammar definition
Nicolas Sceaux
nicolas.sceaux at free.fr
Sun Jan 22 13:40:37 UTC 2006
Robert Strandh <strandh at labri.fr> writes:
> You may want to start with a protocol (in the sense of Keene) for
> manipulating grammars; then you can define syntax to simplify common
> cases. For instance, you most likely would want the grammar to be
> able to evolve programmatically. There should be some examples of
> `add-rule' in the other syntax modules that show this idea.
An attempt to write protocol for LR syntax, as defined in
lisp-syntax.lisp today (the descriptions, when they are mine, are, hm,
minimal):
lr-syntax [protocol class]
Base class for syntaxes using a LR parser.
parser-symbol [protocol class]
Base class for parse trees, including lexemes.
* Lexer
lexer-state [protocol class]
These states are used to determine how the lexer should behave.
define-lexer-state name superclasses &body body [macro]
Define a lexer-state subclass (lexer-state is prepended to the
superclass list).
skip-inter syntax state scan [generic function]
Advance scan until the beginning of a new lexeme.
Return T if one can be found and NIL otherwise.
lexeme [class]
...
lex syntax state scan [generic function]
Return the next lexeme starting at scan.
* Parser
parser-state [protocol class]
Base class for LR parser states.
define-parser-state name superclasses &body body [macro]
Define a parser-state subclass and a singleton instance with the same
name.
(Side question: shouldn't parser-state be added to the superclass list
by the macro, rather than by the user? as is done in
define-lexer-state)
action syntax parser-state lexeme [generic function]
This function is called after the lexer has returned a lexeme to the
parser, which current state is parser-state. It returns a
parser-symbol.
define-action syntax (parser-state lexeme) body [macro]
Define an action method for syntax, parser-state and lexeme.
reduce-fixed-number [macro]
...
reduce-until-type [macro]
...
reduce-all [macro]
...
NOTE: I see that SYNTAX is used in there expansion, without
introducing a binding for it. Isn't that a problem?
done [tag]
...
new-state syntax parser-state parser-symbol [generic function]
This function is called after the parser, which current state is
parser-state, has reached parser-symbol, and return the new parser
state.
define-new-state syntax (parser-state parser-symbol) new-parser-state
Define what the new state of the parser should be when it reaches
parser-symbol while its current state is parser-state.
* Display
display-parse-tree parse-symbol syntax pane
...
> Perhaps a compromise would be to specify a rule pretty much the
> standard way, but to allow for a state name to be inserted between two
> parser symbols, for instance:
>
> (list -> left-parenthesis-lexeme {the-state-we-want-to-be-in} ...)
>
> or something like that.
add-rule syntax (nonterminal -> &rest arguments) [macro]
Create a parser rule for syntax.
arguments should look like: initial-state [symbol next-state]+ [:EOF]?
:EOF is used to signal that the reduction to nonterminal applies when
the end of buffer is reached.
nonterminal -> initial-state symbol1 state1 symbol2 state2 ... symboln staten
means that starting from the parser state initial-state, when symbol1
is reached, the parser changes to state state1; then, being in state
state1, if symbol2 is reached, the parser changes to state state2,
etc. Finally, the parse tree is reduced to nonterminal. The parser is
then in state staten.
(reading myself, I do realize that I'm not really clear)
(add-rule lisp-syntax
(complete-list-form -> form-may-follow left-parenthesis-lexeme
|( form* | comment
|( form* | form
|( form* | right-parenthesis-lexeme
|( form* ) |))
==>
(PROGN (DEFINE-NEW-STATE LISP-SYNTAX (FORM-MAY-FOLLOW LEFT-PARENTHESIS-LEXEME)
|( form* |)
(DEFINE-NEW-STATE LISP-SYNTAX (|( form* | COMMENT) |( form* |)
(DEFINE-NEW-STATE LISP-SYNTAX (|( form* | FORM) |( form* |)
(DEFINE-NEW-STATE LISP-SYNTAX (|( form* | RIGHT-PARENTHESIS-LEXEME)
|( form* ) |)
(DEFINE-ACTION LISP-SYNTAX (|( form* ) | T)
(REDUCE-UNTIL-TYPE COMPLETE-LIST-FORM LEFT-PARENTHESIS-LEXEME)))
(add-rule lisp-syntax
(incomplete-list-form -> form-may-follow left-parenthesis-lexeme
|( form* | comment
|( form* | form
|( form* | :EOF))))
==>
(PROGN (DEFINE-NEW-STATE LISP-SYNTAX (FORM-MAY-FOLLOW LEFT-PARENTHESIS-LEXEME)
|( form* |)
(DEFINE-NEW-STATE LISP-SYNTAX (|( form* | COMMENT) |( form* |)
(DEFINE-NEW-STATE LISP-SYNTAX (|( form* | FORM) |( form* |)
(DEFINE-ACTION LISP-SYNTAX (|( form* | (EQL NIL))
(REDUCE-UNTIL-TYPE INCOMPLETE-LIST-FORM LEFT-PARENTHESIS-LEXEME)))
That would cover most of the rules in lisp-syntax (ie, all of them,
except the error and top-level ones).
nicolas
More information about the climacs-devel
mailing list