help-bison
[Top][All Lists]
Advanced

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

Re: accessing yyval outside lex and yacc


From: Hans Aberg
Subject: Re: accessing yyval outside lex and yacc
Date: Fri, 20 Jul 2001 13:13:56 +0200

Manju James <address@hidden> wrote:
> Is it possible to access yyval externally (from another file -
> for instance)?  I would like to gain access to the $$ value of
> the last non-terminal/terminal that yyparse() builds.

At 10:28 +0200 2001/07/20, Akim Demaille wrote:
>Your question is not clear to me.  Are you asking how to get the
>_last_ $$, i.e., the result of your semantic actions?
>
>Then just use a global, say `ast', and in your axiom, write
>
>%%
>axiom: sentence { ast = $$ };
>...

As Akim points out, there is currently no pure way of getting hold of the
$$ value. I think that incorporating such a way was up last fall in the
bug-bison list. -- Check the archive.

One can though hide it away to look as though by passing over such a global
variable:

I use (under C++) a .h header:

class MyParser_type {
public:
  std::string text;
...
};


#define YYSTYPE MyParser_type

int yyerror(const std::string& errstr);

class MyParser {
  std::istream* isp;  // istream being parsed
  std::ostream* osp;  // ostream being output to
  FlexLexer* lex;     // Lexical analyzer to use;
public:
  CLPParser(std::istream* isp = 0, std::ostream* osp = 0);
    ~CLPParser();

  std::istream& operator>>(clp::Database&);
  friend CLPParser& operator>>(std::istream&, CLPParser&);
};

inline CLPParser& operator>>(std::istream& ist, CLPParser& parser) {
  parser.isp = &ist;
  return parser;
}

The .y file then conatains:

%{
#include "MyParser.h"

#define yyFlexLexer MyParserFlexLexer
#include "FlexLexer.h"

FlexLexer* MyLexer;

inline int yylex() { return MyLexer->yylex(); }

My::GlobalData global_data;

#define YYERROR_VERBOSE

%}


%%

my_variable:
    my_rule { global_data = $$.text /* Or something */ }

%%

int yyerror(const std::string& errstr) {
  std::cerr << "Error line " << CLPLexer->lineno()
    << ": " << errstr << std::endl;
  return EXIT_FAILURE;
}


namespace My {

void GlobalData::read(std::istream& is) {
        is >> MyParser() >> *this;
}

std::istream& operator>>(std::istream& is, GlobalData& data) {
  is >> MyParser() >> data;
  return is;
}

}

Then the usage becomes (in main()):

  try {
    Database data;

    std::ifstream is(stdlib.c_str());
    if (!is) {
      std::cerr << "Library " << stdlib << " not found." << std::endl;
//      return EXIT_FAILURE;
    } else {
    std::cout << "Reading " << stdlib << ":" << std::endl;
    is >> data;
    if (!is) {
      std::cerr << "Could not read library " << stdlib << "." << std::endl;
      return EXIT_FAILURE;
    }
    std::cout << "Done!" << std::endl;
    }

    std::cout << "For help, type \":?\"." << std::endl;

    for (;;) {
      std::cout << "> ";
      std::string str;
      std::getline(std::cin, str);
      std::stringstream iss(str);
      iss >> data;
    }
  } catch (std::exception& ex) {
    std::cerr << "Unexpected exception: "
      << ex.what() << " Bye, bye!" << std::endl;
    return EXIT_FAILURE;
  } catch (...) {
    std::cerr << "Unexpected exception. Bye, bye!" << std::endl;
    return EXIT_FAILURE;
  }

I stripped the code above from a program I made, so it may be somewhat messy.

But I hope the idea becomes clear: I have hidden away the use of the global
variable in a C++ istreams ">>" operator.

I would get into problems if using several simultaneous invokations of
yyparse(), implicitly by ">>" then, so for that I would need to use the
pure parser plus some. But I have not had any use of that yet.

  Hans Aberg





reply via email to

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