/** * Strategies that do type juggling. * Apply the rules on a PHPPrimitiveType to * get a PHPPrimitiveType of the desired type. * * @author Eric Bouwers */ module php/strategy/const-prop/typejuggling rules /** * Converting to PHPBoolean. * see: http://www.php.net/manual/en/language.types.boolean.php#language.types.boolean.casting * * @type PHPPrimitiveType -> PHPBoolean */ get-php-boolean-value: PHPBoolean(bool) -> PHPBoolean(bool) // id get-php-boolean-value: PHPInteger(int) -> PHPBoolean(bool) where if <eq> (int, 0) then bool := False() else bool := True() end get-php-boolean-value: PHPFloat(real) -> PHPBoolean(bool) where if <eq> (real, 0.0) then bool := False() else bool := True() end get-php-boolean-value: PHPString(str) -> PHPBoolean(bool) where if <eq> (str, "") <+ <eq> (str, "0") then bool := False() else bool := True() end get-php-boolean-value: PHPNull() -> PHPBoolean(False()) get-php-boolean-value: aid@PHPArray(_) -> PHPBoolean(bool) where keys := <get-array-keys> aid ; if <eq> (0, <length> keys) then bool := True() else bool := False() end rules /** * Converting to PHPInteger. * see: http://www.php.net/manual/en/language.types.integer.php#language.types.integer.casting * * @type PHPPrimitiveType -> PHPInteger */ get-php-integer-value: PHPInteger(i) -> PHPInteger(i) //id get-php-integer-value: PHPBoolean(True()) -> PHPInteger(1) get-php-integer-value: PHPBoolean(False()) -> PHPInteger(0) get-php-integer-value: PHPFloat(float) -> PHPInteger(i) where i := <int> float get-php-integer-value: PHPString(str) -> PHPInteger(i) where <not(eq)> (str,"") ; str' := <extract-integer-part> str ; if <eq> (str',"") then i := 0 // Empty string is 0 else i := <string-to-int> str' end get-php-integer-value: PHPString(str) -> PHPInteger(0) where <eq> (str,"") get-php-integer-value: //NOTE: not defined in manual PHPNull() -> PHPInteger(0) get-php-integer-value: //NOTE: not defined in manual aid@PHPArray(_) -> value where bool-value := <get-php-boolean-value> aid ; value := <get-php-integer-value> bool-value rules /** * Converting to PHPFloat. * see: http://www.php.net/manual/en/language.types.float.php#language.types.float.casting * * @type PHPPrimitiveType -> PHPFloat */ get-php-float-value: PHPFloat(f) -> PHPFloat(f) get-php-float-value: PHPInteger(i) -> PHPFloat(i') where i' := <add> (i, 0.0) get-php-float-value: PHPBoolean(True()) -> PHPFloat(1) get-php-float-value: PHPBoolean(False()) -> PHPFloat(0) get-php-float-value: PHPString(str) -> PHPFloat(f) where <not(eq)> (str,"") ; str' := <extract-float-part> str ; if <eq> (str',"") // Want to make sure that string without then fail // float start failes. It has no counter-parts else f := <string-to-real> str' // in float end get-php-float-value: PHPString(str) -> PHPFloat(0) // An empty string has no counterpart where <eq> (str,"") // in float. ; fail // So it always fails get-php-float-value: //NOTE: not defined in manual PHPNull() -> PHPFloat(0) get-php-float-value: //NOTE: implementation can change aid@PHPArray(_) -> value where int-value := <get-php-integer-value> aid ; value := <get-php-float-value> int-value strategies /** * Introduction of pseudo-type number. It tries to get a float- or an integer * value. This strategy should be used for everything that is documented with * number values. */ get-php-number-value = ?val ; if <?PHPString(_)> val // should only consider float when string <+ <?PHPFloat(_)> val // or float then ( <get-php-float-value> val <+ <get-php-integer-value> val ) else <get-php-integer-value> val end rules /** * Converting to PHPString. * see: http://www.php.net/manual/en/language.types.string.php#language.types.string.casting * * @type PHPPrimitiveType -> PHPString */ get-php-string-value: PHPString(f) -> PHPString(f) get-php-string-value: PHPBoolean(True()) -> PHPString("1") get-php-string-value: PHPBoolean(False()) -> PHPString("") get-php-string-value: PHPInteger(i) -> PHPString(str) where str := <int-to-string> i get-php-string-value: PHPFloat(f) -> PHPString(str) where str := <real-to-string> f get-php-string-value: PHPNull() -> PHPString("") get-php-string-value: PHPArray(_) -> PHPString("Array") rules /** * Converting to PHPArray * see: http://www.php.net/manual/en/language.types.array.php#language.types.array.casting * * @type PHPPrimitiveType -> PHPArray */ get-php-array-value: PHPArray(aid) -> PHPArray(aid) //id get-php-array-value: t@PHPString(_) -> aid where aid := <generic-get-php-array-value> t get-php-array-value: t@PHPFloat(_) -> aid where aid := <generic-get-php-array-value> t get-php-array-value: t@PHPInteger(_) -> aid where aid := <generic-get-php-array-value> t get-php-array-value: t@PHPBoolean(_) -> aid where aid := <generic-get-php-array-value> t get-php-array-value: PHPNull() -> aid where aid := <get-new-php-array-id> strategies /** * Generic type to Array. It will make an array with one index * with the value the strategy is applied on. * * @type PHPPrimitiveType -> PHPArray */ generic-get-php-array-value = ?phpprim ; aid := <get-new-php-array-id> ; <add-array-entry(|0,phpprim)> aid strategies /** * Extracts the start of a string that can be interperted as an * integer. * * @type String -> String */ extract-integer-part = explode-string ; ( try-take-pos-take-neg(take-while(is-num)) <+ take-while(is-num) ) ; implode-string /** * Extracts the start of a string that can be interperted as an * float. * * @type String -> String */ extract-float-part = explode-string ; ( try-take-pos-take-neg(take-float-part) <+ take-float-part ) ; implode-string /** * Tries to match element of a list given a strategy. * It first matches on a "+" or a "-". * * @type: List(Char) -> List(Char) */ try-take-pos-take-neg(s) = take-positive-part(s) <+ take-negative-part(s) /** * Matches on the "+" and a givens strategy. Build the result as * the "+" and the result of the strategy. * * @type: List(Char) -> List(Char) */ take-positive-part(s) = ?[ 43 | nums ] ; <s> nums ; ![ 43 | <id> ] /** * Matches on the "-" and a givens strategy. Build the result as * the "-" and the result of the strategy. * * @type: List(Char) -> List(Char) */ take-negative-part(s) = ?[ 45 | nums ] ; <s> nums ; ![ 45 | <id> ] /** * Returns the elements of a list of Chars the correspond * to a "." and a sequence of numbers. * * @type: List(Char) -> List(Char) */ take-decimal-part = ?[46 | tail] ; <take-while(is-num)> tail ; ![ 46 | <id> ] /** * Returns the elements of a list of Chars the correspond * to a "e" and a sequence of numbers. * * @type: List(Char) -> List(Char) */ take-exponent-part = ?[101 | tail] ; <take-while(is-num)> tail ; ![101 | <id> ] /** * Returns the elements of a list of Chars the correspond * to a "E" and a sequence of numbers. * * @type: List(Char) -> List(Char) */ take-exponent-part = ?[69 | tail] ; <take-while(is-num)> tail ; ![69 | <id> ] rules /** * Takes a list of Chars and extracts the part that can be interpreted as a * float. This is an optional list of numbers, an optional point, a list of * numbers followed by an optional e/E with numbers behind it. * (0-9]+ [\.]? [0-9]+? ([eE][0-9]+)? * * The rule truncates the rest of the list. * * @Type: List(Char) -> List(Char) */ // No digits OR "." followed by numbers take-float-part : chars -> res where ([],_,_) := <split-fetch-keep(not(is-num))> chars //Does not start with a digit ; ( res := <take-decimal-part> chars <+ res := [] ) // numbers "." numbers ("eE" numbers)? take-float-part : chars -> result where ([],_,_) := <split-fetch-keep(is-num)> chars //Does start with a digit ; (nat,46,tail) := <split-fetch-keep(not(is-num))> chars ; if (decimal,101,rest) := <split-fetch-keep(not(is-num))> tail <+ (decimal,69 ,rest) := <split-fetch-keep(not(is-num))> tail then exp := <take-exponent-part> [ 69 | rest ] ; base := Conc(nat,[ 46 | decimal]) ; result := Conc(base,exp) else decimal := <take-decimal-part> [ 46 | tail ] ; result := Conc(nat,decimal) end // numbers "e" numbers OR numbers "E" numbers take-float-part : chars -> result where ([],_,_) := <split-fetch-keep(is-num)> chars //Does start with a digit ; ( ( (nat,101,rest) := <split-fetch-keep(not(is-num))> chars ; exp := <take-exponent-part> [ 101 | rest ] ) <+ ( (nat,69 ,rest) := <split-fetch-keep(not(is-num))> chars ; exp := <take-exponent-part> [ 69 | rest ] ) ) ; result := Conc(nat,exp)