Related articles |
---|
loops in bison jewell@willowglen.ab.ca (Aaron Jewell) (2000-08-04) |
Re: loops in bison cfc@world.std.com (Chris F Clark) (2000-08-05) |
Re: loops in bison jewell@willowglen.ab.ca (Aaron Jewell) (2000-08-10) |
Re: loops in bison cfc@world.std.com (Chris F Clark) (2000-08-13) |
From: | Chris F Clark <cfc@world.std.com> |
Newsgroups: | comp.compilers |
Date: | 5 Aug 2000 21:29:43 -0400 |
Organization: | The World Public Access UNIX, Brookline, MA |
References: | 00-08-024 |
Keywords: | interpreter, comment |
CC: | compilers@iecc.com, cfc@world.std.com |
The following message is a courtesy copy of an article
that has been posted to comp.compilers as well.
> One idea I had is to redirect yylex()'s input from a string and then
> feed the parser a series of strings read line by line from the
> script file. That way I could buffer those strings corresponding to
> the statement_list within the loop and run them through the lexer
> again 'n' times. However, I'm not sure if this will work - for
> example, if the END_LOOP token falls on the same line as the last
> statement in the statement_list. It may also be alot of work and
> unfortunately a have limited time to implement this.
> [Once again, my advice is "don't do that". . . . -John]
Even if you ignore the moderators sound advice of not inventing your
own scripting language, don't implement it by reparsing the input to
implement loops (nor by skipping around in the input to implement
if's).
Parse your input exactly once, build a "tree" that represents the
input, and walk the tree to execute the program. You will save
yourself considerable grief over the long run.
If you need help in doing that, I can send you a copy of a Sigplan
NOTICES article on the very topic called "Build a Tree; Save a Parse".
If you are truly strapped for time in doing it (and you have to
implement a specific language so that you can't use an off the shelf
interpreter) find a parser generator that will build an AST for you.
(Actually, I would do this anyway, as an automatically generated AST
built from grammar annotations will be more robust to changes in your
grammar.) There are several good candidates of parser generators that
build ASTs.
Once you have an AST, all you have to do is write the code for each
"node type" (class) that implements the semantics of executing that
particular statement or expression. (This is the walking the tree
part of the above advice.)
Thus, for your loop statement, you would write code like the following:
CONSTRUCT loop_statement :: all // build an AST for loop statement
member { // as a class with a member function
int execute() // called execute that implements the
{ // interpreter for that grammar rule
while (yy_operand[3].execute()) {
yy_operand[5].execute();
}
return 0;
}
}
loop_statement
: LOOP '(' expression ')' statement_list END_LOOP
;
Hope this helps,
-Chris
*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
3 Proctor Street voice : (508) 435-5016
Hopkinton, MA 01748 USA fax : (508) 435-4847 (24 hours)
[An AST certainly works fine. I've also used reverse polish tokens and
an evaluation stack. -John]
Return to the
comp.compilers page.
Search the
comp.compilers archives again.