/**
    This file is part of KMathTool, a KDE program for the math class...
    Copyright (C) 2002 Dominique Devriese <fritmebufstek@pandora.be>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef PARSER_H
#define PARSER_H

#include <qstring.h>
#include <qcstring.h>

#include <assert.h>

class FormulaNode;

/**
 * A parser which takes a QString, and tries to parse it into a
 * parabolic formula ( i.e. a*x^2+b*x+c ).  It returns a(), b() and
 * c() in the respective functions...
 *
 * I have used bison and flex for this class, cause i think it's the
 * easiest way of writing it.  This does mean that the class interface
 * and implementation may look somewhat strange.  Here is a short
 * explanation of it:
 * yacc (bison) generates a "parser".  This is a c function (named
 * yyparse() ), that reads in "tokens" from the "lexical analyzer"
 * (see below), and tries to parse them with the grammar specified as
 * yacc's input ( here: the file named bison_parser.ypp ).  For more
 * information about yacc, i suggest you read the info pages of the
 * GNU yacc implementation bison ( info bison ).
 * The "lexical analyzer" is another function (named "yylex()")which
 * reads char's from somewhere ( in this case the QString which is
 * given to the parser ), and determines what "token type" they are,
 * so that yacc knows what to do with them.  It is possible to write
 * this function yourself, but it is much easier to have it produced
 * by a program called lex (GNU implementation is called flex).  The
 * function is generated based on something like regular expressions
 * which is given as input to flex ( here: the file called
 * lex_analyzer.ll ).  The lexical analyzer created by flex gets its
 * input from the macro YY_INPUT, you can see that in front of the
 * .ll file, i redefine this to get the input from
 * Parser::instance()->mString...
 * For more information on Flex, read its info pages (info flex).
 */
class Parser {
public:
  Parser();
  ~Parser();
  // i know the static functions suck, but the yyparse() function
  // generated by bison somehow needs to be able to give us its
  // output, and this seems like the easiest way.  If you think of a
  // better way, don't hesitate to send me a patch ;)
  static Parser* instance();
  // this resets the internal state of the Parser, so only call it if
  // you're going to call parse() next
  static Parser* newInstance();

  bool parse( const QString );
  const double a() const { assert( mParsed ); return mA; };
  const double b() const { assert( mParsed ); return mB; };
  const double c() const { assert( mParsed ); return mC; };
  const QString error() const { return mError; };
  // internal...
  void yyinput( char* buf, int& result, int max_size );
  void setOutput( FormulaNode* n );
private:
  bool mParsed;
  double mA;
  double mB;
  double mC;
  QCString mString;
  QString mError;
  int mPos;
  FormulaNode* mOutput;
  static Parser* sInstance;
  void setError( const char* s ) { mError = QString::fromUtf8( s ); };
  friend void yyerror( const char* s );
};


#endif
