Parser optimization (#12)

This commit is contained in:
HEIHUAa
2026-01-08 14:08:37 -07:00
committed by GitHub
parent f9b5ce71b4
commit 1033e2fd10
+149 -106
View File
@@ -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: