Results 1 to 3 of 3
  1. #1
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,306
    Rep Power
    25

    Default Forward references

    Hi,
    I'm working on a project for a question on another forum where an OP is trying to write a calculator. I thought of using a FSM for this, but have a design problem in that my state tables require both forward and backward references.
    Does anyone have a design that would allow me to have the compiler test that all my linkages are good. I'm using Strings and a Hashtable to connect the states and this creates a maintenance problem.

    Thanks,
    Norm

    My code:
    Java Code:
    // Finite State Machine for calculator
    
    import java.util.*;
    
    public class FSM_ForCalculator {
    
      interface Action {
        public void doAction(char c);
      }
    
      //--------------------------------------------------------------------
      // Transitions hold action to do, next State and input to go there
      class Transition {
        char[] chars;
        String nxtState;
        Action action;
    
        public Transition(char[] chars, String nxtS, Action a){
          this.chars = chars;
          nxtState = nxtS;
          action = a;
        }
    
        public Action getAction() {
          return action;
        }
    
        public State getNextState(){
          return (State)stateRefs.get(nxtState);
        }
    
        public boolean hasChar(char c) {
          for(int i=0; i < chars.length; i++) {
            if(chars[i] == c)
              return true;
          } // end for(i)
          return false;
        }
    
        public String toString() {
          return "nxtState=" + nxtState;
        }
      } // end class
    
    
      //-------------------------------------------------------------
      class State {
         Transition[] transA;
    
         public State(Transition[] tA){
           transA = tA;
         }
    
         // Find the Transition for this character
         public Transition getTrans(char c) {
           if(transA == null)  // stay here?
             return null;  
           for(int i=0; i < transA.length; i++) {
             if(transA[i].hasChar(c))
               return transA[i];
           }
           return null;
         }
      } // end class
    
      //----------------------------------------------------------------------
      final State StayHere = new State(null);   // special no transition state
    
    
      final char[] Dot = {'.'};
      final char[] Numbers = {'0','1', '2', '3', '4', '5', '6', '7', '8', '9'};
      final char[] Operators = {'+', '-', '*', '/', '='};
    
      // Data for parsing the expression
      char opertr = '?';
      String operand = "";
      String operand1;
      String operand2;
      double results;
    
      
      Action handleLeadingSign = new Action() {
        public void doAction(char c){
           operand = new String(new char[] {c});
        }
      };
      Action handleLeadingDot = new Action() {
        public void doAction(char c){
           operand = ".";
        }
      };
      Action handleDot = new Action() {
        public void doAction(char c){
           operand += ".";
        }
      };
      Action saveDigits = new Action() {
        public void doAction(char c){
           operand += new String(new char[]{c});
        }
      };
      Action saveOperator = new Action() {
        public void doAction(char c){
           if(c == '=') {
              operand2 = operand;
    //          System.out.println("op1="  + operand1 + " op=" + opertr + " op2=" + operand2);
              double op1 = Double.parseDouble(operand1);
              double op2 = Double.parseDouble(operand2);
              switch(opertr) {
                case '+': results = op1 + op2;
                break;
                case '-': results = op1 - op2;
                break;
                case '*': results = op1 * op2;
                break;
                case '/': results = op1 / op2;
                break;
              }
    //          System.out.println("results=" + results);
    
           }else{
              opertr = c;
              operand1 = operand;
              operand = "";  // clear
           }
        }
      };
    
      // Hold references to states because of forward reference problem  
      final Hashtable stateRefs = new Hashtable();
       //FSM_ForCalculator.java(134,48) : error J0060: Invalid forward reference to member 'one'
       //FSM_ForCalculator.java(135,48) : error J0060: Invalid forward reference to member 'two'
       //FSM_ForCalculator.java(136,48) : error J0060: Invalid forward reference to member 'three'
       //FSM_ForCalculator.java(144,36) : error J0060: Invalid forward reference to member 'two'
    
      // Define FSM for calculator
      State five = new State(new Transition[] {
             new Transition(new char[] {'+', '-'}, "one", handleLeadingSign), 
             new Transition(Dot,                   "two", handleLeadingDot), 
             new Transition(Numbers,               "three", saveDigits) });
    
      State four = new State(new Transition[] {
             new Transition(Numbers,   "StayHere", saveDigits),
             new Transition(Operators, "five", saveOperator)
             });
    
      State three = new State(new Transition[] {
             new Transition(Dot,       "two", handleDot),
             new Transition(Numbers,   "StayHere", saveDigits),
             new Transition(Operators, "five", saveOperator)
             });
    
      State two = new State(new Transition[] {
             new Transition(Numbers, "four", saveDigits) });
    
      State one =  new State(new Transition[] {
             new Transition(Dot,      "two", handleDot),
             new Transition(Numbers,  "three", saveDigits) });
    
      State start = new State(new Transition[] {
             new Transition(new char[] {'+', '-'}, "one", handleLeadingSign), 
             new Transition(Dot,                   "two", handleLeadingDot), 
             new Transition(Numbers,               "three", saveDigits) });
    
    
       public void runEngine(State startHere) {/* to be developed */}
      // ---------------
      public static void main(String[] args) {
        new FSM_ForCalculator();
      }
    
      //--------------------------------------------------------------
      public FSM_ForCalculator() {
        // Fill the state references table >>>>>>>>> VERY POOR 
        stateRefs.put("start", start);
        stateRefs.put("one", one);
        stateRefs.put("two", two);
        stateRefs.put("three", three);
        stateRefs.put("four", four);
        stateRefs.put("five", five);
        stateRefs.put("StayHere", StayHere);
    
        // test data
        String data = "-12+2.1=";
        char[] chars = data.toCharArray();
    
        // The FSM Engine
        State thisState = start;   // set the starting state
        
        for(int i=0; (i < chars.length) && (thisState != null); i++) {
          Transition t = thisState.getTrans(chars[i]);
    //      System.out.println("i=" + i + ", t=" + t);
          if(t != null) {
             t.getAction().doAction(chars[i]);
             if(t.getNextState() != StayHere){
                thisState = t.getNextState(); // move to next state
    //            System.out.println("thisState=" + thisState);
             }
          }else{
            System.out.println("Invalid char: " + chars[i] + ", at i=" + i);
          }
        } // end for(i)
    
        // Report the results
        System.out.println("input=" + data + ",  op1=" + operand1 + ", operator=" + opertr + ", op2=" + operand2 
                           + ", results= " + results);
        //data=-12+2.1=,  op1=-12, operator=+, op2=2.1, results= -9.9
      }
    } // end class

  2. #2
    travishein's Avatar
    travishein is offline Senior Member
    Join Date
    Sep 2009
    Location
    Canada
    Posts
    684
    Rep Power
    5

    Default

    what if you had structures kind of like a 'schema' would be in a database,
    where the states, actions, were in their own map, indexed by some string name, and the transitions referenced the state and action by the string name (e.g. primary key) that we invent as the index for the map.

    e.g.
    Java Code:
    Map<String, State> mapOfStates = new HashMap<String,State>();
    Map<String, Action> mapOfActions = new HashMap<String, Action>();
    Where the transitions could still exist inside the states I guess, but they would refer to the next state, and the action by the string name, which presumably we would have pre-populated into these maps. I was thinking to have all transitions refer to their from-state as a string reference as well. for run time we could have another map of
    Java Code:
    Map<State, Map<Symbol,State>>
    which would be entirely generated from the references that already exist in our state, transition, and action maps.

    I was thinking of having all of the transitions themselves (also have their references stuffed into at least a list, so that after we are done setting it up, but before we are ready to use it, we could iterate over the list of transitions and validate that the referenced states and actions do actually exist in the respective maps before we try to use the FSM.

    Another benefit of the the reference by string approach, is we could have the option to read the state machine configuration from a text or .csv file perhaps our own notation something like
    Java Code:
    states
    s1,state1,other_vars_here
    s2,and so on
    actions
    a1,action1,methodname
    a2, and so on
    transitions
    t1,s1,s2,'c',a1

  3. #3
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,306
    Rep Power
    25

    Default

    Thanks for the ideas. I went with a map/hashtable and Strings for names.

    The import/export to a file is an interesting idea.

Similar Threads

  1. jsp:forward vs jsp:redirect / XML tag if
    By lse123 in forum JavaServer Pages (JSP) and JSTL
    Replies: 1
    Last Post: 01-25-2010, 08:23 AM
  2. [SOLVED] Problem using jsp:forward to a servlet
    By Norm in forum Java Servlet
    Replies: 6
    Last Post: 04-27-2009, 09:49 PM
  3. I need a back and forward code
    By Jaymz in forum New To Java
    Replies: 9
    Last Post: 10-12-2008, 11:50 PM
  4. Replies: 5
    Last Post: 07-29-2008, 02:13 PM
  5. jsp:forward action
    By Java Tip in forum Java Tip
    Replies: 0
    Last Post: 12-24-2007, 10:04 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •