jlibs.nblr.codegen.IfBlock Maven / Gradle / Ivy
/**
* Copyright 2015 Santhosh Kumar Tekuri
*
* The JLibs authors license this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package jlibs.nblr.codegen;
import jlibs.core.annotation.processing.Printer;
import jlibs.core.lang.StringUtil;
import jlibs.nblr.actions.ErrorAction;
import jlibs.nblr.actions.EventAction;
import jlibs.nblr.actions.PublishAction;
import jlibs.nblr.codegen.java.SyntaxClass;
import jlibs.nblr.matchers.Any;
import jlibs.nblr.matchers.Matcher;
import jlibs.nblr.matchers.Range;
import jlibs.nblr.rules.*;
import jlibs.nbp.NBParser;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static jlibs.core.annotation.processing.Printer.MINUS;
import static jlibs.core.annotation.processing.Printer.PLUS;
/**
* @author Santhosh Kumar T
*/
public class IfBlock implements Iterable{
public Matcher matcher;
public Path path;
protected int common = -1;
public final State state;
public final RootIf root;
public IfBlock parent;
public final List children = new ArrayList();
public IfBlock(State state){
this.state = state;
root = state.rootIF==null ? (RootIf)this : state.rootIF;
}
@Override
public Iterator iterator(){
return new Iterator(){
IfBlock block;
private IfBlock getNext(){
if(block==null)
return IfBlock.this;
if(block.children.size()>0){
return block.children.get(0);
}else{
IfBlock block = this.block;
IfBlock next = null;
while(block!=null){
List siblings = block.siblings();
int index = siblings.indexOf(block);
if(index+10){
depth++;
height = Math.max(height, depth);
block = block.children.get(0);
}else{
IfBlock next = null;
while(block.parent!=null){
int index = block.parent.children.indexOf(block);
if(index+1 siblings(){
return parent==null ? state.ifBlocks : parent.children;
}
private String blockStatement(boolean heightDecreased){
List siblings = siblings();
int index = siblings.indexOf(this);
if(state.ifBlocks.get(0).usesFinishAll())
index--;
String blockStmt = "";
if(index!=0 && !root.lookAheadRequired())
blockStmt = "else";
if(matcher!=null){
if(blockStmt.length()>0)
blockStmt += " ";
String ch = "ch";
if(heightDecreased || !children.isEmpty()){
int depth = depth();
if(state.rootIF.lookAheadChars()){
if(!heightDecreased)
ch = depth==0 ? "input[position]" : "input[position+"+depth+"]";
}else
ch = "la["+depth+"]";
}
blockStmt += "if("+condition(matcher, ch)+")";
}
return blockStmt.length()==0 ? null : blockStmt;
}
protected void generateChildren(Printer printer, State next){
if(common!=-1)
children.get(0).travelPath(printer, 0, common);
for(IfBlock child: children)
child.generate(printer, next);
}
public void generate(Printer printer, State next){
if(usesFinishAll()){
useFinishAll(printer);
return;
}
boolean closeLaLenCheck = false;
boolean heightDecreased = false;
if(parent==null){
int index = state.ifBlocks.indexOf(this);
int prevHeight = index==0 ? 1 : state.ifBlocks.get(index-1).height();
int curHeight = height();
if(curHeight>prevHeight){
if(prevHeight==1){
if(root.lookAheadChars())
printer.printlns("int "+state.rootIF.available()+" = limit-position+(marker==EOF ? 1 : 0);");
else
printer.println("addToLookAhead(ch);");
}
if(!root.lookAheadChars())
root.fillLookAhead(printer, prevHeight, curHeight);
closeLaLenCheck = true;
if(root.lookAheadChars()){
String last = "position+"+(curHeight-1);
printer.printlns(
"if("+root.available()+">="+curHeight+"){",
PLUS,
"ch = limit=="+last+" ? EOF : input["+last+"];"
);
}else{
printer.printlns(
"if(laLen=="+curHeight+"){",
PLUS
);
}
}else{
heightDecreased = curHeight siblings = siblings();
String blockStmt = blockStatement(heightDecreased);
if(blockStmt!=null){
printer.printlns(
blockStmt+"{",
PLUS
);
}
if(path!=null)
generateBody(printer, next, heightDecreased);
else
generateChildren(printer, next);
boolean addExpected = parent == null && siblings.indexOf(this) == siblings.size() - 1 && matcher != null;
if(blockStmt!=null){
printer.printlns(MINUS);
printer.print("}");
int index = siblings.indexOf(this);
IfBlock nextIF = index==siblings.size()-1 ? null : siblings.get(index+1);
String nextBlockStmt = nextIF==null ? null : nextIF.blockStatement(heightDecreased);
boolean sameLine;
if(nextBlockStmt==null)
sameLine = addExpected && !root.lookAheadRequired();
else
sameLine = nextBlockStmt.startsWith("else");
if(!sameLine)
printer.println();
}
if(closeLaLenCheck){
printer.printlns(MINUS);
printer.print("}");
if(root.lookAheadChars()){
printer.printlns(
"else if(marker==EOC)",
PLUS,
state.breakStatement(),
MINUS
);
}else
printer.println();
}
if(addExpected){
if(!root.lookAheadRequired())
printer.print("else ");
printer.println("throw expected(ch, \""+ StringUtil.toLiteral(state.expected(), false)+"\");");
}
}
private Edge edgeWithRule(){
for(Object obj : path){
if(obj instanceof Edge){
Edge edge = (Edge) obj;
if(edge.ruleTarget != null)
return edge;
}
}
return null;
}
private String ruleID(Edge edgeWithRule){
String ruleName = edgeWithRule.ruleTarget.rule.name;
if(!SyntaxClass.DEBUGGABLE && Node.DYNAMIC_STRING_MATCH.equals(edgeWithRule.source.name))
ruleName = "DYNAMIC_STRING_MATCH";
return "RULE_"+ruleName.toUpperCase();
}
private String methodCall(Edge edgeWithRule){
int id = edgeWithRule.ruleTarget.node().stateID;
String methodCall;
if(!SyntaxClass.DEBUGGABLE && Node.DYNAMIC_STRING_MATCH.equals(edgeWithRule.source.name))
methodCall = "matchString("+id+", dynamicStringToBeMatched)";
else{
Rule rule = edgeWithRule.ruleTarget.rule;
if(rule.id<0)
methodCall = "matchString(RULE_"+rule.name.toUpperCase()+", "+id+", STRING_IDS[-RULE_"+rule.name.toUpperCase()+"])";
else
methodCall = rule.name+"("+id+")";
}
return methodCall;
}
private void setState(Printer printer, Node node){
if(path.get(0)!=node)
printer.println("state = "+node.stateID+";");
}
private boolean addContinue(State next, Node returnNode){
return root.lookAheadRequired() || next==null || returnNode!=next.fromNode;
}
private void generateBody(Printer printer, State next, boolean heightDecreased){
int common = parent==null ? root.common : parent.common;
int check = travelPath(printer, common+1, path.size()-1);
if(check==CHECK_ERROR)
return;
if(parent!=null || heightDecreased){
if(!root.lookAheadChars())
printer.println("resetLookAhead();");
}
Edge edgeWithRule = edgeWithRule();
if(edgeWithRule==null){
Node returnNode = (Node)path.get(path.size()-1);
if(returnNode.outgoing.size()==0){
printer.println("return "+(check==CHECK_STOP?"!stop":"true")+";");
}else{
setState(printer, returnNode);
if(check==CHECK_STOP)
printer.printlnIf("stop", state.breakStatement());
else if(check==CHECK_POP)
printer.printlnIf("pop", "return true;");
if(addContinue(next, returnNode))
printer.println("continue;");
}
}else{
Node returnNode = edgeWithRule.target;
boolean doReturn = new Routes(state.ruleMethod.rule, returnNode).isEOF();
if(!doReturn)
setState(printer, returnNode);
if(check==CHECK_STOP){
printer.printlns(
"if(stop){",
PLUS,
"exiting("+ruleID(edgeWithRule)+", "+edgeWithRule.ruleTarget.node().stateID+");",
doReturn ? "return false;" : state.breakStatement(),
MINUS,
"}else"
);
}else if(check==CHECK_POP)
printer.printlnIf("pop", "return true;");
if(doReturn){
printer.println("return "+methodCall(edgeWithRule)+";");
}else{
List ifBody = new ArrayList();
if(addContinue(next, returnNode))
ifBody.add("continue;");
List elseBody = new ArrayList();
elseBody.add(state.breakStatement());
if(ifBody.size()==0)
printer.printlnIf("!"+methodCall(edgeWithRule), elseBody);
else
printer.printlnIf(methodCall(edgeWithRule), ifBody, elseBody);
}
}
}
private static int CHECK_STOP = 1;
private static int CHECK_POP = 2;
private static int CHECK_ERROR = 3;
public int travelPath(Printer printer, int from, int to){
int check = 0;
for(int index=0; index=from && index<=to){
if(SyntaxClass.DEBUGGABLE)
printer.println("handler.execute("+state.ruleMethod.rule.id+", "+node.id+");");
else
printer.println(node.action.javaCode()+';');
}
if(node.action instanceof EventAction || node.action instanceof PublishAction){
if(node.action.toString().startsWith("#"))
check = CHECK_STOP;
else if(node.action.toString().startsWith("!"))
check = CHECK_POP;
}else if(node.action instanceof ErrorAction)
return CHECK_ERROR;
}
}
}else if(obj instanceof Edge){
if(!(index>=from && index<=to))
continue;
Edge edge = (Edge)obj;
if(edge.ruleTarget!=null){
// RuleTarget ruleTarget = edge.ruleTarget;
// int idAfterRule = idAfterRule(edge);
// String ruleName = ruleName(edge);
// printer.println("push(RULE_"+ruleName.toUpperCase()+", "+idAfterRule+", "+id(ruleTarget.node())+");");
}else if(edge.matcher!=null){
if(parent==null){
if(!matcher.clashesWith(Range.SUPPLIMENTAL) && !matcher.clashesWith(Any.NEW_LINE))
consumeDirectly(printer, edge);
else
printer.println("consume(ch);"); //"+edge.source.buffering);
}else{
if(root.lookAheadChars())
consumeDirectly(printer, edge);
else
printer.println("consume(FROM_LA);"); //"+edge.source.buffering);
}
}
}
}
return check;
}
private void consumeDirectly(Printer printer, Edge edge){
if(edge.source.buffering== Answer.NO)
printer.println("position++;");
else if(edge.source.buffering==Answer.YES)
printer.println("buffer.append(input[position++]);");
else{
printer.printlns(
"if(buffer.isBuffering())",
PLUS,
"buffer.append(input[position]);",
MINUS,
"position++;"
);
}
}
/*-------------------------------------------------[ FinishAll ]---------------------------------------------------*/
public boolean usesFinishAll(){
return parent==null && state.ifBlocks.get(0)==this && path!=null && path.size()>1 && edgeWithRule()==null && path.get(0)==path.get(path.size()-1);
}
public boolean finishAllReturnValueRequired(){
for(int i=1; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy