From a30c33cdc43b5adfa1396e08c756a54438d8184d Mon Sep 17 00:00:00 2001 From: Nicolas Cannasse Date: Tue, 29 Mar 2011 20:19:43 +0000 Subject: [PATCH] added ETernary, fixed operand priority to match haXe one --- hscript/Bytes.hx | 4 +++ hscript/Expr.hx | 1 + hscript/Interp.hx | 2 ++ hscript/Parser.hx | 81 +++++++++++++++++++++++++---------------------- 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/hscript/Bytes.hx b/hscript/Bytes.hx index 2b499c4..3973ef8 100644 --- a/hscript/Bytes.hx +++ b/hscript/Bytes.hx @@ -211,6 +211,10 @@ class Bytes { doEncodeString(f.name); doEncode(f.e); } + case ETernary(cond, e1, e2): + doEncode(cond); + doEncode(e1); + doEncode(e2); } } diff --git a/hscript/Expr.hx b/hscript/Expr.hx index e25529e..ebb74a1 100644 --- a/hscript/Expr.hx +++ b/hscript/Expr.hx @@ -63,6 +63,7 @@ enum Expr { EThrow( e : Expr ); ETry( e : Expr, v : String, t : Null, ecatch : Expr ); EObject( fl : Array<{ name : String, e : Expr }> ); + ETernary( cond : Expr, e1 : Expr, e2 : Expr ); } enum CType { diff --git a/hscript/Interp.hx b/hscript/Interp.hx index 17231bb..45e5815 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -346,6 +346,8 @@ class Interp { for( f in fl ) set(o,f.name,expr(f.e)); return o; + case ETernary(econd,e1,e2): + return if( expr(econd) == true ) expr(e1) else expr(e2); } return null; } diff --git a/hscript/Parser.hx b/hscript/Parser.hx index f247c68..9aa3196 100644 --- a/hscript/Parser.hx +++ b/hscript/Parser.hx @@ -49,9 +49,9 @@ class Parser { public var line : Int; public var opChars : String; public var identChars : String; - public var opPriority : Array; - public var unopsPrefix : Array; - public var unopsSuffix : Array; + public var opPriority : Hash; + public var opRightAssoc : Hash; + public var unops : Hash; // true if allow postfix /** activate JSON compatiblity @@ -89,19 +89,28 @@ class Parser { line = 1; opChars = "+*/-=!><&|^%~"; identChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; - opPriority = [ - "...", - "=", - "||","&&", - "==","!=",">","<",">=","<=", - "|","&","^", - "<<",">>",">>>", - "+","-", - "*","/", - "%" + var priorities = [ + ["%"], + ["*", "/"], + ["+", "-"], + ["<<", ">>", ">>>"], + ["|", "&", "^"], + ["==", "!=", ">", "<", ">=", "<="], + ["..."], + ["&&"], + ["||"], + ["=","+=","-=","*=","/=","%=","<<=",">>=",">>>=","|=","&=","^="], ]; - unopsPrefix = ["!","++","--","-","~"]; - unopsSuffix = ["++", "--"]; + opPriority = new Hash(); + opRightAssoc = new Hash(); + for( i in 0...priorities.length ) + for( x in priorities[i] ) { + opPriority.set(x, i); + if( i == 9 ) opRightAssoc.set(x, true); + } + unops = new Hash(); + for( x in ["!", "++", "--", "-", "~"] ) + unops.set(x, x == "++" || x == "--"); } public inline function error( err, pmin, pmax ) { @@ -279,7 +288,7 @@ class Parser { case TPOpen: var e = parseExpr(); ensure(TPClose); - return parseExprNext(mk(EParent(e),p1,pmax(e))); + return parseExprNext(mk(EParent(e),p1,tokenMax)); case TBrOpen: tk = token(); switch( tk ) { @@ -324,10 +333,8 @@ class Parser { } return mk(EBlock(a),p1); case TOp(op): - var found; - for( x in unopsPrefix ) - if( x == op ) - return makeUnop(op,parseExpr()); + if( unops.exists(op) ) + return makeUnop(op,parseExpr()); return unexpected(tk); case TBkOpen: var a = new Array(); @@ -345,16 +352,10 @@ class Parser { } } - function priority(op) { - for( i in 0...opPriority.length ) - if( opPriority[i] == op ) - return i; - return -1; - } - function makeUnop( op, e ) { return switch( expr(e) ) { - case EBinop(bop, e1, e2): mk(EBinop(bop, makeUnop(op, e1), e2),pmin(e1),pmax(e2)); + case EBinop(bop, e1, e2): mk(EBinop(bop, makeUnop(op, e1), e2), pmin(e1), pmax(e2)); + case ETernary(e1,e2,e3): mk(ETernary(makeUnop(op,e1),e2,e3),pmin(e1) default: mk(EUnop(op,true,e),pmin(e),pmax(e)); } } @@ -362,10 +363,15 @@ class Parser { function makeBinop( op, e1, e ) { return switch( expr(e) ) { case EBinop(op2,e2,e3): - if( priority(op) > priority(op2) ) + if( opPriority.get(op) <= opPriority.get(op2) && !opRightAssoc.exists(op) ) mk(EBinop(op2,makeBinop(op,e1,e2),e3),pmin(e1),pmax(e3)); else - mk(EBinop(op, e1, e),pmin(e1),pmax(e)); + mk(EBinop(op, e1, e), pmin(e1), pmax(e)); + case ETernary(e2,e3,e4): + if( opRightAssoc.exists(op) ) + mk(EBinop(op,e1,e),pmin(e1),pmax(e)); + else + mk(ETernary(makeBinop(op, e1, e2), e3, e4), pmin(e1), pmax(e)); default: mk(EBinop(op,e1,e),pmin(e1),pmax(e)); } @@ -537,14 +543,13 @@ class Parser { var tk = token(); switch( tk ) { case TOp(op): - for( x in unopsSuffix ) - if( x == op ) { - if( isBlock(e1) || switch(expr(e1)) { case EParent(_): true; default: false; } ) { - push(tk); - return e1; - } - return parseExprNext(mk(EUnop(op,false,e1),pmin(e1))); + if( unops.get(op) ) { + if( isBlock(e1) || switch(expr(e1)) { case EParent(_): true; default: false; } ) { + push(tk); + return e1; } + return parseExprNext(mk(EUnop(op,false,e1),pmin(e1))); + } return makeBinop(op,e1,parseExpr()); case TDot: tk = token(); @@ -564,7 +569,7 @@ class Parser { var e2 = parseExpr(); ensure(TDoubleDot); var e3 = parseExpr(); - return mk(EIf(e1,e2,e3),pmin(e1),pmax(e3)); + return mk(ETernary(e1,e2,e3),pmin(e1),pmax(e3)); default: push(tk); return e1;