<?xml version="1.0" ?>
<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"
       initial="wrapper" datamodel="ecmascript" name="CalculatorStateMachine">
    <datamodel>
         <data id="long_expr" />
         <data id="short_expr" />
         <data id="res" />
    </datamodel>
    <state id="wrapper" initial="on">
        <state id="on" initial="ready">
            <onentry>
                <send event="DISPLAY.UPDATE" />
            </onentry>
            <state id="ready" initial="begin">
                <state id="begin">
                    <transition event="OPER.MINUS" target="negated1" />
                    <onentry>
                        <assign location="long_expr" expr="''" />
                        <assign location="short_expr" expr="0" />
                        <assign location="res" expr="0" />
                        <send event="DISPLAY.UPDATE" />
                    </onentry>
                </state>
                <state id="result">
                </state>
                <transition event="OPER" target="opEntered" />
                <transition event="DIGIT.0" target="zero1">
                    <assign location="short_expr" expr="''" />
                </transition>
                <transition event="DIGIT" target="int1">
                    <assign location="short_expr" expr="''" />
                </transition>
                <transition event="POINT" target="frac1">
                    <assign location="short_expr" expr="''" />
                </transition>
            </state>
            <state id="negated1">
                <onentry>
                    <assign location="short_expr" expr="'-'" />
                    <send event="DISPLAY.UPDATE" />
                </onentry>
                <transition event="DIGIT.0" target="zero1" />
                <transition event="DIGIT" target="int1" />
                <transition event="POINT" target="frac1" />
            </state>
            <state id="operand1">
                <state id="zero1">
                    <transition event="DIGIT" cond="_event.name != 'DIGIT.0'" target="int1" />
                    <transition event="POINT" target="frac1" />
                </state>
                <state id="int1">
                    <transition event="POINT" target="frac1" />
                    <transition event="DIGIT">
                        <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" />
                        <send event="DISPLAY.UPDATE" />
                    </transition>
                    <onentry>
                        <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" />
                        <send event="DISPLAY.UPDATE" />
                    </onentry>
                </state>
                <state id="frac1">
                    <onentry>
                        <assign location="short_expr" expr="short_expr+'.'" />
                        <send event="DISPLAY.UPDATE" />
                    </onentry>
                    <transition event="DIGIT">
                        <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" />
                        <send event="DISPLAY.UPDATE" />
                    </transition>
                </state>
                <transition event="OPER" target="opEntered" />
            </state>
            <state id="opEntered">
                <transition event="OPER.MINUS" target="negated2" />
                <transition event="POINT" target="frac2" />
                <transition event="DIGIT.0" target="zero2" />
                <transition event="DIGIT" target="int2" />
                <onentry>
                    <raise event="CALC.SUB" />
                    <send target="#_internal" event="OP.INSERT">
                        <param name="operator" expr="_event.name" />
                    </send>
                </onentry>
            </state>
            <state id="negated2">
                <onentry>
                    <assign location="short_expr" expr="'-'" />
                    <send event="DISPLAY.UPDATE" />
                </onentry>
                <transition event="DIGIT.0" target="zero2" />
                <transition event="DIGIT" target="int2" />
                <transition event="POINT" target="frac2" />
            </state>
            <state id="operand2">
                <state id="zero2">
                    <transition event="DIGIT" cond="_event.name != 'DIGIT.0'" target="int2" />
                    <transition event="POINT" target="frac2" />
                </state>
                <state id="int2">
                    <transition event="DIGIT">
                        <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" />
                        <send event="DISPLAY.UPDATE" />
                    </transition>
                    <onentry>
                        <assign location="short_expr" expr="short_expr+_event.name.substr(_event.name.lastIndexOf('.')+1)" />
                        <send event="DISPLAY.UPDATE" />
                    </onentry>
                    <transition event="POINT" target="frac2" />
                </state>
                <state id="frac2">
                    <onentry>
                        <assign location="short_expr" expr="short_expr +'.'" />
                        <send event="DISPLAY.UPDATE" />
                    </onentry>
                    <transition event="DIGIT">
                        <assign location="short_expr" expr="short_expr +_event.name.substr(_event.name.lastIndexOf('.')+1)" />
                        <send event="DISPLAY.UPDATE" />
                    </transition>
                </state>
                <transition event="OPER" target="opEntered">
                    <raise event="CALC.SUB" />
                    <raise event="OP.INSERT" />
                </transition>
                <transition event="EQUALS" target="result">
                    <raise event="CALC.SUB" />
                    <raise event="CALC.DO" />
                </transition>
            </state>
            <transition event="C" target="on" />
        </state>
        <transition event="CALC.DO">
            <assign location="short_expr" expr="''+ res" />
            <assign location="long_expr" expr="''" />
            <assign location="res" expr="0" />
        </transition>
        <transition event="CALC.SUB">
            <if cond="short_expr!=''">
                <assign location="long_expr" expr="long_expr+'('+short_expr+')'" />
            </if>
            <assign location="res" expr="eval(long_expr)" />
            <assign location="short_expr" expr="''" />
            <send event="DISPLAY.UPDATE" />
        </transition>
        <transition event="DISPLAY.UPDATE">
            <log label="'result'" expr="short_expr==''?res:short_expr" />
            <send event="updateDisplay">
                <param name="display" expr="short_expr==''?res:short_expr"/>
            </send>
        </transition>
        <transition event="OP.INSERT">
            <log expr="_event.data.operator" />
            <if cond="_event.data.operator == 'OPER.PLUS'">
                <assign location="long_expr" expr="long_expr+'+'" />
            <elseif cond="_event.data.operator=='OPER.MINUS'" />
                <assign location="long_expr" expr="long_expr+'-'" />
            <elseif cond="_event.data.operator=='OPER.STAR'" />
                <assign location="long_expr" expr="long_expr+'*'" />
            <elseif cond="_event.data.operator=='OPER.DIV'" />
                <assign location="long_expr" expr="long_expr+'/'" />
            </if>
        </transition>
    </state>
</scxml>
