C. MyParser.java[2]

package MyParser;

import fj.P2;
import fj.F;
import fj.P1;
import static fj.pre.Equal.charEqual;
import static fj.P.p;
import fj.data.Option;
import fj.data.List;
import static fj.data.Validation.parseInt;
import static fj.data.List.asString;
import static fj.data.List.fromString;
import static fj.data.Option.some;
import static fj.data.Option.none;

import static java.lang.Character.*;
import static MyParser.Parser.*;

abstract class Parser<A> {
  abstract Option<P2<List<Character>, A>> parse(List<Character> s);

  Parser<A> or(final P1<Parser<A>> p2) {
    return new Parser<A>() {
      Option<P2<List<Character>, A>> parse(final List<Character> s) {
        final Option<P2<List<Character>, A>> v = Parser.this.parse(s);
        return v.isSome()
            ? v
            : p2._1().parse(s);
      }
    };
  }

  <B> Parser<B> anonymousBind(final P1<Parser<B>> q) {
    return bindParser(this, new F<A, Parser<B>>() {
      public Parser<B> f(final A _) {
        return q._1();
      }
    });
  }

  static <A> Parser<A> value(final A a) {
    return new Parser<A>() {
      Option<P2<List<Character>, A>> parse(final List<Character> s) {
        return some(p(s, a));
      }
    };
  }

  static <A> Parser<A> failed() {
    return new Parser<A>() {
      Option<P2<List<Character>, A>> parse(final List<Character> s) {
        return none();
      }
    };
  }

  static Parser<Character> character() {
    return new Parser<Character>() {
      Option<P2<List<Character>, Character>> parse(final List<Character> s) {
        return s.isEmpty()
            ? Option.<P2<List<Character>, Character>>none()
            : some(p(s.tail(), s.head()));
      }
    };
  }

  static <A, B> Parser<B> mapParser(final Parser<A> p, final F<A, B> f) {
    return new Parser<B>() {
      Option<P2<List<Character>, B>> parse(final List<Character> s) {
        return p.parse(s).map(new F<P2<List<Character>, A>, P2<List<Character>, B>>() {
          public P2<List<Character>, B> f(final P2<List<Character>, A> rc) {
            return rc.map2(f);
          }
        });
      }
    };
  }

  static <A, B> Parser<B> bindParser(final Parser<A> p, final F<A, Parser<B>> f) {
    return new Parser<B>() {
      Option<P2<List<Character>, B>> parse(final List<Character> s) {
        return p.parse(s).bind(new F<P2<List<Character>, A>, Option<P2<List<Character>, B>>>() {
          public Option<P2<List<Character>, B>> f(final P2<List<Character>, A> rc) {
            return f.f(rc._2()).parse(rc._1());
          }
        });
      }
    };
  }

  static <A> Parser<List<A>> sequenceParser(final List<Parser<A>> ps) {
    return ps.isEmpty()
        ? value(List.<A>nil())
        : bindParser(ps.head(), new F<A, Parser<List<A>>>() {
      public Parser<List<A>> f(final A a) {
        return mapParser(sequenceParser(ps.tail()), List.<A>cons().f(a));
      }
    });
  }

  static <A> Parser<List<A>> thisMany(final int n, final Parser<A> p) {
    return sequenceParser(List.replicate(n, p));
  }

  static <A> Parser<List<A>> list(final Parser<A> k) {
    return many1(k).or(new P1<Parser<List<A>>>() {
      public Parser<List<A>> _1() {
        return value(List.<A>nil());
      }
    });
  }

  static <A> Parser<List<A>> many1(final Parser<A> k) {
    return bindParser(k, new F<A, Parser<List<A>>>() {
      public Parser<List<A>> f(final A kx) {
        return mapParser(list(k), List.<A>cons().f(kx));
      }
    });
  }

  static Parser<Character> satisfy(final F<Character, Boolean> p) {
    return bindParser(character(), new F<Character, Parser<Character>>() {
      public Parser<Character> f(final Character c) {
        return p.f(c) ? value(c) : Parser.<Character>failed();
      }
    });
  }

  static Parser<Character> is(final char c) {
    return satisfy(charEqual.eq(c));
  }

  final static Parser<Character> digit = satisfy(new F<Character, Boolean>() {
    public Boolean f(final Character z) {
      return isDigit(z);
    }
  });

  final static Parser<Integer> natural = mapParser(list(digit), new F<List<Character>, Integer>() {
    public Integer f(final List<Character> z) {
      return parseInt(asString(z)).success();
    }
  });

  final static Parser<Character> space = satisfy(new F<Character, Boolean>() {
    public Boolean f(final Character z) {
      return isWhitespace(z);
    }
  });

  final static Parser<List<Character>> spaces = many1(space);

  final static Parser<Character> lower = satisfy(new F<Character, Boolean>() {
    public Boolean f(final Character z) {
      return isLowerCase(z);
    }
  });

  final static Parser<Character> upper = satisfy(new F<Character, Boolean>() {
    public Boolean f(final Character z) {
      return isUpperCase(z);
    }
  });

  final static Parser<Character> alpha = satisfy(new F<Character, Boolean>() {
    public Boolean f(final Character z) {
      return isLetter(z);
    }
  });

  final static Parser<Character> alphaNum = satisfy(new F<Character, Boolean>() {
    public Boolean f(final Character z) {
      return isLetterOrDigit(z);
    }
  });
}

class Person {
  final int age;
  final String firstName;
  final String surname;
  final char gender;
  final String phone;

  Person(final int age, final String firstName, final String surname, final char gender, final String phone) {
    this.age = age;
    this.firstName = firstName;
    this.surname = surname;
    this.gender = gender;
    this.phone = phone;
  }

  final static Parser<Integer> ageParser = natural;

  final static Parser<String> firstNameParser = bindParser(upper, new F<Character, Parser<String>>() {
    public Parser<String> f(final Character c) {
      return mapParser(list(lower), new F<List<Character>, String>() {
        public String f(final List<Character> cs) {
          return asString(cs.cons(c));
        }
      });
    }
  });

  final static Parser<String> surnameParser = bindParser(upper, new F<Character, Parser<String>>() {
    public Parser<String> f(final Character c) {
      return bindParser(thisMany(5, lower), new F<List<Character>, Parser<String>>() {
        public Parser<String> f(final List<Character> cs) {
          return mapParser(list(lower), new F<List<Character>, String>() {
            public String f(final List<Character> t) {
              return asString(cs.cons(c).append(t));
            }
          });
        }
      });
    }
  });

  final static Parser<Character> genderParser = is('m').or(new P1<Parser<Character>>() {
    public Parser<Character> _1() {
      return is('f');
    }
  });

  final static Parser<String> phoneBodyParser = mapParser(list(digit.or(new P1<Parser<Character>>() {
    public Parser<Character> _1() {
      return is('.');
    }
  }).or(new P1<Parser<Character>>() {
    public Parser<Character> _1() {
      return is('-');
    }
  })), new F<List<Character>, String>() {
    public String f(final List<Character> z) {
      return asString(z);
    }
  });

  final static Parser<String> phoneParser = bindParser(digit, new F<Character, Parser<String>>() {
    public Parser<String> f(final Character d) {
      return bindParser(phoneBodyParser, new F<String, Parser<String>>() {
        public Parser<String> f(final String z) {
          return mapParser(is('#'), new F<Character, String>() {
            public String f(final Character _) {
              return asString(fromString(z).cons(d));
            }
          });
        }
      });
    }
  });

  final static Parser<Person> personParser1 = bindParser(ageParser, new F<Integer, Parser<Person>>() {
    public Parser<Person> f(final Integer age) {
      return spaces.anonymousBind(new P1<Parser<Person>>() {
        public Parser<Person> _1() {
          return bindParser(firstNameParser, new F<String, Parser<Person>>() {
            public Parser<Person> f(final String firstName) {
              return spaces.anonymousBind(new P1<Parser<Person>>() {
                public Parser<Person> _1() {
                  return bindParser(surnameParser, new F<String, Parser<Person>>() {
                    public Parser<Person> f(final String surname) {
                      return spaces.anonymousBind(new P1<Parser<Person>>() {
                        public Parser<Person> _1() {
                          return bindParser(genderParser, new F<Character, Parser<Person>>() {
                            public Parser<Person> f(final Character gender) {
                              return spaces.anonymousBind(new P1<Parser<Person>>() {
                                public Parser<Person> _1() {
                                  return bindParser(phoneParser, new F<String, Parser<Person>>() {
                                    public Parser<Person> f(final String phone) {
                                      return value(new Person(age, firstName, surname, gender, phone));
                                    }
                                  });
                                }
                              });
                            }
                          });
                        }
                      });
                    }
                  });
                }
              });
            }
          });
        }
      });
    }
  });
}



[2] Requires Functional Java