package org.develnext.jphp.core.tokenizer;
import org.develnext.jphp.core.tokenizer.token.*;
import org.develnext.jphp.core.tokenizer.token.expr.*;
import org.develnext.jphp.core.tokenizer.token.expr.operator.*;
import org.develnext.jphp.core.tokenizer.token.expr.value.*;
import org.develnext.jphp.core.tokenizer.token.expr.value.macro.*;
import org.develnext.jphp.core.tokenizer.token.stmt.*;
import php.runtime.common.GrammarUtils;
import java.util.HashMap;
import java.util.Map;
public class TokenFinder {
private final static HashMap<String, Class<? extends Token>> patterns = new HashMap<String, Class<? extends Token>>(){{
put("<?", OpenTagToken.class);
put("<?php", OpenTagToken.class);
put("?>", BreakToken.class);
put("<?=", OpenEchoTagToken.class);
put("/*", CommentToken.class);
put("//", CommentToken.class);
put("<<<", StringStartDocToken.class);
put("+", PlusExprToken.class);
put("-", MinusExprToken.class);
put("*", MulExprToken.class);
put("/", DivExprToken.class);
put("%", ModExprToken.class);
put("**", PowExprToken.class);
put("=", AssignExprToken.class);
put("\\", BackslashExprToken.class);
put("==", EqualExprToken.class);
put("!=", BooleanNotEqualExprToken.class);
put("<>", BooleanNotEqualExprToken.class);
put("===", IdenticalExprToken.class);
put("!==", NotIdenticalExprToken.class);
put(">", GreaterExprToken.class);
put(">=", GreaterOrEqualExprToken.class);
put("<", SmallerExprToken.class);
put("<=", SmallerOrEqualToken.class);
put("&&", BooleanAndExprToken.class);
put("and", BooleanAnd2ExprToken.class);
put("||", BooleanOrExprToken.class);
put("or", BooleanOr2ExprToken.class);
put("xor", BooleanXorExprToken.class);
put("!", BooleanNotExprToken.class);
put("?", ValueIfElseToken.class);
put("~", NotExprToken.class);
put("^", XorExprToken.class);
put("|", OrExprToken.class);
put("&", AndExprToken.class);
put(">>", ShiftRightExprToken.class);
put("<<", ShiftLeftExprToken.class);
put("@", SilentToken.class);
put("->", DynamicAccessExprToken.class);
put("::", StaticAccessExprToken.class);
put("=>", KeyValueExprToken.class);
put("+=", AssignPlusExprToken.class);
put("-=", AssignMinusExprToken.class);
put("*=", AssignMulExprToken.class);
put("**=", AssignPowExprToken.class);
put("/=", AssignDivExprToken.class);
put("%=", AssignModExprToken.class);
put(".=", AssignConcatExprToken.class);
put("^=", AssignXorExprToken.class);
put("&=", AssignAndExprToken.class);
put("|=", AssignOrExprToken.class);
put("++", IncExprToken.class);
put("--", DecExprToken.class);
put(">>=", AssignShiftRightExprToken.class);
put("<<=", AssignShiftLeftExprToken.class);
put("...", ArgumentUnpackExprToken.class);
put("new", NewExprToken.class);
put("clone", CloneExprToken.class);
put("instanceof", InstanceofExprToken.class);
put("insteadof", InsteadofStmtToken.class);
put(".", ConcatExprToken.class);
put(":", ColonToken.class);
put("true", BooleanExprToken.class);
put("false", BooleanExprToken.class);
put("null", NullExprToken.class);
put(";", SemicolonToken.class);
put("&", AmpersandRefToken.class);
put(",", CommaToken.class);
put("$", DollarExprToken.class);
put("{", BraceExprToken.class);
put("[", BraceExprToken.class);
put("(", BraceExprToken.class);
put("}", BraceExprToken.class);
put("]", BraceExprToken.class);
put(")", BraceExprToken.class);
put("static", StaticExprToken.class);
put("self", SelfExprToken.class);
put("parent", ParentExprToken.class);
//put("$this", ThisExprToken.class);
//put("array", ArrayExprToken.class);
put("as", AsStmtToken.class);
put("if", IfStmtToken.class);
put("else", ElseStmtToken.class);
put("elseif", ElseIfStmtToken.class);
put("while", WhileStmtToken.class);
put("do", DoStmtToken.class);
put("for", ForStmtToken.class);
put("foreach", ForeachStmtToken.class);
put("switch", SwitchStmtToken.class);
put("case", CaseStmtToken.class);
put("default", DefaultStmtToken.class);
put("declare", DeclareStmtToken.class);
put("return", ReturnStmtToken.class);
put("endif", EndifStmtToken.class);
put("endforeach", EndforeachStmtToken.class);
put("endfor", EndforStmtToken.class);
put("endwhile", EndwhileStmtToken.class);
put("endswitch", EndswitchStmtToken.class);
put("enddeclare", EnddeclareStmtToken.class);
put("break", BreakStmtToken.class);
put("continue", ContinueStmtToken.class);
put("goto", GotoStmtToken.class);
put("unset", UnsetExprToken.class);
put("isset", IssetExprToken.class);
put("empty", EmptyExprToken.class);
put("die", DieExprToken.class);
put("exit", DieExprToken.class);
put("class", ClassStmtToken.class);
put("interface", InterfaceStmtToken.class);
put("trait", TraitStmtToken.class);
put("function", FunctionStmtToken.class);
put("const", ConstStmtToken.class);
put("namespace", NamespaceStmtToken.class);
put("use", NamespaceUseStmtToken.class);
//put("uses", UsesStmtToken.class);
put("abstract", AbstractStmtToken.class);
put("final", FinalStmtToken.class);
put("private", PrivateStmtToken.class);
put("protected", ProtectedStmtToken.class);
put("public", PublicStmtToken.class);
put("var", VarStmtToken.class);
put("try", TryStmtToken.class);
put("catch", CatchStmtToken.class);
put("finally", FinallyStmtToken.class);
put("throw", ThrowStmtToken.class);
put("extends", ExtendsStmtToken.class);
put("implements", ImplementsStmtToken.class);
put("global", GlobalStmtToken.class);
put("list", ListExprToken.class);
put("__line__", LineMacroToken.class);
put("__file__", FileMacroToken.class);
put("__dir__", DirMacroToken.class);
put("__function__", FunctionMacroToken.class);
put("__class__", ClassMacroToken.class);
put("__method__", MethodMacroToken.class);
put("__trait__", TraitMacroToken.class);
put("__namespace__", NamespaceMacroToken.class);
put("include", IncludeExprToken.class);
put("include_once", IncludeOnceExprToken.class);
put("require", RequireExprToken.class);
put("require_once", RequireOnceExprToken.class);
put("echo", EchoStmtToken.class);
put("print", PrintNameToken.class);
put("yield", YieldExprToken.class);
}};
public static final int MAX_FIND_CACHE_SIZE = 10000;
private Map<String, Class<? extends Token>> findCache = new HashMap<>();
public TokenFinder() {
}
public Class<? extends Token> find(String word) {
if (findCache.size() > MAX_FIND_CACHE_SIZE) {
findCache.clear();
}
Class<? extends Token> token = findCache.get(word);
if (token != null) {
return token;
}
word = word.toLowerCase();
token = patterns.get(word);
if (token != null) {
findCache.put(word, token);
return token;
}
int length = word.length();
if (length == 0) {
return null;
}
if (GrammarUtils.isVariable(word)) {
findCache.put(word, VariableExprToken.class);
return VariableExprToken.class;
}
if (GrammarUtils.isInteger(word) || GrammarUtils.isHexInteger(word)
|| GrammarUtils.isBinaryInteger(word)) {
findCache.put(word, IntegerExprToken.class);
return IntegerExprToken.class;
}
if (GrammarUtils.isSimpleFloat(word) || GrammarUtils.isExpFloat(word)) {
findCache.put(word, DoubleExprToken.class);
return DoubleExprToken.class;
}
boolean fulledName = false;
for (int i = 0; i < length; i++) {
char ch = word.charAt(i);
if (ch == '\\') {
fulledName = true;
} else if (!GrammarUtils.isNameChar(ch)) {
return null;
}
}
if (fulledName) {
if (word.length() < 32) {
findCache.put(word, FulledNameToken.class);
}
return FulledNameToken.class;
}
if (word.length() < 32) {
findCache.put(word, NameToken.class);
}
return NameToken.class;
}
public Class<? extends Token> find(TokenMeta meta){
return find(meta.getWord());
}
}