"Abdulaziz Ghuloum" wrote:
>On Aug 3, 2009, at 8:36 AM, Marco Maggi wrote:
>
>> One problem that needs to be solved is how to access
>> parser and lexer specific state when loading the
>> parser/lexer from a library.
>
> Why do the lexer and parser have state, and what does that
> state hold?
(silex) and (lalr) define the lexer and the parser using
rules like:
SOME-PATTERN (a-form-which-ends-in-a-closure)
and they generate tables which, somewhat, look like:
'#(---
(lambda (some argument)
(do-something-in-parser
(a-form-which-ends-in-a-closure)))
---)
when the table is enclosed in a library it looks like:
(library (calc-parser)
(export calc-parser)
(import (rnrs) (lalr lr-driver) ---)
(define calc-parser
(lr-driver
'#(---
(lambda (some argument)
(do-something-in-parser
(a-form-which-ends-in-a-closure)))
---))))
If the driver is meant to allow it,
A-FORM-WHICH-ENDS-IN-A-CLOSURE can access SOME and ARGUMENT.
They have informations about the state of the driver itself;
for example, with (silex), they provide the line and column
number counters.
But that is all; the libraries, as they are now, do not
allow to hand to the closures lexer and parser instances
specific state.
(lalr) is designed to allow direct evaluation of code, so
the calculator example has rules like:
(assign
(ID ASSIGN expr) :
(hashtable-set! (table-of-variables) $1 $3))
(expr (expr + expr) : (+ $1 $3)
(expr - expr) : (- $1 $3)
(expr * expr) : (* $1 $3)
(expr / expr) : (/ $1 $3)
(- expr (prec: uminus)) : (- $2)
(ID) : (hashtable-ref (table-of-variables) $1 #f)
(ID LPAREN args RPAREN) : (apply $1 $3)
(NUM) : $1
(LPAREN expr RPAREN) : $2)
which become lambdas like (for the addition):
(lambda (___stack ___sp ___goto-table ___push yypushback)
(let* (($3 (vector-ref ___stack (- ___sp 1)))
($2 (vector-ref ___stack (- ___sp 3)))
($1 (vector-ref ___stack (- ___sp 5))))
(___push 3 4 (+ $1 $3))))
It is possible to modify the generators to make the
closures accept custom arguments, but I am not looking
forward to it. To use parameters is much easier.
To build a parse tree (I have not tried it, yet), we can
modify the rules to:
(expr + expr) : (list + $1 $3)
so the nested evaluation of each closure builds the tree.
But (lalr) does not allow access to the value of each
evaluated rule, and it does not return the value of the
outer expression parsed; when it receives the end-of-input
token, it just returns nothing. This could be changed of
course, because it involves only a change in the driver
(which is small and should not be too difficult to
understand). The solution right now is to make the outer
rule store the result in a parameter.
--
Marco Maggi