# parserc-java **Repository Path**: byx2000/parserc-java ## Basic Information - **Project Name**: parserc-java - **Description**: java开发的解析器组合子(Parser Combinator)库 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 2 - **Created**: 2022-05-04 - **Last Updated**: 2024-08-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: parser, parser-combinator, Java ## README # parserc-java parserc-java是用java实现的解析器组合子(Parser Combinator)库,可以方便地以自底向上的方式构建复杂的解析器。 ## 计算器示例 ```java /** * 表达式计算器 */ class ExprCalc { private static final Parser digit = range('0', '9'); private static final Parser add = ch('+').trim(); private static final Parser sub = ch('-').trim(); private static final Parser mul = ch('*').trim(); private static final Parser div = ch('/').trim(); private static final Parser lp = ch('(').trim(); private static final Parser rp = ch(')').trim(); private static final Parser digits = digit.many1().map(ExprCalc::join); private static final Parser integer = digits.map(Double::parseDouble); private static final Parser decimal = seq(digits, ch('.'), digits).map(ExprCalc::join).map(Double::parseDouble); private static final Parser number = decimal.or(integer).trim(); private static final Parser bracketExpr = skip(lp).and(lazy(() -> ExprCalc.expr)).skip(rp); private static final Parser negFact = skip(sub).and(lazy(() -> ExprCalc.fact)).map(e -> -e); private static final Parser fact = oneOf(number, bracketExpr, negFact); private static final Parser term = fact.and(mul.or(div).and(fact).many()).map(ExprCalc::calc); private static final Parser expr = term.and(add.or(sub).and(term).many()).map(ExprCalc::calc); private static final Parser parser = expr.end(); private static String join(List list) { return list.stream().map(Objects::toString).collect(Collectors.joining()); } private static Double calc(Pair>> p) { double res = p.getFirst(); for (Pair pp : p.getSecond()) { switch (pp.getFirst()) { case '+': res += pp.getSecond(); break; case '-': res -= pp.getSecond(); break; case '*': res *= pp.getSecond(); break; case '/': res /= pp.getSecond(); break; } } return res; } public static Double eval(String input) { return parser.parse(input); } } ``` ## JSON示例 ```java /** * json解析器 */ class JsonParser { private static final Parser digit = range('0', '9').map(Objects::toString); private static final Parser digits = digit.many1().map(JsonParser::join); private static final Parser integer = digits.map(Integer::parseInt).trim(); private static final Parser decimal = seq(digits, ch('.'), digits).map(JsonParser::join).map(Double::parseDouble); private static final Parser string = skip(ch('"')).and(not('"').many()).skip(ch('"')).map(JsonParser::join); private static final Parser bool = strs("true", "false").map(Boolean::parseBoolean).trim(); private static final Parser objStart = ch('{').trim(); private static final Parser objEnd = ch('}').trim(); private static final Parser arrStart = ch('[').trim(); private static final Parser arrEnd = ch(']').trim(); private static final Parser colon = ch(':').trim(); private static final Parser comma = ch(',').trim(); private static final Parser lazyJsonObj = lazy(() -> JsonParser.jsonObj); private static final Parser> jsonObjList = lazyJsonObj.and(skip(comma).and(lazyJsonObj).many()) .map(r -> reduceList(r.getFirst(), r.getSecond())); private static final Parser> arr = skip(arrStart).and(jsonObjList.opt(Collections.emptyList())).skip(arrEnd); private static final Parser> pair = string.skip(colon).and(lazyJsonObj); private static final Parser>> pairList = pair.and(skip(comma).and(pair).many()) .map(r -> reduceList(r.getFirst(), r.getSecond())); private static final Parser> obj = skip(objStart).and(pairList.opt(Collections.emptyList())).skip(objEnd) .map(ps -> ps.stream().collect(Collectors.toMap(Pair::getFirst, Pair::getSecond))); private static final Parser jsonObj = oneOf(decimal, integer, string, bool, arr, obj); private static final Parser parser = jsonObj.end(); private static String join(List list) { return list.stream().map(Objects::toString).collect(Collectors.joining("")); } private static List reduceList(T first, List remain) { List list = new ArrayList<>(); list.add(first); list.addAll(remain); return list; } public static Object parse(String input) { return parser.parse(input); } } ```