diff --git a/hscript/Parser.hx b/hscript/Parser.hx index 4552d30..d4c8f67 100644 --- a/hscript/Parser.hx +++ b/hscript/Parser.hx @@ -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 ):Void { + @:analyzer(fusion) function parseFullExpr( exprs : Array ):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 = []; // 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 = 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: