private Expr createMatchMethodAndCallFor( String symbol, String namePrefix, GExpansion expansion, Expr outerLookahead, NodeList<FormalParameter> params, NodeList<Expr> args, boolean memoize) { switch (expansion.kind) { case LookAhead: Expr semanticLookahead = expansion.semanticLookahead; if (semanticLookahead != null) { if (semanticLookahead.equals(methodInvocationExpr(name("isLambda")))) { semanticLookahead = methodInvocationExpr(name("isLambda")).withArgs(listOf(outerLookahead)); } else if (semanticLookahead.equals(methodInvocationExpr(name("isCast")))) { semanticLookahead = methodInvocationExpr(name("isCast")).withArgs(listOf(outerLookahead)); } return conditionalExpr(semanticLookahead, outerLookahead, FAILED_LOOKAHEAD); } return null; case Sequence: { int index = memoize ? memoizationIndex++ : -1; NodeList<Stmt> stmts = emptyList(); int count = 0; for (GExpansion child : expansion.children) { Expr childCall = createMatchMethodAndCallFor( symbol, namePrefix + "_" + ++count, child, LOOKAHEAD, params, params.map(p -> p.id().get().name()), false); if (childCall == null) continue; stmts = stmts.append(expressionStmt(assignExpr(LOOKAHEAD, AssignOp.Normal, childCall))); stmts = stmts.append( ifStmt( binaryExpr(LOOKAHEAD, BinaryOp.Equal, FAILED_LOOKAHEAD), memoize ? stmt("return memoizeMatch(initialLookahead, " + index + ", -1);") .build() : stmt("return -1;").build())); } if (memoize) { stmts = stmts.prependAll( listOf( stmt("int initialLookahead = lookahead;").build(), stmt("int memoizedMatch = memoizedMatch(initialLookahead, " + index + ");") .build(), stmt("if (memoizedMatch > -2) return memoizedMatch;").build())); } stmts = stmts.append( memoize ? stmt("return memoizeMatch(initialLookahead, " + index + ", lookahead);") .build() : stmt("return lookahead;").build()); createMatchMethod(symbol, namePrefix, expansion, stmts, params); return matchMethodCall(namePrefix, outerLookahead, args); } case Choice: { NodeList<Stmt> stmts = emptyList(); stmts = stmts.append( expressionStmt( variableDeclarationExpr( localVariableDecl(primitiveType(Primitive.Int)) .withVariables( listOf( variableDeclarator(variableDeclaratorId(LOOKAHEAD_NEW))))))); int count = 0; for (GExpansion child : expansion.children) { Expr childCall = createMatchMethodAndCallFor( symbol, namePrefix + "_" + ++count, child, LOOKAHEAD, params, params.map(p -> p.id().get().name()), false); if (childCall == null) continue; stmts = stmts.append(expressionStmt(assignExpr(LOOKAHEAD_NEW, AssignOp.Normal, childCall))); stmts = stmts.append( ifStmt( binaryExpr(LOOKAHEAD_NEW, BinaryOp.NotEqual, FAILED_LOOKAHEAD), returnStmt().withExpr(LOOKAHEAD_NEW))); } stmts = stmts.append(returnStmt().withExpr(FAILED_LOOKAHEAD)); createMatchMethod(symbol, namePrefix, expansion, stmts, params); return matchMethodCall(namePrefix, outerLookahead, args); } case ZeroOrOne: { NodeList<Stmt> stmts = emptyList(); stmts = stmts.append( expressionStmt( variableDeclarationExpr( localVariableDecl(primitiveType(Primitive.Int)) .withVariables( listOf( variableDeclarator(variableDeclaratorId(LOOKAHEAD_NEW))))))); Expr childCall = createMatchMethodAndCallFor( symbol, namePrefix + "_" + 1, GExpansion.sequence(expansion.children), LOOKAHEAD, params, params.map(p -> p.id().get().name()), false); stmts = stmts.append(expressionStmt(assignExpr(LOOKAHEAD_NEW, AssignOp.Normal, childCall))); stmts = stmts.append( ifStmt( binaryExpr(LOOKAHEAD_NEW, BinaryOp.NotEqual, FAILED_LOOKAHEAD), returnStmt().withExpr(LOOKAHEAD_NEW))); stmts = stmts.append(returnStmt().withExpr(LOOKAHEAD)); createMatchMethod(symbol, namePrefix, expansion, stmts, params); return matchMethodCall(namePrefix, outerLookahead, args); } case ZeroOrMore: { NodeList<Stmt> stmts = emptyList(); stmts = stmts.append( expressionStmt( variableDeclarationExpr( localVariableDecl(primitiveType(Primitive.Int)) .withVariables( listOf( variableDeclarator(variableDeclaratorId(LOOKAHEAD_NEW))))))); Expr childCall = createMatchMethodAndCallFor( symbol, namePrefix + "_" + 1, GExpansion.sequence(expansion.children), LOOKAHEAD, params, params.map(p -> p.id().get().name()), false); stmts = stmts.append(expressionStmt(assignExpr(LOOKAHEAD_NEW, AssignOp.Normal, childCall))); stmts = stmts.append( whileStmt( binaryExpr(LOOKAHEAD_NEW, BinaryOp.NotEqual, FAILED_LOOKAHEAD), blockStmt() .withStmts( listOf( expressionStmt( assignExpr(LOOKAHEAD, AssignOp.Normal, LOOKAHEAD_NEW)), expressionStmt( assignExpr(LOOKAHEAD_NEW, AssignOp.Normal, childCall)))))); stmts = stmts.append(returnStmt().withExpr(LOOKAHEAD)); createMatchMethod(symbol, namePrefix, expansion, stmts, params); return matchMethodCall(namePrefix, outerLookahead, args); } case OneOrMore: { NodeList<Stmt> stmts = emptyList(); stmts = stmts.append( expressionStmt( variableDeclarationExpr( localVariableDecl(primitiveType(Primitive.Int)) .withVariables( listOf( variableDeclarator(variableDeclaratorId(LOOKAHEAD_NEW))))))); Expr childCall = createMatchMethodAndCallFor( symbol, namePrefix + "_" + 1, GExpansion.sequence(expansion.children), LOOKAHEAD, params, params.map(p -> p.id().get().name()), false); stmts = stmts.append(expressionStmt(assignExpr(LOOKAHEAD_NEW, AssignOp.Normal, childCall))); stmts = stmts.append( ifStmt( binaryExpr(LOOKAHEAD_NEW, BinaryOp.Equal, FAILED_LOOKAHEAD), returnStmt().withExpr(FAILED_LOOKAHEAD))); stmts = stmts.append( whileStmt( binaryExpr(LOOKAHEAD_NEW, BinaryOp.NotEqual, FAILED_LOOKAHEAD), blockStmt() .withStmts( listOf( expressionStmt( assignExpr(LOOKAHEAD, AssignOp.Normal, LOOKAHEAD_NEW)), expressionStmt( assignExpr(LOOKAHEAD_NEW, AssignOp.Normal, childCall)))))); stmts = stmts.append(returnStmt().withExpr(LOOKAHEAD)); createMatchMethod(symbol, namePrefix, expansion, stmts, params); return matchMethodCall(namePrefix, outerLookahead, args); } case NonTerminal: { return createMatchMethodAndCallFor(expansion.symbol, outerLookahead, expansion.hints); } case Terminal: { return matchCall(expansion.symbol, LOOKAHEAD); } case Action: { return null; } default: } return null; }
private Expr matchCondition( String symbol, GExpansion expansion, NodeList<FormalParameter> params, NodeList<Expr> args) { if (expansion.children != null && !expansion.children.isEmpty()) { GExpansion firstChild = expansion.children.get(0); if (firstChild.kind == GExpansion.Kind.LookAhead) { Expr lookaheadCondition = null; Expr semanticLookaheadCondition = firstChild.semanticLookahead; int amount = firstChild.amount; List<GExpansion> children = firstChild.children; boolean negativeLookahead = firstChild.negativeLookahead; if (semanticLookaheadCondition != null) { if (semanticLookaheadCondition.equals(methodInvocationExpr(name("isLambda")))) { semanticLookaheadCondition = methodInvocationExpr(name("isLambda")).withArgs(listOf(literalExpr(0))); } else if (semanticLookaheadCondition.equals(methodInvocationExpr(name("isCast")))) { semanticLookaheadCondition = methodInvocationExpr(name("isCast")).withArgs(listOf(literalExpr(0))); } lookaheadCondition = negativeLookahead ? unaryExpr(UnaryOp.Not, semanticLookaheadCondition) : semanticLookaheadCondition; } if (amount != -1) { Expr amountLookaheadCondition = buildLookaheadWithAmountCondition(symbol, expansion, amount, params, args); lookaheadCondition = lookaheadCondition == null ? amountLookaheadCondition : binaryExpr(lookaheadCondition, BinaryOp.And, amountLookaheadCondition); } if (children != null) { String matchMethodName = "match" + symbol + "_lookahead" + incrementCount(symbol); Expr call = createMatchMethodAndCallFor( symbol, matchMethodName, GExpansion.sequence(children), literalExpr(0), params, args, false); Expr descriptiveLookaheadCondition = binaryExpr( call, negativeLookahead ? BinaryOp.Equal : BinaryOp.NotEqual, literalExpr(-1)); lookaheadCondition = lookaheadCondition == null ? descriptiveLookaheadCondition : binaryExpr( lookaheadCondition, negativeLookahead ? BinaryOp.Or : BinaryOp.And, descriptiveLookaheadCondition); } return lookaheadCondition; } } return binaryExpr( matchCall(firstTerminalsOf(expansion), literalExpr(0)), BinaryOp.NotEqual, FAILED_LOOKAHEAD); }