help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Please help!....Strange Error


From: Hans Aberg
Subject: Re: Please help!....Strange Error
Date: Sun, 13 Apr 2003 10:40:10 +0200

[Please reply to Help-Bison.]
At 22:27 -0700 2003/04/12, Gregory L Montgomery wrote:
>       I'm constructing an interpreter which is an extention of a simple
>calculator. My goal is to enable my interpreter to have scope, and to be able
>to have function calls. At the present time I have run into a strange problem
>(previous versions worked well no problem.) I can enter a simple command at
>my interpreters prompt like a=1\n and everything is OK ONLY FOR THAT FIRST
>LINE. Everything entered after this receives an error. To track down what was
>happening I #define YYDEBUG 1, and set "int yydebug = 1;" in the output from
>bison. The command which I used to generate my parser files was

You have hooked up your parser so that it should handle the command line
interaction. I think that funny things can happen that way with a parser
algorithm like LALR(1) that Bison uses, because it may or may not make use
of the lookahead token. This may then affect the interaction. (A similar
thing may happen when you set context switches from the .y actions, so it
is better to do that from the lexer, if possible.)

So when I make an interactive parser, I first write the parser as though it
read from a file. Then I add, for the interaction, a REPL
(read-evaluate-print-loop): a code snippet that reads one line at a time,
passes it to the parser, and then prints the parsed result (if the parser
does not do that itself).

One advantage of this approach is that if you later you extend to multiline
input, that has already been done. For example, it is often convenient to
have the program to use the parser to read a definitions file at startup.

Below is an example of how my .y file looks for a parser that can be used
interactively (actions are in C++). As you can see, I do not have any
newline tokens in my grammar: In fact, I have a rule in my Flex .l file
    [[:space:]]+      { /* Skip white-space. */ }
That zips out all white-space. -- I think that this leads to better
language and grammar.

There are some disadvantages with this approach: Commands can be entered in
files, so if one does not want that, some rules must be turned off say by
generating errors in the actions when read from a file. Also, if the
grammar is written as below, more than one command can be entered on a
single line.

%%
file:
    file_contents {}
  |               {}
  | error {
      clp_parser_context = 0;
      declaration_context = false;
      substitution_context = false;
      YYABORT;
    }
;
file_contents:
    file_contents command {}
  | command               {}
;
command:
    help_key { mli::help(std::cout); }
  | quit_key { std::cout << "Thank you and goodbye." << std::endl;
      std::exit(EXIT_SUCCESS); }
  | show_key { yypval.write(std::cout, write_default); }
  | level_key integer_value "." { level_max = $2.number; }
  | "Prolog" Prolog_clause { clp_parser_context = 0;
      yypval.insert(statement($2.object_)); }
  | "Prolog" "{" Prolog_clauses "}" { clp_parser_context = 0; }
  | Prolog_query { clp_parser_context = 0; }
  | { clp_table_stack_.clear(); } "unify"
    "(" declared_formula "," declared_formula ")" {
      maybe<substitution> s = unify(formula($4.object_), formula($6.object_));
      if (!s)  std::cout << "No solutions." << std::endl;
      std::cout << *s << std::endl; }
  | solve proof_statement {}
  | solve query "by" find_statement "." {
      database d = database($4.object_);
      d.demonstrate(formula($2.object_));
    }
  | verify query "." { yypval.demonstrate(formula($2.object_)); }
  | { clp_table_stack_.clear(); }
    axiom {
      yypval.insert(statement($2.object_));
      if (object_out != 0)  (*object_out) << $2.object_ << "\n\n";
    }
  | { clp_table_stack_.clear(); } theory {}
  | theorem {
      statement t($1.object_); // The theorem.
      yypval.insert(t);
      t.prove();     // Attempt to prove the theorem.
      if (object_out != 0)
        (*object_out) << t << "\n\n";
    }
;
...

  Hans Aberg






reply via email to

[Prev in Thread] Current Thread [Next in Thread]