toycalc_parser.hh

Toycalc example - parser declaration
Constructs a parse tree of toycalc::expression objects. Each of the handling member functions return a new expression, which is added to the parse tree. The member function toycalc::parser::result, which is called at a newline, evaluates the parse tree recursively, and show the result on the standard output.
//
// $Id: toycalc_parser.hh,v 1.11 2004/03/09 02:37:56 cholm Exp $ 
//  
//  yaccmm.hh
//  Copyright (C) 2002 Christian Holm Christensen <cholm@nbi.dk> 
//
//  This library is free software; you can redistribute it and/or 
//  modify it under the terms of the GNU Lesser General Public License 
//  as published by the Free Software Foundation; either version 2.1 
//  of the License, or (at your option) any later version. 
//
//  This library 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 
//  Lesser General Public License for more details. 
// 
//  You should have received a copy of the GNU Lesser General Public 
//  License along with this library; if not, write to the Free 
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
//  02111-1307 USA 
//
/** @file   toycalc_parser.hh
    @author Christian Holm
    @date   Sat Dec 07 20:15:40 2002
    @brief  Parser class declaration */
#ifndef toycalc_parser_hh
#define toycalc_parser_hh

#ifndef toycalc_expression_hh
#include "toycalc_expression.hh"
#endif
#ifndef toycalc_refcounted_hh
#include "toycalc_ref_counted.hh"
#endif
#ifndef YLMM_basic_parser 
#include <ylmm/basic_parser.hh>
#endif
#ifndef YLMM_basic_scanner
#include <ylmm/basic_scanner.hh>
#endif
#ifndef __IOSTREAM__
#include <iostream>
#endif

namespace toycalc 
{
  /** Parser class for toy calculator 
      @ingroup toycalc 
  */
  class parser : public ylmm::basic_parser<ref_counted<expression> > 
  {
  public:
    typedef ref_counted<expression> token_type;
    typedef ylmm::basic_scanner<ref_counted<expression> > scanner_type;
  private:
    /** reference to scanner */    
    scanner_type& _scanner;
  public:
    /** Constuctor
        @param s reference to scanner  */
    parser(scanner_type& s) : _scanner(s) { prompt(); }
    virtual ~parser() {}
    /** Scan input
        @return The next token ID */
    int scan(void*) 
    { 
      if (need_where()) 
        return _scanner.next(*_token,*_location); 
      return _scanner.next(*_token);
    }
    /** show the prompt 
        @param nl Whether to preceed the prompt with a new line */
    void prompt(bool nl=false) 
    { 
      if (_scanner.current_buffer()->interactive())
        _messenger->message("%sprompt> ", (nl ? "\n" : "")); 
    }
    /** On errors, advance one line on error stream and show the
        prompt.  
        @param msg The message to print */
    void fatal(const char* msg) 
    { 
      ylmm::basic_parser<token_type>::fatal(msg); 
      prompt(true); 
    }
    /*@{*/
    /** @name Expression processing */
    /** Process a simple number 
        @param num A number 
        @return @a num */
    token_type number(const token_type& num) 
    { 
      return const_cast<token_type&>(num); 
    }
    /** Process an addition 
        @param lhs Left hand side 
        @param rhs Right hand side 
        @return A new toycalc::add object */
    token_type addition(const token_type& lhs, const token_type& rhs) 
    { 
      return new add(lhs, rhs); 
    }
    /** Process a subtraction 
        @param lhs Left hand side 
        @param rhs Right hand side 
        @return A new toycalc::subtract object */
    token_type subtraction(const token_type& lhs, const token_type& rhs) 
    { 
      return new subtract(lhs, rhs); 
    }
    /** Process a multiplication
        @param lhs Left hand side 
        @param rhs Right hand side 
        @return A new toycalc::multiply object */
    token_type multiplication(const token_type& lhs, const token_type& rhs) 
    { 
      return token_type(new multiply(lhs, rhs)); 
    }
    /** Process a division 
        @param lhs Left hand side 
        @param rhs Right hand side 
        @return A new toycalc::divide object */
    token_type division(const token_type& lhs, const token_type& rhs) 
    { 
      return token_type(new divide(lhs, rhs)); 
    }
    /** Process a minus 
        @param oper The operand expression
        @return a new toycalc::minus object */
    token_type negation(const token_type& oper) 
    { 
      return token_type(new minus(oper)); 
    }
    /** Process a precedence (pair of parentheis) 
        @param expr Expression to take precedence
        @return a new toycalc::precedence object */
    token_type precedence(const token_type& expr) 
    {
      return token_type(new toycalc::precedence(expr)); 
    }
    /** Process an expression 
        Evaluates the expression, and if an output messenger is
        defined, show the expression and the result on the messengers
        output stream 
        @param expr The expression to evaluate 
        @return @a expr */
    token_type result(const token_type& expr=0) { 
      if (expr) {
        double val = expr->evaluate(); 
        if (_messenger) 
          _messenger->message_stream() << *expr << " => " 
                                            << val << std::endl;
      }
      prompt();
      return const_cast<token_type&>(expr); 
    }
    /*@}*/
  };
}

#endif
//____________________________________________________________________
//
// EOF
//
Top of page
Christian Holm (home page)
Last update Fri Jul 8 12:58:03 2005
Created by DoxyGen 1.4.3-20050530