private Expr buildLookaheadWithAmountCondition( String symbol, GExpansion expansion, int amount, NodeList<FormalParameter> params, NodeList<Expr> args) { String matchMethodName = "match" + symbol + "_lookahead" + incrementCount(symbol); NodeList<Stmt> stmts = buildLookaheadWithAmountCondition( Collections.singletonList(expansion.location()), 0, amount, params, args); stmts = stmts.append(returnStmt().withExpr(FAILED_LOOKAHEAD)); createMatchMethod(symbol, matchMethodName, expansion, stmts, emptyList()); return binaryExpr( matchMethodCall(matchMethodName, literalExpr(0), emptyList()), BinaryOp.NotEqual, FAILED_LOOKAHEAD); }
@Override protected ClassDecl contributeBody( ClassDecl decl, ImportManager importManager, TreeClassDescriptor[] arg) { importManager.addImports( listOf( importDecl(qualifiedName("org.jlato.internal.bu")).setOnDemand(true), importDecl(qualifiedName("org.jlato.internal.bu.coll")).setOnDemand(true), importDecl(qualifiedName("org.jlato.internal.bu.decl")).setOnDemand(true), importDecl(qualifiedName("org.jlato.internal.bu.expr")).setOnDemand(true), importDecl(qualifiedName("org.jlato.internal.bu.name")).setOnDemand(true), importDecl(qualifiedName("org.jlato.internal.bu.stmt")).setOnDemand(true), importDecl(qualifiedName("org.jlato.internal.bu.type")).setOnDemand(true), importDecl(qualifiedName("org.jlato.internal.parser.Token")), importDecl(qualifiedName("org.jlato.internal.parser.TokenType")), importDecl(qualifiedName("org.jlato.tree.Problem.Severity")), importDecl(qualifiedName("org.jlato.parser.ParseException")), importDecl(qualifiedName("org.jlato.tree.expr.AssignOp")), importDecl(qualifiedName("org.jlato.tree.expr.BinaryOp")), importDecl(qualifiedName("org.jlato.tree.expr.UnaryOp")), importDecl(qualifiedName("org.jlato.tree.decl.ModifierKeyword")), importDecl(qualifiedName("org.jlato.tree.type.Primitive")))); List<GProduction> allProductions = productions.getAll(); int memoizedProductionCount = MEMOIZE_ALL_MATCHES ? allProductions.size() : 0; if (!MEMOIZE_ALL_MATCHES) { for (GProduction production : allProductions) { if (production.memoizeMatches) memoizedProductionCount++; } } NodeList<MemberDecl> members = Trees.emptyList(); members = members.append( memberDecl( "protected int memoizedProductionCount() { return " + memoizedProductionCount + "; }") .build()); for (GProduction production : allProductions) { if (excluded(production)) continue; parseMethods = parseMethods.append(parseMethod(importManager, production)); } for (MethodDecl parseMethod : parseMethods) { members = members.append(parseMethod); String id = parseMethod.name().id(); int indexOfUnderscore = id.indexOf('_'); String symbol = id.substring("parse".length(), indexOfUnderscore == -1 ? id.length() : indexOfUnderscore); List<MethodDecl> methods = perSymbolMatchMethods.get(symbol); if (methods != null) { Collections.sort(methods, (m1, m2) -> m1.name().id().compareTo(m2.name().id())); members = members.appendAll(listOf(methods)); } } return decl.withMembers(members); }
private NodeList<Stmt> parseStatementsFor( String symbol, GExpansion expansion, NodeList<FormalParameter> hintParams, boolean optional) { NodeList<Stmt> stmts = emptyList(); switch (expansion.kind) { case Sequence: stmts = stmts.appendAll(parseStatementsForChildren(symbol, expansion, hintParams, false)); break; case ZeroOrOne: { if (expansion.children.size() == 1 && expansion.children.get(0).kind == GExpansion.Kind.Choice) { stmts = stmts.appendAll(parseStatementsForChildren(symbol, expansion, hintParams, true)); } else { stmts = stmts.append( ifStmt( matchCondition( symbol, expansion, hintParams, hintParams.map(p -> p.id().get().name())), blockStmt() .withStmts( parseStatementsForChildren(symbol, expansion, hintParams, false)))); } break; } case ZeroOrMore: { stmts = stmts.append( whileStmt( matchCondition( symbol, expansion, hintParams, hintParams.map(p -> p.id().get().name())), blockStmt() .withStmts( parseStatementsForChildren(symbol, expansion, hintParams, false)))); break; } case OneOrMore: { stmts = stmts.append( doStmt( blockStmt() .withStmts( parseStatementsForChildren(symbol, expansion, hintParams, false)), matchCondition( symbol, expansion, hintParams, hintParams.map(p -> p.id().get().name())))); break; } case Choice: { List<IfStmt> expansionsIfStmt = expansion .children .stream() .map( e -> ifStmt( matchCondition( symbol, e, hintParams, hintParams.map(p -> p.id().get().name())), blockStmt() .withStmts(parseStatementsFor(symbol, e, hintParams, false)))) .collect(Collectors.toList()); Collections.reverse(expansionsIfStmt); stmts = stmts.append( listOf(expansionsIfStmt) .foldRight( (Stmt) (optional ? null : blockStmt() .withStmts( listOf( throwStmt( methodInvocationExpr( name("produceParseException")) .withArgs( listOf( firstTerminalsOf(expansion) .stream() .map(this::prefixedConstant) .collect( Collectors.toList()))))))), (ifThenClause, elseClause) -> optional && elseClause == null ? ifThenClause : ifThenClause.withElseStmt(elseClause))); break; } case NonTerminal: { Expr call = methodInvocationExpr(name("parse" + upperCaseFirst(expansion.symbol))) .withArgs(expansion.hints.appendAll(expansion.arguments)); stmts = stmts.append( expressionStmt( expansion.name == null ? call : assignExpr(name(expansion.name), AssignOp.Normal, call))); break; } case Terminal: { Expr argument = prefixedConstant(expansion.symbol); Expr call = methodInvocationExpr(name("parse")).withArgs(listOf(argument)); stmts = stmts.append( expressionStmt( expansion.name == null ? call : assignExpr(name(expansion.name), AssignOp.Normal, call))); break; } case Action: { stmts = stmts.appendAll(expansion.action); break; } default: } return stmts; }