// This program is based on the the paper // "Monadic Parser Combinators" // by Graham Hutton and Erik Meijer. #include #include #define FCPP_ENABLE_LAMBDA #include "prelude.h" using std::cout; using std::endl; using std::string; using std::cin; using std::ostream; using namespace fcpp; typedef List String; struct ParserM { // M a = String -> [(a,String)] // We use indirect functoids as a representation type, since we will // often need two functions with different behaviors (but the same // signatures) to appear to have the same type. template struct Rep { typedef Fun1 > > Type; }; template struct UnRep { typedef typename RT::ResultType::ElementType::first_type Type; }; // ReRep is a type-identity in Haskell; here it "indirect"ifies the // type, so direct functoids are turned into indirect ones so that // only the signature information appears in the type. template struct ReRep { typedef typename Rep::Type>::Type Type; }; struct XUnit { template struct Sig : public FunType::Type> {}; template typename Sig::ResultType operator()( const A& a ) const { LambdaVar<1> S; return lambda(S)[ cons[makePair[a,S],NIL] ]; } }; typedef Full1 Unit; static Unit unit; struct XBind { template struct Sig : public FunType::Type>::ResultType>::Type> {}; template typename Sig::ResultType operator()( const M& m, const K& k ) const { LambdaVar<1> P; LambdaVar<2> S; return lambda(S)[ concat[ compM() [ k[fst[P]][snd[P]] | P <= m[S] ] ] ]; } }; typedef Full2 Bind; static Bind bind; typedef Fun1 Zero; static Zero zero; }; ParserM::Unit ParserM::unit; ParserM::Bind ParserM::bind; ParserM::Zero ParserM::zero = ignore( const_(NIL) ); struct XItem : public CFunType > > { OddList > operator()( const String& s ) const { if( null(s) ) return NIL; else return cons( makePair( head(s), tail(s) ), NIL ); } }; typedef Full1 Item; Item item; struct XPlusP { template struct Sig : public FunType::ResultType, typename RT::ResultType>::ResultType> {}; template typename Sig::ResultType operator()( const P& p, const Q& q, const String& s ) const { return p(s) ^cat^ curry1(q,s); } }; typedef Full3 PlusP; PlusP plusP; template struct XManyM { // Monad a -> Monad [a] template struct Sig : public FunType::Type, typename LEType,LV<2> >,GETS<1,MA>,GETS<2,CALL >,MA> > > > >::Type, typename RT::Type, List::Type> >::ResultType>::ResultType> {}; template typename Sig::ResultType operator()( const MA& ma ) const { typedef typename Monad::template UnRep::Type AA; LambdaVar<1> A; LambdaVar<2> AS; return lambda()[ compM()[ cons(A,AS) | A <= ma, AS <= makeFull1(*this)[ma] ] ]() ^plusM()^ unitM()( List() ); } }; // Just using parser version here: Parser a -> Parser [a] typedef Full1 > Many; Many many; // sat :: (char -> bool) -> Parser char struct XSat { template struct Sig : public FunType,GETS<1,Item>, GUARD > > > > >::Type>::ResultType> {}; template typename Sig

::ResultType operator()( const P& p ) const { LambdaVar<1> C; return lambda()[ compM()[ C | C<=item, guard[p[C]] ] ](); } }; typedef Full1 Sat; Sat sat; struct XCharP : public CFunType::ResultType>::ResultType> { RT::ResultType>::ResultType operator()( char c ) const { return sat( equal(c) ); } }; typedef Full1 CharP; CharP charP; struct XBetween { template struct Sig : public FunType {}; template bool operator()( const T& goal, const T& lower, const T& upper ) const { return lessEqual(goal,upper) && greaterEqual(goal,lower); } }; typedef Full3 Between; Between between; typedef RT ::ResultType>::ResultType Digit; Digit digit = sat( between(_,'0','9') ); typedef Digit Lower; Lower lower = sat( between(_,'a','z') ); typedef Digit Upper; Upper upper = sat( between(_,'A','Z') ); typedef RT::ResultType Letter; Letter letter = lower ^plusP^ upper; typedef RT::ResultType AlphaNum; AlphaNum alphaNum = letter ^plusP^ digit; template struct XMany1M { // Monad a -> Monad [a] template struct Sig : public FunType,LV<2> > >,GETS<1,MA>,GETS<2, CALL >,MA> > > > >::Type> {}; template typename Sig::ResultType operator()( const MA& ma ) const { LambdaVar<1> A; LambdaVar<2> AS; return lambda()[ compM() [ delay[cons[A,AS]] | A <= ma, AS <= makeFull1(XManyM())[ma] ] ](); } }; // Just using parser version here: Parser a -> Parser [a] typedef Full1 > Many1; Many1 many1; struct XChainl1 { // Parser a -> Parser (a->a->a) -> Parser a // parses a series of items separated by left-associative operators typedef BindM::Type BIND; typedef UnitM::Type UNIT; template struct XRest { P p; O op; XRest( const P& pp, const O& oo ) : p(pp), op(oo) {} template struct Sig : public FunType::Type> {}; template typename Sig::ResultType operator()( const X& x ) const { LambdaVar<1> F; LambdaVar<2> Y; return (op ^BIND()^ lambda(F)[ p %BIND()% lambda(Y)[ makeFull1(*this)[ F[x,Y] ] ] ]) ^plusP^ UNIT()(x); } }; template struct Sig : public FunType > >::ResultType> {}; template typename Sig::ResultType operator()( const P& p, const O& op ) const { return p ^BIND()^ makeFull1(XRest(p,op)); } }; typedef Full2 Chainl1; Chainl1 chainl1; struct XChainr1 { // Parser a -> Parser (a->a->a) -> Parser a // parses a series of items separated by right-associative operators template struct Sig : public FunType::Type>::Type> {}; template typename Sig::ResultType operator()( const P& p, const O& op ) const { LambdaVar<1> F; LambdaVar<2> X; LambdaVar<3> Y; return p ^bindM()^ lambda(X)[ compM() [ F[X,Y] | F <= op, Y <= makeFull2(*this)[p][op] ] %plusP% unitM()[X] ]; } }; typedef Full2 Chainr1; Chainr1 chainr1; struct XChainl { template struct Sig : public FunType::ResultType, typename RT::Type,V>::ResultType>::ResultType> {}; template typename Sig::ResultType operator()( const P& p, const O& op, const V& v ) const { return (p ^chainl1^ op) ^plusP^ unitM()(v); } }; typedef Full3 Chainl; Chainl chainl; struct XChainr { template struct Sig : public FunType::ResultType, typename RT::Type,V>::ResultType>::ResultType> {}; template typename Sig::ResultType operator()( const P& p, const O& op, const V& v ) const { return (p ^chainr1^ op) ^plusP^ unitM()(v); } }; typedef Full3 Chainr; Chainr chainr; typedef RT,LV<3>,CALL >,LV<3> > > >,CALL::Type,CALL,char> >,GETS<4,Digit> >, CALL::Type,LV<1> > > > > >::Type>::ResultType Nat; Nat xnat() { LambdaVar<1> OP; LambdaVar<2> M; LambdaVar<3> N; LambdaVar<4> X; return lambda()[ let[ OP == lambda(M,N)[ plus[multiplies[10,M],N] ] ].in[ compM()[ construct1()[minus[X,'0']] | X<=digit ] %chainl1% unitM()[OP] ] ](); } Nat nat = xnat(); typedef RT >::Type,Negate>,CALL >,CALL< UnitM::Type,CALL >::Type,Id> > > >, COMP,LV<2> >,GETS<1,LV<3> >,GETS<2,Nat> > > > >::Type>::ResultType IntP; IntP xintp() { LambdaVar<1> F; LambdaVar<2> N; LambdaVar<3> OP; Construct1 >::Type cf = construct1 >(); return lambda()[ let[ OP == compM()[ cf[negate] | charP['-'] ] %plusP% unitM()[ cf[id] ] ] .in[ compM()[ F[N] | F<=OP, N<=nat ] ] ](); } IntP intP = xintp(); struct XSepBy1 { // Parser a -> Parser b -> Parser [a] // parses "p (sep p)*", throwing away the separators template struct Sig : public FunType,LV<2> > >,GETS<1,P>,GETS<2,CALL,S,GETS<3,P> > > > > > >::Type>::ResultType> {}; template typename Sig::ResultType operator()( const P& p, const S& sep ) const { LambdaVar<1> X; LambdaVar<2> XS; LambdaVar<3> Y; return lambda()[ compM()[ delay[cons[X,XS]] | X <= p, XS <= many[ compM()[ Y | sep, Y <= p ] ] ] ](); } }; typedef Full2 SepBy1; SepBy1 sepBy1; struct XBracket { template struct Sig : public FunType,O,GETS<1,P>,C> > >::Type>::ResultType> {}; template typename Sig::ResultType operator()( const O& open, const P& p, const C& close ) const { LambdaVar<1> X; return lambda()[ compM()[ X | open, X<=p, close ] ](); } }; typedef Full3 Bracket; Bracket bracket; struct XSepBy { template struct Sig : public FunType::ResultType, typename RT::Type,List::Type> >::ResultType>::ResultType> {}; template typename Sig::ResultType operator()( const P& p, const S& sep ) const { typedef typename ParserM::UnRep

::Type A; List l = NIL; return (p ^sepBy1^ sep) ^plusP^ unitM()( l ); } }; typedef Full2 SepBy; SepBy sepBy; struct XOps { // [(Parser a, b)] -> Parser b // given a list of pair, returns a parser template struct Sig : public FunType >,CALL > >, GETS<1,X> > > >::Type>::ResultType>::ResultType> {}; template typename Sig::ResultType operator()( const X& xs ) const { LambdaVar<1> P; return foldr1( plusP, lambda()[ compM()[ compM()[ snd[P] | fst[P] ] | P <= xs ] ]() ); } }; typedef Full1 Ops; Ops ops; ////////////////////////////////////////////////////////////////////// ostream& operator<<( ostream& o, const String& s ) { string ss( s.begin(), s.end() ); return o << "\"" << ss << "\""; } template ostream& operator<<( ostream& o, const std::pair& p ) { return o << "(" << p.first << "," << p.second << ")"; } template ostream& operator<<( ostream& o, OddList l ) { o << "["; if(l) for(;;) { o << head(l); l = tail(l); if(l) o << ","; else break; } return o << "]"; } template ostream& operator<<( ostream& o, List l ) { return o << l.force(); } ////////////////////////////////////////////////////////////////////// int my_pow( int x, int y ) { int r = 1; while(y) { r *= x; --y; } return r; } typedef ParserM::Rep::Type ExprP; extern ExprP exprP; typedef RT::ResultType,Fun2 > > >::ResultType AddOp; AddOp xaddOp() { typedef Fun2 F; return ops( list_with( makePair( charP('+'), F(plus) ), makePair( charP('-'), F(minus) ) ) ); } AddOp addOp = xaddOp(); typedef AddOp ExpOp; ExpOp xexpOp() { typedef Fun2 F; return ops( list_with( makePair(charP('^'),F(ptr_to_fun(&my_pow))) ) ); } ExpOp expOp = xexpOp(); typedef RT::ResultType, ExprP,RT::ResultType>::ResultType>::ResultType Factor; Factor xfactor() { static Factor result = nat ^plusP^ bracket( charP('('), exprP, charP(')') ); return result; } typedef ExprP Term; // I am too lazy to direct-type this Term xterm() { static Term result = thunkFuncToFunc(ptr_to_fun(&xfactor)) ^chainr1^ expOp; return result; } ExprP xexprP() { return thunkFuncToFunc(ptr_to_fun(&xterm)) ^chainl1^ addOp; } ExprP exprP = xexprP(); ////////////////////////////////////////////////////////////////////// // Here I just want to show the straightforward way using indirect // functoid types: typedef ParserM::Rep::Type P_int; P_int dummy = ignore(const_(cons(makePair(0,String()),NIL))); P_int group=dummy, factor=dummy, term=dummy, expression=dummy; int main() { LambdaVar<91> S; factor = lambda(S)[ (nat %plusP% dereference[&group])[S] ]; term = factor ^chainr1^ expOp; expression = term ^chainl1^ addOp; group = bracket( charP('('), expression, charP(')') ); ////////////////////////////////////////////////////////////////////// string ss; cout << "Enter a string to parse (e.g. '1+2^3-(2-1)^5'):" << endl; getline(cin,ss); String s( ss.begin(), ss.end() ); length(s); // force evaluation typedef ParserM P; LambdaVar<1> X; List > lpcs = lambda()[ compM

() [ X | X <= item ] ]()(s); cout << "item: " << lpcs << endl; cout << "List of expression parses:" << endl << exprP(s) << endl; cout << "List of expression parses:" << endl << expression(s) << endl; /* This works. I did it just to prove a point. List > lpss; LambdaVar<12> lower; LambdaVar<13> upper; LambdaVar<14> letter; LambdaVar<15> word; lpss = lambda()[ let[ lower == compM

()[ X | X<=item, guard[logicalAnd[greaterEqual[X,'a'], lessEqual[X,'z']]]], upper == compM

()[ X | X<=item, guard[logicalAnd[greaterEqual[X,'A'], lessEqual[X,'Z']]]], letter == lower %plusP% upper, word == many[letter] ].in[ word[s] ] ](); cout << lpss << endl; */ /* FIX THIS comment window List > lpss; lpss = many(letter)(s); cout << "many(letter): " << lpss << endl; lpss = many1(letter)(s); cout << "many1(letter): " << lpss << endl; List > lpis; lpis = nat(s); cout << "nat: " << lpis << endl; List,String> > lplis; lplis = bracket( charP('['), intP ^sepBy^ charP(','), charP(']') )(s); cout << "list of ints: " << lplis << endl; cout << "List of expression parses:" << endl << exprP(s) << endl; LambdaVar<21> ex; LambdaVar<22> tm; LambdaVar<23> fc; LambdaVar<24> S; Fun1 > > dummy = ignore( const_( List >() ) ); cout << "Expr parses via letrec defs:" << endl << lambda()[ letrec[ // need some way to break recursion... one way is shown below // ex == lambda(S)[ (tm %chainl1% addOp)[S] ], ex == if2[true,lambda(S)[ (tm %chainl1% addOp)[S] ],dummy], tm == lambda(S)[ (fc %chainr1% expOp)[S] ], fc == lambda(S)[ (nat %plusP% bracket[charP['('],ex,charP[')']])[S] ] ].in[ ex[s] ] ]() << endl; */ }