jlibs.nblr.codegen.java.SyntaxClass Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jlibs-nblr Show documentation
Show all versions of jlibs-nblr Show documentation
Non-Blocking Language Recognition
/**
* 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.java;
import jlibs.core.annotation.processing.Printer;
import jlibs.nblr.Syntax;
import jlibs.nblr.codegen.FinishAllMethod;
import jlibs.nblr.codegen.IfBlock;
import jlibs.nblr.codegen.RuleMethod;
import jlibs.nblr.codegen.State;
import jlibs.nblr.matchers.Any;
import jlibs.nblr.matchers.Matcher;
import jlibs.nblr.matchers.Not;
import jlibs.nblr.rules.Answer;
import jlibs.nblr.rules.Rule;
import java.util.*;
import static jlibs.core.annotation.processing.Printer.MINUS;
import static jlibs.core.annotation.processing.Printer.PLUS;
/**
* @author Santhosh Kumar T
*/
public class SyntaxClass{
public static boolean DEBUGGABLE = false;
public Syntax syntax;
public List ruleMethods = new ArrayList();
public SyntaxClass(Syntax syntax){
this.syntax = syntax.copy();
if(!DEBUGGABLE){
detectStringRules();
syntax = this.syntax;
}
boolean recompute;
do{
ruleMethods.clear();
recompute = false;
// NOTE: ids of all rules should be computed before calculating Routes
for(Rule rule: syntax.rules.values())
rule.computeIDS();
for(Rule rule: syntax.rules.values()){
if(rule.id>=0){
RuleMethod ruleMethod;
while(true){
ruleMethod = new RuleMethod(this, rule);
if(DEBUGGABLE || !ruleMethod.deleteEmptySwitches())
break;
else
recompute = true;
}
ruleMethods.add(ruleMethod);
}
}
}while(recompute);
syntax.computeBufferingStates();
for(RuleMethod ruleMethod: ruleMethods){
for(State state: ruleMethod.states){
IfBlock first = state.ifBlocks.get(0);
if(first.usesFinishAll()){
FinishAllMethod method = addToFinishAll(first.matcher);
Answer ans = state.fromNode.buffering;
if(method.buffering==null)
method.buffering = ans;
else if(method.buffering!=ans)
method.buffering = Answer.MAY_BE;
if(first.finishAllReturnValueRequired())
method.returnValueRequired = true;
}
}
}
/*
// print no of continues used for each rule
for(RuleMethod ruleMethod: ruleMethods){
int count = 0;
for(int i=0; i stringRules = new ArrayList();
private void detectStringRules(){
syntax = syntax.copy();
int stringRuleID = -1;
int id = 0;
for(Rule r: syntax.rules.values()){
int codePoints[] = r.matchString();
if(codePoints!=null){
r.id = stringRuleID--;
stringRules.add(r);
}else
r.id = id++;
}
}
private int unnamed_finishAllMethods = 0;
private Map finishAllMethods = new LinkedHashMap();
public static final String FINISH_ALL = "finishAll";
public static final String FINISH_ALL_OTHER_THAN = "finishAll_OtherThan";
public FinishAllMethod addToFinishAll(Matcher matcher){
boolean not = false;
Matcher givenMatcher = matcher;
if(matcher instanceof Not){
not = true;
matcher = ((Not)matcher).delegate;
}
if(matcher instanceof Any){
Any any = (Any)matcher;
if(any.chars!=null && any.chars.length==1)
return new FinishAllMethod(matcher, not ? FINISH_ALL_OTHER_THAN : FINISH_ALL);
}
matcher = givenMatcher;
FinishAllMethod method = null;
if(matcher.name!=null)
method = finishAllMethods.get(matcher);
else{
for(Map.Entry entry: finishAllMethods.entrySet()){
if(entry.getKey().same(matcher)){
method = entry.getValue();
break;
}
}
}
if(method==null){
String name = matcher.name;
if(name==null)
name = String.valueOf(++unnamed_finishAllMethods);
method = new FinishAllMethod(matcher, name);
finishAllMethods.put(matcher, method);
}
return method;
}
public void generate(Printer printer){
if(!DEBUGGABLE)
generateStringRules(printer);
generateMatcherMethods(printer);
generaleRuleMethods(printer);
generateFinishAllMethods(printer);
generateCallRuleMethod(printer);
}
private void generaleRuleMethods(Printer printer){
if(ruleMethods.size()>0){
printer.titleComment("Rules");
for(RuleMethod ruleMethod: ruleMethods){
ruleMethod.generate(printer);
printer.emptyLine(true);
}
}
}
private void generateFinishAllMethods(Printer printer){
for(FinishAllMethod method: finishAllMethods.values()){
printer.emptyLine(true);
method.generate(printer);
}
}
private void generateStringRules(Printer printer){
printer.printlns(
"private static final int STRING_IDS[][] = {",
PLUS,
"{}, // dummy one"
);
for(Rule rule: syntax.rules.values()){
if(rule.id<0){
int[] codePoints = rule.matchString();
String str = Arrays.toString(codePoints);
printer.print("{");
printer.print(str.substring(1, str.length()-1));
printer.print("}, // ");
printer.println(new String(codePoints, 0, codePoints.length));
}
}
printer.printlns(
MINUS,
"};"
);
printer.emptyLine(true);
for(Rule rule: syntax.rules.values()){
if(rule.id<0)
printer.println("public static final int RULE_"+rule.name.toUpperCase()+" = "+rule.id+';');
}
}
private void generateMatcherMethods(Printer printer){
if(syntax.matchers.size()>0){
printer.titleComment("Matchers");
for(Matcher matcher: syntax.matchers.values()){
if(!matcher.canInline()){
printer.printlns(
"private static boolean "+matcher.name+"(int ch){",
PLUS,
"return "+matcher.javaCode("ch")+';',
MINUS,
"}"
);
printer.emptyLine(true);
}
}
}
}
private void generateCallRuleMethod(Printer printer){
printer.emptyLine(true);
printer.printlns(
"@Override",
"protected final boolean callRule(int rule, int state) throws Exception{",
PLUS,
"if(SHOW_STATS)",
PLUS,
"callRuleCount++;",
MINUS
);
if(!DEBUGGABLE){
printer.printlns(
"if(rule<0){",
PLUS,
"if(rule==RULE_DYNAMIC_STRING_MATCH)",
PLUS,
"return matchString(state, dynamicStringToBeMatched);",
MINUS,
"else",
PLUS,
"return matchString(rule, state, STRING_IDS[-rule]);",
MINUS,
MINUS,
"}"
);
}
printer.printlns(
"switch(rule){",
PLUS
);
for(Rule rule: syntax.rules.values()){
if(rule.id>=0){
printer.printlns(
"case "+rule.id+":",
PLUS,
"return "+rule.name+"(state);",
MINUS
);
}
}
printer.printlns(
"default:",
PLUS,
"throw new Error(\"impossible rule: \"+stack[free-2]);",
MINUS,
MINUS,
"}",
MINUS,
"}"
);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy