obj kw : "kwdefs" token : "tokenrdr" bt : "bintree" st : "symbols" dat pass byte 0 insideDAT byte 0 ignoreUndefined byte 0 evalSuccess byte 0 pGlobalLabel word 0 pub set_Pass( p ) pass := p pub get_Pass return pass pub EnteringDat insideDAT~~ pub LeavingDat insideDAT~ pub Succeeded return evalSuccess pub TryToEvaluateExpression( _pGlobalLabel ) {{ }} pGlobalLabel := _pGlobalLabel ignoreUndefined~~ evalSuccess~~ return Evaluate( 13 ) pub EvaluateExpression( _pGlobalLabel ) pGlobalLabel := _pGlobalLabel ignoreUndefined~ evalSuccess~~ return Evaluate( 13 ) pri Evaluate( rbp ) | prec, lbp, t prec := token.GetPrecedence if token.AdvanceIf( kw#kAT ) result := EvaluateSymbol( true ) elseif (token.IsUnaryOp and not token.IsPostfixOp) or token.Type == kw#kMINUS t := token.Type token.Advance result := EvaluateUnary( t, prec ) elseif token.AdvanceIf( kw#kLPAREN ) result := Evaluate( 13 ) token.Eat( kw#kRPAREN ) elseif token.IsIntLiteral or token.IsFloatLiteral result := token.Value token.Advance elseif token.IsReg result := $1f0 + token.GetReg token.Advance else result := EvaluateSymbol( false ) repeat lbp := token.GetPrecedence if rbp =< lbp quit t := token.Type token.Advance result := EvaluateBinary( t, result, Evaluate( lbp ) ) pri EvaluateSymbol( takeAddress ) | p, t, pObj, cogx4, pLocalLabels {{ CON symbols evaluate as their defined values, as do OBJ#constants. DAT symbols evaluate differently depending on context. }} if byte[token.Text] == ":" ' local label? ifnot pGlobalLabel abort string("Unknown local label(1)") p := pGlobalLabel ' Search local label list for current token. repeat ifnot p := bt.PeekW( p + 6 ) ' p points to string part of local label if ignoreUndefined evalSuccess~ token.Advance return -1 ' dummy value abort string("Unknown local label(2)") if strcomp( p, token.Text ) quit p += strsize(p) + 1 ' Increment p past string part to data part ' On exit, we've found the local label. p += strsize(p) + 1 ' Increment p past string part to data part else p := st.SymbolLookup( token.Text ) ifnot p if ignoreUndefined evalSuccess~ token.Advance return -1 abort string("Unknown symbol") t := byte[p] if t == st#kINT_CON_SYMBOL or t == st#kFLOAT_CON_SYMBOL or t == st#kBUILTIN_INT_SYMBOL or t == st#kBUILTIN_FLOAT_SYMBOL ' TODO: should handle floats differently if takeAddress abort string("Can't take address of CON symbol") token.Advance return bt.PeekL( p+1 ) if t == st#kUNDEFINED_CON_SYMBOL if ignoreUndefined evalSuccess~ token.Advance return -1 ' dummy value abort string("Undefined CON symbol") if t == st#kOBJ_SYMBOL if takeAddress abort string("Can't take address of OBJ symbol") token.Advance p := bt.PeekW( p+1 ) pObj := bt.PeekW( p + strsize(p) + 2 ) token.Eat( kw#kOCTOTHORP ) ifnot p := bt.FindInTable( token.Text, pObj ) abort string("CON symbol unknown in sub-object") 't := byte[p] -- at this point, t should be either kINT_CON_SYMBOL or kFLOAT_CON_SYMBOL ' TODO: should handle floats differently token.Advance return bt.PeekL( p+1 ) if t == st#kDAT_SYMBOL if pass == 1 if ignoreUndefined evalSuccess~ token.Advance return -1 ' dummy value if takeAddress abort string("Can't take address of DAT symbol in pass 1") if not insideDAT or takeAddress token.Advance return bt.PeekW( p+2 ) cogx4 := bt.PeekW( p+4 ) if cogx4 & 3 abort string("Address is not long") token.Advance return cogx4 >> 2 abort string("Invalid symbol in constant expression") pri EvaluateUnary( t, prec ) {{ }} result := Evaluate( prec ) case t & $ff $ed: -result $e7: !result $ff: not result $f3: ||result $f8: ^^result $e9: ||result other: abort string("Syntax error in constant expression(1)") pri EvaluateBinary( t, a, b ) case t & $ff $ec: return a + b $ed: return a - b $f4: return a * b $f6: return a / b $f5: return a ** b $f7: return a // b $e0: return a -> b $e1: return a <- b $e2: return a >> b $e3: return a << b $ee: return a ~> b $ef: return a >< b $e8: return a & b $ea: return a | b $eb: return a ^ b $e4: return a #> b $e5: return a <# b $f9: return a < b $fa: return a > b $fc: return a == b $fb: return a <> b $fd: return a =< b $fe: return a => b $f0: return a and b $f2: return a or b other: abort string("Syntax error in constant expression(2)") {{ Copyright (c) 2009 Michael Park +------------------------------------------------------------------------------------------------------------------------------+ | TERMS OF USE: MIT License | +------------------------------------------------------------------------------------------------------------------------------+ |Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation | |files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, | |modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software| |is furnished to do so, subject to the following conditions: | | | |The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.| | | |THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | |WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | |COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | +------------------------------------------------------------------------------------------------------------------------------+ }}