Parser optimization (#12)
This commit is contained in:
+149
-106
@@ -215,7 +215,7 @@ class Parser {
|
||||
return null;
|
||||
}
|
||||
|
||||
inline function push(tk: Token):Void {
|
||||
@:analyzer(fusion) inline function push(tk: Token):Void {
|
||||
#if hscriptPos
|
||||
tokens.push( { t : tk, min : tokenMin, max : tokenMax } );
|
||||
tokenMin = oldTokenMin;
|
||||
@@ -225,17 +225,17 @@ class Parser {
|
||||
#end
|
||||
}
|
||||
|
||||
inline function ensure(tk:Token):Void {
|
||||
@:analyzer(fusion) inline function ensure(tk:Token):Void {
|
||||
var t = token();
|
||||
if( t != tk ) unexpected(t);
|
||||
}
|
||||
|
||||
inline function ensureToken(tk:Token):Void {
|
||||
@:analyzer(fusion) inline function ensureToken(tk:Token):Void {
|
||||
var t = token();
|
||||
if( !Type.enumEq(t,tk) ) unexpected(t);
|
||||
}
|
||||
|
||||
function maybe(tk:Token):Bool {
|
||||
@:analyzer(fusion) inline function maybe(tk:Token):Bool {
|
||||
var t = token();
|
||||
if( Type.enumEq(t, tk) )
|
||||
return true;
|
||||
@@ -253,7 +253,7 @@ class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
inline function expr(e:Expr):#if hscriptPos ExprDef #else Expr #end {
|
||||
@:analyzer(fusion) inline function expr(e:Expr):#if hscriptPos ExprDef #else Expr #end {
|
||||
#if hscriptPos
|
||||
return e.e;
|
||||
#else
|
||||
@@ -261,7 +261,7 @@ class Parser {
|
||||
#end
|
||||
}
|
||||
|
||||
inline function pmin(e:Expr):Int {
|
||||
@:analyzer(fusion) inline function pmin(e:Expr):Int {
|
||||
#if hscriptPos
|
||||
return e == null ? 0 : e.pmin;
|
||||
#else
|
||||
@@ -269,7 +269,7 @@ class Parser {
|
||||
#end
|
||||
}
|
||||
|
||||
inline function pmax(e:Expr):Int {
|
||||
@:analyzer(fusion) inline function pmax(e:Expr):Int {
|
||||
#if hscriptPos
|
||||
return e == null ? 0 : e.pmax;
|
||||
#else
|
||||
@@ -277,7 +277,7 @@ class Parser {
|
||||
#end
|
||||
}
|
||||
|
||||
inline function mk(e:#if hscriptPos ExprDef #else Expr #end,?pmin:Int,?pmax:Int) : Expr {
|
||||
@:analyzer(fusion) inline function mk(e:#if hscriptPos ExprDef #else Expr #end,?pmin:Int,?pmax:Int) : Expr {
|
||||
#if hscriptPos
|
||||
if( e == null ) return null;
|
||||
if( pmin == null ) pmin = tokenMin;
|
||||
@@ -288,7 +288,7 @@ class Parser {
|
||||
#end
|
||||
}
|
||||
|
||||
function isBlock(e:Expr):Bool {
|
||||
@:analyzer(fusion) inline function isBlock(e:Expr):Bool {
|
||||
if( e == null ) return false;
|
||||
return switch( expr(e) ) {
|
||||
case EBlock(_), EObject(_), ESwitch(_), EEnum(_, _): true;
|
||||
@@ -308,7 +308,7 @@ class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
function parseFullExpr( exprs : Array<Expr> ):Void {
|
||||
@:analyzer(fusion) function parseFullExpr( exprs : Array<Expr> ):Void {
|
||||
var e = parseExpr();
|
||||
exprs.push(e);
|
||||
|
||||
@@ -608,7 +608,7 @@ class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
function makeBinop( op:String, e1:Expr, e:Expr ):Expr {
|
||||
@:analyzer(fusion) inline function makeBinop( op:String, e1:Expr, e:Expr ):Expr {
|
||||
if( e == null && resumeErrors )
|
||||
return mk(EBinop(op,e1,e),pmin(e1),pmax(e1));
|
||||
return switch( expr(e) ) {
|
||||
@@ -1059,25 +1059,64 @@ class Parser {
|
||||
var interfaces:Array<String> = [];
|
||||
// optional - example: extends BaseClass
|
||||
|
||||
while( true ) {
|
||||
var t = token();
|
||||
switch( t ) {
|
||||
case TId("extends"):
|
||||
var e = parseType();
|
||||
switch(e) {
|
||||
case CTPath(path, params):
|
||||
if(extend != null) {
|
||||
error(ECustom('Cannot extend a class twice.'), 0, 0);
|
||||
}
|
||||
extend = path.join(".");
|
||||
default:
|
||||
error(ECustom('${Std.string(e)} is not a valid path.'), 0, 0);
|
||||
}
|
||||
default:
|
||||
push(t);
|
||||
break;
|
||||
}
|
||||
var t = token();
|
||||
switch( t ) {
|
||||
case TId("extends"):
|
||||
var e = parseType();
|
||||
switch(e) {
|
||||
case CTPath(path, params):
|
||||
if(extend != null) {
|
||||
error(ECustom('Cannot extend a class twice.'), 0, 0);
|
||||
}
|
||||
var buf = new StringBuf();
|
||||
for(i in 0...path.length) {
|
||||
if(i > 0) buf.add(".");
|
||||
buf.add(path[i]);
|
||||
}
|
||||
extend = buf.toString();
|
||||
default:
|
||||
error(ECustom('${Std.string(e)} is not a valid path.'), 0, 0);
|
||||
}
|
||||
t = token();
|
||||
switch(t) {
|
||||
case TId("implements"):
|
||||
var e = parseType();
|
||||
switch(e) {
|
||||
case CTPath(path, params):
|
||||
var buf = new StringBuf();
|
||||
for(i in 0...path.length) {
|
||||
if(i > 0) buf.add(".");
|
||||
buf.add(path[i]);
|
||||
}
|
||||
interfaces.push(buf.toString());
|
||||
default:
|
||||
error(ECustom('${Std.string(e)} is not a valid path.'), 0, 0);
|
||||
}
|
||||
t = token();
|
||||
default:
|
||||
}
|
||||
case TId("implements"):
|
||||
var e = parseType();
|
||||
switch(e) {
|
||||
case CTPath(path, params):
|
||||
var buf = new StringBuf();
|
||||
for(i in 0...path.length) {
|
||||
if(i > 0) buf.add(".");
|
||||
buf.add(path[i]);
|
||||
}
|
||||
interfaces.push(buf.toString());
|
||||
default:
|
||||
error(ECustom('${Std.string(e)} is not a valid path.'), 0, 0);
|
||||
}
|
||||
t = token();
|
||||
switch(t) {
|
||||
case TId("extends"):
|
||||
error(ECustom('Implements must come after extends.'), 0, 0);
|
||||
default:
|
||||
}
|
||||
default:
|
||||
}
|
||||
push(t);
|
||||
|
||||
/*while(true) {
|
||||
tk = token();
|
||||
@@ -1401,17 +1440,15 @@ class Parser {
|
||||
var done = false;
|
||||
while( !done ) {
|
||||
var name = null, opt = false;
|
||||
switch( tk ) {
|
||||
case TQuestion:
|
||||
opt = true;
|
||||
tk = token();
|
||||
default:
|
||||
if( tk == TQuestion ) {
|
||||
opt = true;
|
||||
tk = token();
|
||||
}
|
||||
switch( tk ) {
|
||||
case TId(id): name = id;
|
||||
case TId(id):
|
||||
name = id;
|
||||
default:
|
||||
unexpected(tk);
|
||||
break;
|
||||
}
|
||||
var arg : Argument = { name : name, opt: false, value: null, t: null };
|
||||
args.push(arg);
|
||||
@@ -1426,13 +1463,12 @@ class Parser {
|
||||
}
|
||||
}
|
||||
tk = token();
|
||||
switch( tk ) {
|
||||
case TComma:
|
||||
tk = token();
|
||||
case TPClose:
|
||||
done = true;
|
||||
default:
|
||||
unexpected(tk);
|
||||
if( tk == TComma ) {
|
||||
tk = token();
|
||||
} else if( tk == TPClose ) {
|
||||
done = true;
|
||||
} else {
|
||||
unexpected(tk);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1479,31 +1515,32 @@ class Parser {
|
||||
if( op == "<" ) {
|
||||
params = [];
|
||||
while( true ) {
|
||||
switch( token() ) {
|
||||
case TConst(c):
|
||||
params.push(CTExpr(mk(EConst(c))));
|
||||
case tk:
|
||||
push(tk);
|
||||
params.push(parseType());
|
||||
}
|
||||
t = token();
|
||||
switch( t ) {
|
||||
case TComma: continue;
|
||||
case TOp(op):
|
||||
if( op == ">" ) break;
|
||||
if( op.charCodeAt(0) == ">".code ) {
|
||||
#if hscriptPos
|
||||
tokens.add({ t : TOp(op.substr(1)), min : tokenMax - op.length - 1, max : tokenMax });
|
||||
#else
|
||||
tokens.add(TOp(op.substr(1)));
|
||||
#end
|
||||
break;
|
||||
var tt = token();
|
||||
switch( tt ) {
|
||||
case TConst(c):
|
||||
params.push(CTExpr(mk(EConst(c))));
|
||||
default:
|
||||
push(tt);
|
||||
params.push(parseType());
|
||||
}
|
||||
default:
|
||||
t = token();
|
||||
switch( t ) {
|
||||
case TComma: continue;
|
||||
case TOp(op):
|
||||
if( op == ">" ) break;
|
||||
if( op.charCodeAt(0) == ">".code ) {
|
||||
#if hscriptPos
|
||||
tokens.add({ t : TOp(op.substr(1)), min : tokenMax - op.length - 1, max : tokenMax });
|
||||
#else
|
||||
tokens.add(TOp(op.substr(1)));
|
||||
#end
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
unexpected(t);
|
||||
break;
|
||||
}
|
||||
unexpected(t);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
push(t);
|
||||
default:
|
||||
@@ -1633,13 +1670,10 @@ class Parser {
|
||||
while( true ) {
|
||||
args.push(parseExpr());
|
||||
tk = token();
|
||||
switch( tk ) {
|
||||
case TComma:
|
||||
default:
|
||||
if( tk == etk ) break;
|
||||
unexpected(tk);
|
||||
break;
|
||||
}
|
||||
if( tk == etk )
|
||||
break;
|
||||
if( tk != TComma )
|
||||
unexpected(tk);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
@@ -2164,7 +2198,9 @@ class Parser {
|
||||
switch( char ) {
|
||||
case 48,49,50,51,52,53,54,55,56,57:
|
||||
n = n * 10 + (char - 48);
|
||||
continue;
|
||||
case '_'.code:
|
||||
continue;
|
||||
case "e".code, "E".code:
|
||||
var tk = token();
|
||||
var pow : Null<Int> = null;
|
||||
@@ -2193,46 +2229,48 @@ class Parser {
|
||||
invalidChar(char);
|
||||
}
|
||||
exp = 1.;
|
||||
continue;
|
||||
case "x".code:
|
||||
if( n > 0 || exp > 0 )
|
||||
invalidChar(char);
|
||||
// read hexa
|
||||
var n = 0;
|
||||
var hex = 0;
|
||||
while( true ) {
|
||||
char = readChar();
|
||||
switch( char ) {
|
||||
case 48,49,50,51,52,53,54,55,56,57: // 0-9
|
||||
n = (n << 4) + char - 48;
|
||||
case 65,66,67,68,69,70: // A-F
|
||||
n = (n << 4) + (char - 55);
|
||||
case 97,98,99,100,101,102: // a-f
|
||||
n = (n << 4) + (char - 87);
|
||||
case '_'.code:
|
||||
default:
|
||||
this.char = char;
|
||||
return TConst(CInt(n));
|
||||
if( char >= 48 && char <= 57 ) {
|
||||
hex = (hex << 4) + char - 48;
|
||||
continue;
|
||||
} else if( char >= 65 && char <= 70 ) {
|
||||
hex = (hex << 4) + char - 55;
|
||||
continue;
|
||||
} else if( char >= 97 && char <= 102 ) {
|
||||
hex = (hex << 4) + char - 87;
|
||||
continue;
|
||||
} else if( char == '_'.code ) {
|
||||
continue;
|
||||
}
|
||||
this.char = char;
|
||||
return TConst(CInt(hex));
|
||||
}
|
||||
case "b".code: // Custom thing, not supported in haxe
|
||||
if( n > 0 || exp > 0 )
|
||||
invalidChar(char);
|
||||
// read binary
|
||||
var n = 0;
|
||||
var bin = 0;
|
||||
while( true ) {
|
||||
char = readChar();
|
||||
switch( char ) {
|
||||
case 48,49: // 0-1
|
||||
n = (n << 1) + char - 48;
|
||||
case '_'.code:
|
||||
default:
|
||||
this.char = char;
|
||||
return TConst(CInt(n));
|
||||
if( char == 48 || char == 49 ) {
|
||||
bin = (bin << 1) + char - 48;
|
||||
continue;
|
||||
} else if( char == '_'.code ) {
|
||||
continue;
|
||||
}
|
||||
this.char = char;
|
||||
return TConst(CInt(bin));
|
||||
}
|
||||
default:
|
||||
this.char = char;
|
||||
var i = Std.int(n);
|
||||
return TConst( (exp > 0) ? CFloat(n * 10 / exp) : ((i == n) ? CInt(i) : CFloat(n)) );
|
||||
return TConst( (exp > 0) ? CFloat(n * 10 / exp) : ((n % 1 == 0) ? CInt(Std.int(n)) : CFloat(n)) );
|
||||
}
|
||||
}
|
||||
case ";".code: return TSemicolon;
|
||||
@@ -2328,17 +2366,19 @@ class Parser {
|
||||
invalidChar(char);
|
||||
default:
|
||||
if( ops[char] ) {
|
||||
var op:String = String.fromCharCode(char);
|
||||
var buf = new StringBuf();
|
||||
buf.addChar(char);
|
||||
while( true ) {
|
||||
char = readChar();
|
||||
if( StringTools.isEof(char) ) char = 0;
|
||||
if( !ops[char] ) {
|
||||
this.char = char;
|
||||
return TOp(op);
|
||||
return TOp(buf.toString());
|
||||
}
|
||||
var pop = op;
|
||||
op += String.fromCharCode(char);
|
||||
if( allowRegex && op == "~/") {
|
||||
var pop = buf.toString();
|
||||
buf.addChar(char);
|
||||
var op = buf.toString();
|
||||
if( allowRegex && op == "~/" ) {
|
||||
var e = readString(char, true);
|
||||
var f = readFlags();
|
||||
return TRegex(e, f);
|
||||
@@ -2352,16 +2392,17 @@ class Parser {
|
||||
}
|
||||
}
|
||||
if( idents[char] ) {
|
||||
var id = String.fromCharCode(char);
|
||||
var buf = new StringBuf();
|
||||
buf.addChar(char);
|
||||
while( true ) {
|
||||
char = readChar();
|
||||
if( StringTools.isEof(char) ) char = 0;
|
||||
if( !idents[char] ) {
|
||||
this.char = char;
|
||||
//if(id == "is") return TOp("is");
|
||||
return TId(id);
|
||||
return TId(buf.toString());
|
||||
}
|
||||
id += String.fromCharCode(char);
|
||||
buf.addChar(char);
|
||||
}
|
||||
}
|
||||
invalidChar(char);
|
||||
@@ -2384,14 +2425,16 @@ class Parser {
|
||||
push(TPOpen);
|
||||
parseExpr();
|
||||
case TId(id):
|
||||
var buf = new StringBuf();
|
||||
buf.add(id);
|
||||
while(true) {
|
||||
var tk = token();
|
||||
if(tk == TDot) {
|
||||
id += ".";
|
||||
buf.add(".");
|
||||
tk = token();
|
||||
switch(tk) {
|
||||
case TId(id2):
|
||||
id += id2;
|
||||
buf.add(id2);
|
||||
default: unexpected(tk);
|
||||
}
|
||||
} else {
|
||||
@@ -2399,7 +2442,7 @@ class Parser {
|
||||
break;
|
||||
}
|
||||
}
|
||||
mk(EIdent(id), tokenMin, tokenMax);
|
||||
mk(EIdent(buf.toString()), tokenMin, tokenMax);
|
||||
case TOp("!"):
|
||||
mk(EUnop("!", true, parsePreproCond()), tokenMin, tokenMax);
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user