Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
// Copyright (c) 2008 by Dr. Colin Hirsch // Please see license.txt for license. #include <pegtl.hh> namespace calculator { // The first program used during development and debugging // of the library that uses actions. It evaluates each command // line argument as arithmetic expression consisting of // - integers with optional sign, // - the four basic arithmetic operations, // - grouping brackets. // For example input "3 * ( -7 + 9)" yields result 6. using namespace pegtl; // The state. // Canonical use of an evaluation stack, // here implemented with a std::vector. typedef int value_type; typedef std::vector< value_type > stack_type; // Helper function that's [exception] safe with ints as values. value_type pull( stack_type & s ) { assert( ! s.empty() ); value_type nrv( s.back() ); s.pop_back(); return nrv; } // The actions. // This action converts the matched sub-string // to an integer and pushes it on the stack, // which must be its only additional state argument. // Deriving from action_base<> is necessary since // version 0.26; the base class takes care of the pretty- // printing for diagnostic messages, it is necessary for // all action classes that do not derive from a rule class. struct push_action : action_base< push_action > { static void apply( const std::string & m, stack_type & s ) { s.push_back( string_to_signed< value_type >( m ) ); } }; // Class op_action performs an operation on the two // top-most elements of the evaluation stack. This // should always be possible in the sense that the // grammar must make sure to only apply this action // when sufficiently many operands are on the stack. template< typename Operation > struct op_action : action_base< op_action< Operation > > { static void apply( const std::string &, stack_type & s ) { const value_type a = pull( s ); const value_type b = pull( s ); s.push_back( Operation()( b, a ) ); } }; template<> struct op_action< std::divides< value_type > > : action_base< op_action< std::divides< value_type > > > { template< typename State > static void apply( const std::string &, State & s ) { const value_type rhs = pull( s ); if ( ! rhs ) { PEGTL_THROW( "pegtl: division by zero" ); } const value_type lhs = pull( s ); s.push_back( std::divides< value_type >()( lhs, rhs ) ); } }; // The grammar rules. struct read_number : seq< opt< one< '+', '-' > >, plus< digit > > {}; // This rule uses the rule read_number to match a // number in the input and, on success, applies the // push_action to the matched sub-string and the // state, in calculator.cc: an instance of stack_type, // in order to push the number on the evaluation stack. struct push_rule : pad< ifapply< read_number, push_action >, space > {}; template< int C > struct calc_pad : pad_one< C, space > {}; struct read_open : calc_pad< '(' > {}; struct read_close : calc_pad< ')' > {}; struct read_expr; struct read_atom : sor< push_rule, seq< read_open, read_expr, read_close > > {}; struct read_mul : ifapply< ifmust< calc_pad< '*' >, read_atom >, op_action< std::multiplies< value_type > > > {}; struct read_div : ifapply< ifmust< calc_pad< '/' >, read_atom >, op_action< std::divides< value_type > > > {}; struct read_prod : seq< read_atom, star< sor< read_mul, read_div > > > {}; struct read_add : ifapply< ifmust< calc_pad< '+' >, read_prod >, op_action< std::plus< value_type > > > {}; struct read_sub : ifapply< ifmust< calc_pad< '-' >, read_prod >, op_action< std::minus< value_type > > > {}; struct read_expr : seq< read_prod, star< sor< read_add, read_sub > > > {}; struct read_calc : seq< read_expr, space_until_eof > {}; } // calculator int main( int argc, char ** argv ) { for ( int arg = 1; arg < argc; ++arg ) { calculator::stack_type stack; pegtl::basic_parse_string< calculator::read_calc >( argv[ arg ], stack ); assert( stack.size() == 1 ); std::cerr << "input " << argv[ arg ] << " result " << stack.front() << "\n"; } return 0; }
This paste will be private.
From the Design Piracy series on my blog: