fsmgen : An automatic FSM generator

Download fsmgen.zip

Synopsis:

jaa.xml
jaa.xsl
fsmgen.java
GraphicalUI.java
TextualUI.java
BasicWindowMonitor.java
FileChooserAction.java
FileChooserDialog.java
FsmTableHandler.java
FsmView.java
MainFrame.java
MenuActionHandler.java
MenuActions.java
MenuHandler.java
MenuStates.java
Vector2D.java
FsmAction.java
FsmActions.java
FsmGenerator.java
FsmModel.java
FsmOptions.java
FsmParameters.java
FsmState.java
FsmStates.java
FsmStimulii.java
FsmStimulus.java
FsmTransition.java
FsmTransitions.java
GennedFile.java
GenProcessor.java
TemplateFile.java
TemplateProcessor.java
Token.java
XmlFile.java
XmlLexer.java
XmlParser.java
XmlWriter.java
Globals.java
fsm.cpp.cpp.tpl
fsm.h.cpp.tpl


jaa.xml

Synopsis
<?xml version="1.0" standalone="yes"?>
<!-- WARNING! Do not modify this file!
     WARNING! This file is not XML.
     It looks like XML but if any other XML constructs are used,
     fsmgen will fail!
-->
<?xml-stylesheet type="text/xsl" href="jaa.xsl" ?>

<fsm>
<options>
  <start>STATE_S1</start>
  <init>once</init>
  <outdir>.\debug</outdir>
  <outlang>cpp</outlang>
</options>

<action>
  <name>DoNothing</name>
  <desc>Do not perform any action</desc>
  <cppcode><![CDATA[
    return false;
  ]]></cppcode>
</action>

<action>
  <name>PutCurrChar</name>
  <desc>emit the current character</desc>
  <cppcode><![CDATA[
    fputc(fp.m_ch, stdout);
    return false;
  ]]></cppcode>
</action>

<action>
  <name>PutSlashThenCurrChar</name>
  <desc>emit a '/' and then the current character</desc>
  <cppcode><![CDATA[
    fputc('/', stdout);
    fputc(fp.m_ch, stdout);
    return false;
  ]]></cppcode>
</action>

<stim>
  <name>Slash</name>
  <desc>matches a '/'</desc>
  <cppcode><![CDATA[
    return !fp.m_eof && fp.m_ch == '/';
  ]]></cppcode>
</stim>

<stim>
  <name>NewLine</name>
  <desc>matches a '\n'</desc>
  <cppcode><![CDATA[
    return !fp.m_eof && fp.m_ch == '\n';
  ]]></cppcode>
</stim>

<stim>
  <name>EOF</name>
  <desc>matches the end of the file</desc>
  <cppcode><![CDATA[
    return fp.m_eof;
  ]]></cppcode>
</stim>

<stim>
  <name>Other</name>
  <desc>matches any character</desc>
  <cppcode><![CDATA[
    return true;
  ]]></cppcode>
</stim>

<state>
  <name>FINAL</name>
  <desc>we're at the end of the file; all done</desc>
  <final>true</final>
</state>

<state>
  <name>S1</name>
  <desc>normal text has gone by, no slashes seen</desc>
  <final>false</final>
</state>

<state>
  <name>S2</name>
  <desc>the first slash has been seen; looking for the second one</desc>
  <final>false</final>
</state>

<state>
  <name>S3</name>
  <desc>the second slash has gone by; we're in a comment</desc>
  <final>false</final>
</state>

<transition>
  <state>FINAL</state>
  <stim>Other</stim>
  <action>DoNothing</action>
  <next>FINAL</next>
</transition>

<transition>
  <state>S1</state>
  <stim>Slash</stim>
  <action>DoNothing</action>
  <next>S2</next>
</transition>

<transition>
  <state>S1</state>
  <stim>EOF</stim>
  <action>DoNothing</action>
  <next>FINAL</next>
</transition>

<transition>
  <state>S1</state>
  <stim>NewLine</stim>
  <action>PutCurrChar</action>
  <next>S1</next>
</transition>

<transition>
  <state>S1</state>
  <stim>Other</stim>
  <action>PutCurrChar</action>
  <next>S1</next>
</transition>

<transition>
  <state>S2</state>
  <stim>Slash</stim>
  <action>DoNothing</action>
  <next>S3</next>
</transition>

<transition>
  <state>S2</state>
  <stim>EOF</stim>
  <action>DoNothing</action>
  <next>FINAL</next>
</transition>

<transition>
  <state>S2</state>
  <stim>NewLine</stim>
  <action>PutSlashThenCurrChar</action>
  <next>S1</next>
</transition>

<transition>
  <state>S2</state>
  <stim>Other</stim>
  <action>PutSlashThenCurrChar</action>
  <next>S1</next>
</transition>

<transition>
  <state>S3</state>
  <stim>NewLine</stim>
  <action>PutCurrChar</action>
  <next>S1</next>
</transition>

<transition>
  <state>S3</state>
  <stim>EOF</stim>
  <action>DoNothing</action>
  <next>FINAL</next>
</transition>

<transition>
  <state>S3</state>
  <stim>Slash</stim>
  <action>DoNothing</action>
  <next>S3</next>
</transition>

<transition>
  <state>S3</state>
  <stim>Other</stim>
  <action>DoNothing</action>
  <next>S3</next>
</transition>

</fsm>

jaa.xsl

Synopsis
<?xml version="1.0"?>
<xsl:stylesheet
     xmlns:xsl="http://www.w3.org/TR/WD-xsl" version="1.0"
  >
  <xsl:template match="/">
    <html>
      <Title>FSM Generator</Title>
      <xsl:apply-templates/>
    </html>
  </xsl:template>

  <xsl:template match="fsm">
    <body>
      <xsl:apply-templates select="options" />
      <table cols='4' border='1' cellspacing='1' cellpadding='8'>
      <tr><strong>FSM Matrix</strong></tr>
      <xsl:apply-templates select="transition"/>
      </table>
      <H1 style="background-color=#00AAFF">States</H1>
      <xsl:apply-templates select="state"/>
      <H1 style="background-color=#00AAFF">Stimulii</H1>
      <xsl:apply-templates select="stim"/>
      <H1 style="background-color=#00AAFF">Actions</H1>
      <xsl:apply-templates select="action"/>
    </body>
  </xsl:template>

  <xsl:template match="options">
    <strong>General parameters:</strong><br/>
    <table cols='2' style="spacing=0">
    <tr><td>Start State:    </td><td><xsl:value-of select="start" />   </td></tr>
    <tr><td>Output Dir:     </td><td><xsl:value-of select="outdir" />  </td></tr>
    <tr><td>Ouput Language: </td><td><xsl:value-of select="outlang" /> </td></tr>
    <tr><td>Initialize done:</td><td><xsl:value-of select="init" />    </td></tr>
    </table>
    <br/>
  </xsl:template>

  <xsl:template match="transition">
    <tr>
     <td><a><xsl:attribute name='href'>#<xsl:value-of select="state" /></xsl:attribute><xsl:value-of select="state" /></a></td>
     <td><a><xsl:attribute name='href'>#<xsl:value-of select="stim" /></xsl:attribute><xsl:value-of select="stim" /></a></td>
     <td><a><xsl:attribute name='href'>#<xsl:value-of select="action" /></xsl:attribute><xsl:value-of select="action" /></a></td>
     <td><a><xsl:attribute name='href'>#<xsl:value-of select="next" /></xsl:attribute><xsl:value-of select="next" /></a></td>
    </tr>
  </xsl:template>

  <xsl:template match="state">
    State:  <strong><a><xsl:attribute name='name'>#<xsl:value-of select="name" /></xsl:attribute><xsl:value-of select="name" /></a></strong>
    <br/>
    <a href="#top" style="border: groove red 1px">Top</a>
    <br/><br/>
    Is it a final state: <xsl:value-of select="final" />
    <em><p style="margin-left=5em"><xsl:value-of select="desc" /></p></em>
    <hr/>
  </xsl:template>

  <xsl:template match="action">
    Action:  <strong><a><xsl:attribute name='name'>#<xsl:value-of select="name" /></xsl:attribute><xsl:value-of select="name" /></a></strong>
    <br/>
    <a href="#top" style="border: groove red 1px">Top</a>
    <p style="margin-left:5em"><xsl:value-of select="desc" /></p>
    <strong>CPP code:</strong>
    <pre style="margin=0;background-color=#EEEEDD">
    <xsl:value-of select="cppcode" />
    </pre>
    <hr/>
  </xsl:template>

  <xsl:template match="stim">
    Stimulus:  <strong><a><xsl:attribute name='name'>#<xsl:value-of select="name" /></xsl:attribute><xsl:value-of select="name" /></a></strong>
    <br/>
    <a href="#top" style="border: groove red 1px">Top</a>
    <em><p style="margin-left=5em"><xsl:value-of select="desc" /></p></em>
    <strong>CPP code:</strong>
    <pre style="margin=0;background-color=#EEEEDD">
    <xsl:value-of select="cppcode" />
    </pre>
    <hr/>
  </xsl:template>

</xsl:stylesheet>



fsmgen.java

Synopsis
class fsmgenmain
  {
  public static void main(String args[])
    {
    if (args.length == 0)
      {
      new GraphicalUI().run();
      return ;
      }

    if (args.length == 1)
      {
      new TextualUI().run(args);
      return ;
      }

    if (args.length > 1)
      {
      System.out.println("usage: fsmgenmain <inputfile>");
      return ;
      }
    }
  }

GraphicalUI.java

Synopsis
import gui.*;
import javax.swing.*;

class GraphicalUI
  {
  public void run()
    {
    try
      {
      //jaa: add L&F chooser
      UIManager.setLookAndFeel(new com.sun.java.swing.plaf.windows.WindowsLookAndFeel());
      }
    catch (UnsupportedLookAndFeelException e)
      {
      System.out.println("unsupported look and feel: windows");
      System.exit(1);
      }
    MainFrame mf = new MainFrame();
    mf.show();
    }
  }

TextualUI.java

Synopsis
import common.Globals;

class TextualUI
  {
  public void run(String args[])
    {
    //FsmModel fsmmodel = new FsmModel();

    Globals.model.load(args[0]);
    //Globals.model.dump(); //jaa: temp for testing!
    Globals.model.gen();

    Globals.model.save();  //jaa: temp for testing!
    Globals.model.saveAs(args[0] + ".save");//jaa: temp for testing!
    }
  }

BasicWindowMonitor.java

Synopsis
package gui;

import java.awt.event.*;
import java.awt.Window;

class BasicWindowMonitor extends WindowAdapter
  {
  public void windowClosing(WindowEvent e)
    {
    System.out.println("BasicWindowMonitor: windowclosing");
    Window w = e.getWindow();
    w.setVisible(false);
    w.dispose();
    System.exit(0);
    }
  }

FileChooserAction.java

Synopsis
package gui;

//-----------------------------------------------------------------------
public interface FileChooserAction
  {
  void action(String path);
  }

FileChooserDialog.java

Synopsis
package gui;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import java.io.File;
import javax.swing.filechooser.FileFilter;

//-----------------------------------------------------------------------
public class FileChooserDialog
  {
  //-----------------------------------------------------------------------
  public void Open(JFrame parent, FileChooserAction ca)
    {
    choose(1, parent, ca);
    }

  //-----------------------------------------------------------------------
  public void Save(JFrame parent, FileChooserAction ca)
    {
    choose(2, parent, ca);
    }

  //-----------------------------------------------------------------------
  private void choose(int dlgtype, JFrame parent, FileChooserAction ca)
    {
    JFileChooser chooser = new JFileChooser();
    chooser.setCurrentDirectory(new File("."));
    chooser.setFileFilter(new ExtensionFileFilter());

    int rc;
    if (dlgtype == 1)
      rc = chooser.showOpenDialog(parent);
    else
      rc = chooser.showSaveDialog(parent);

    if (rc == JFileChooser.APPROVE_OPTION)
      ca.action(chooser.getSelectedFile().getAbsolutePath());
    }

  //-----------------------------------------------------------------------
  private class ExtensionFileFilter extends FileFilter
    {
    //-----------------------------------------------------------------------
    public boolean accept(File f)
      {
      return f.getName().toLowerCase().endsWith(".xml") ||
             f.isDirectory();
      }

    //-----------------------------------------------------------------------
    public String getDescription()
      {
      return "Fsm descriptor file";
      }
    }
  }

FsmTableHandler.java

Synopsis
package gui;

import javax.swing.table.*;
import common.*;

//----------------------------------------------
class FsmTableHandler extends AbstractTableModel
  {
  private static final String cColumns[] = {"State", "Stimulus", "Action", "NextState"};

  //----------------------------------------------
  public int getColumnCount()
    {
    return 4;
    }

  //----------------------------------------------
  public int getRowCount()
    {
    return Globals.model.getRowCount();
    }

  //----------------------------------------------
  public Object getValueAt(int row, int col)
    {
    return Globals.model.getValueAt(row, col);
    }

  //----------------------------------------------
  public String getColumnName(int col)
    {
    return cColumns[col];
    }
  }

FsmView.java

Synopsis
package gui;
import javax.swing.JFrame;

interface FsmView
  {
  JFrame frame();

  boolean askConfirmation(String cmd);
  boolean askOverwriteConfirmation(String cmd, String path);

  boolean isDirty();
  void setClean();
  void setDirty();

  boolean isTableView();
  void setTableView();
  boolean isGraphView();
  void setGraphView();

  void showTable();
  void hideTable();

  void setFilename(String title);
  void setModifiedFlag(boolean val);
  void setGennedFlag(boolean val);
  void reshow();
  }

MainFrame.java

Synopsis
package gui;

import java.io.File;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JOptionPane;

//-----------------------------------------------------------------------
public class MainFrame extends JFrame implements FsmView
  {
  private static final String cCaptionPrefix = "fsmgen v0.0";

  MenuHandler menuHandler;
  JScrollPane jsp;
  JTable jtbl;
  boolean modFlag;  //indicates if the current file has been modified
  boolean genFlag;  //indicates if the current file has been genned
  static final int cTableView = 1;
  static final int cGraphView = 2;
  int curView;
  boolean isDirty;

  //-----------------------------------------------------------------------
  public MainFrame()
    {
    super(cCaptionPrefix);
    menuHandler = new MenuHandler(this);
    modFlag = false;
    //jaa: get intial view from global options...
    curView = cTableView;

    addWindowListener(new BasicWindowMonitor());

    Toolkit tk = Toolkit.getDefaultToolkit();
    setSize(tk);
    setIcon(tk);
    setJMenuBar(menuHandler.createMenuBar());

    jtbl = new JTable(new FsmTableHandler());
    jsp = new JScrollPane(jtbl);
    jsp.setVisible(false);
    getContentPane().add(jsp, BorderLayout.CENTER);

    setVisible(true);
    }

  //-----------------------------------------------------------------------
  public boolean isDirty()
  {
    return isDirty;
    }

  //-----------------------------------------------------------------------
  public void setClean()
    {
    isDirty = false;
    }
  //-----------------------------------------------------------------------
  public void setDirty()
    {
    isDirty = true;
    }

  //-----------------------------------------------------------------------
  public boolean askConfirmation(String cmd)
    {
    if (!isDirty())
      return true;

    return askRawConfirmation("The current fsm has been modified.\nAre you sure you want to " + cmd + "?");
    }

  //-----------------------------------------------------------------------
  public boolean askOverwriteConfirmation(String cmd, String path)
    {
    File f = new File(path);
    if (!f.exists())
      return true;
    return askRawConfirmation("You chose to " + cmd + " this existing file:\n    " + path + "\nAre you sure you want to overwrite it?");
    }

  //-----------------------------------------------------------------------
  private boolean askRawConfirmation(String question)
    {
    int rc = JOptionPane.showConfirmDialog(this,
                                           question, "Please confirm...",
                                           JOptionPane.YES_NO_OPTION);
    reshow();
    return (rc != JOptionPane.NO_OPTION);
    }

  //-----------------------------------------------------------------------
  public boolean isTableView()
    {
    return curView == cTableView;
    }

  //-----------------------------------------------------------------------
  public void setTableView()
    {
    curView = cTableView;
    }

  //-----------------------------------------------------------------------
  public boolean isGraphView()
    {
    return curView == cGraphView;
    }

  //-----------------------------------------------------------------------
  public void setGraphView()
    {
    curView = cGraphView;
    }

  //-----------------------------------------------------------------------
  public void reshow()
    {
    jtbl.revalidate();
    }

  //-----------------------------------------------------------------------
  public void setFilename(String path)
    {
    if (path == null)
      setTitle(cCaptionPrefix);
    else
      setTitle(cCaptionPrefix + " : " + path);
    }

  //-----------------------------------------------------------------------
  public void setModifiedFlag(boolean val)
    {
    modFlag = val;
    }

  //-----------------------------------------------------------------------
  public void setGennedFlag(boolean val)
    {
    genFlag = val;
    }

  //-----------------------------------------------------------------------
  public JFrame frame()
    {
    return this;
    }

  //-----------------------------------------------------------------------
  public void showTable()
    {
    jsp.setVisible(true);
    System.out.println("showTable");
    validate();
    }
  //-----------------------------------------------------------------------
  public void hideTable()
    {
    jsp.setVisible(false);
    System.out.println("hideTable");
    validate();
    }

  //-----------------------------------------------------------------------
  private void setSize(Toolkit tk)
    {
    Dimension d = tk.getScreenSize();
    int screenHeight = d.height;
    int screenWidth = d.width;
    setSize(screenWidth / 2, screenHeight / 2);
    setLocation(screenWidth / 4, screenHeight / 4);
    }

  //-----------------------------------------------------------------------
  private void setIcon(Toolkit tk)
    {
    Image img = tk.getImage("fsmgen.jpg");
    setIconImage(img);
    }
  }


MenuActionHandler.java

Synopsis
package gui;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JOptionPane;


//-----------------------------------------------------------------------
class MenuActionHandler
  {
  MenuActions menuactions;
  FsmView view;

  //-----------------------------------------------------------------------
  public MenuActionHandler(FsmView v, MenuActions ma)
    {
    view = v;
    menuactions = ma;
    }

  //-----------------------------------------------------------------------
  public ActionListener OpenListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                Open();
                }
              }
           ) ;
    }

  //-----------------------------------------------------------------------
  public ActionListener CloseListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                Close();
                }
              }
           ) ;
    }

  //-----------------------------------------------------------------------
  public ActionListener SaveListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                menuactions.Save();
                }
              }
           ) ;
    }

  //-----------------------------------------------------------------------
  public ActionListener SaveAsListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                SaveAs();
                }
              }
           ) ;
    }

  //-----------------------------------------------------------------------
  public ActionListener ExitListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                Exit();
                }
              }
           ) ;
    }

  //-----------------------------------------------------------------------
  public ActionListener EditListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                menuactions.Edit();
                }
              }
           ) ;
    }
  //-----------------------------------------------------------------------
  public ActionListener GenListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                menuactions.Gen();
                }
              }
           ) ;
    }

  //-----------------------------------------------------------------------
  public ActionListener ViewTableListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                menuactions.ViewTable();
                }
              }
           ) ;
    }


  //-----------------------------------------------------------------------
  public ActionListener ViewGraphListener()
    {
    return (new ActionListener()
              {
              public void actionPerformed(ActionEvent e)
                {
                menuactions.ViewGraph();
                }
              }
           ) ;
    }

  //-----------------------------------------------------------------------
  private void Open()
    {
    if (!view.askConfirmation("Open"))
      return ;

    FileChooserDialog cd = new FileChooserDialog();
    cd.Open(view.frame(),
            new FileChooserAction()
              {
              public void action(String path)
                {
                menuactions.Open(path);
                }
              }
           );
    view.reshow();
    }

  //-----------------------------------------------------------------------
  private void SaveAs()
    {
    FileChooserDialog cd = new FileChooserDialog();
    cd.Save(view.frame(),
            new FileChooserAction()
              {
              public void action(String path)
                {
                if (!view.askOverwriteConfirmation("Save As", path))
                  return ;

                menuactions.SaveAs(path);
                }
              }
           );
    view.reshow();
    }

  //-----------------------------------------------------------------------
  private void Exit()
    {
    if (!view.askConfirmation("Exit"))
      return ;

    menuactions.Exit();
    }

  //-----------------------------------------------------------------------
  private void Close()
    {
    if (!view.askConfirmation("Close"))
      return ;

    menuactions.Close();
    }

  }


MenuActions.java

Synopsis
package gui;

import java.awt.event.WindowEvent;
import java.awt.Toolkit;

import common.*;

//-----------------------------------------------------------------------
class MenuActions
  {
  MenuStates menustates;
  FsmView view;

  //-----------------------------------------------------------------------
  MenuActions(FsmView v, MenuStates ms)
    {
    menustates = ms;
    view = v;
    }

  //-----------------------------------------------------------------------
  void Open(String path)
    {
    Globals.model.load(path);
    menustates.setClean();
    view.showTable();
    view.setFilename(path);
    view.setModifiedFlag(false);
    view.setGennedFlag(false);
    }

  //-----------------------------------------------------------------------
  void Close()
    {
    Globals.model.close();
    menustates.resetAll();
    view.hideTable();
    view.setFilename(null);
    view.setModifiedFlag(false);
    view.setGennedFlag(false);
    view.reshow();
    }

  //-----------------------------------------------------------------------
  void Save()
    {
    Globals.model.save();
    menustates.resetDirty();
    view.setFilename(null);
    view.setModifiedFlag(false);
    }

  //-----------------------------------------------------------------------
  void SaveAs(String path)
    {
    Globals.model.saveAs(path);
    menustates.resetDirty();
    view.setFilename(path);
    view.setModifiedFlag(false);
    }

  //-----------------------------------------------------------------------
  void Edit()
    {
    Globals.model.edit();
    menustates.setDirty();
    view.setModifiedFlag(true);
    view.setGennedFlag(false);
    }

  //-----------------------------------------------------------------------
  void ViewTable()
    {
    if (view.isTableView())
      return ;

    System.out.println("Switching to Table view.");
    view.setTableView();
    }

  //-----------------------------------------------------------------------
  void ViewGraph()
    {
    if (view.isGraphView())
      return ;

    System.out.println("Switching to Graph view.");
    view.setGraphView();
    }

  //-----------------------------------------------------------------------
  void Gen()
    {
    Globals.model.gen();
    menustates.setGenned();
    view.setGennedFlag(true);
    }

  //-----------------------------------------------------------------------
  void Exit()
    {
    menustates.resetAll();
    WindowEvent we = new WindowEvent(view.frame(), WindowEvent.WINDOW_CLOSING);
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(we);
    }
  }

MenuHandler.java

Synopsis
package gui;

import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JCheckBoxMenuItem;

import javax.swing.ButtonGroup;
import javax.swing.JMenuBar;
import javax.swing.border.*;
import java.awt.event.ActionListener;

//to add a menu:
//  - add the menu to the menubar in createMenuBar
//  - add a handler in MenuActionHandler.java
//
//to add a menu item:
//  -

//-----------------------------------------------------------------------
class MenuHandler
  {
  FsmView view;
  MenuActionHandler actHandler;
  MenuActions menuactions;
  MenuStates menustates;
  JMenuBar menuBar;
  JMenuItem miFileOpen;
  JMenuItem miFileClose;
  JMenuItem miFileSave;
  JMenuItem miFileSaveAs;
  JMenuItem miGen;
  JMenuItem miEdit;
  JCheckBoxMenuItem miTableView;
  JCheckBoxMenuItem miGraphView;

  //-----------------------------------------------------------------------
  public MenuHandler(FsmView v)
    {
    view = v;
    menustates = new MenuStates(view, this);
    menuactions = new MenuActions(view, menustates);
    actHandler = new MenuActionHandler(view, menuactions);
    }

  //-----------------------------------------------------------------------
  public JMenuBar createMenuBar()
    {
    menuBar = new JMenuBar();
    menuBar.add(createFileMenu("File"));
    menuBar.add(createEditMenu("Edit"));
    menuBar.add(createViewMenu("View"));
    menuBar.add(createToolsMenu("Tools"));
    menuBar.setBorder(new BevelBorder(BevelBorder.RAISED));
    menustates.resetAll();

    return menuBar;
    }

  //-----------------------------------------------------------------------
  public void setEnabledStates()
    {
    //miFileOpen always enabled
    miFileClose.setEnabled(menustates.okToClose());
    miFileSave.setEnabled(menustates.okToSave());
    miFileSaveAs.setEnabled(menustates.okToSaveAs());
    miGen.setEnabled(menustates.okToGen());
    miEdit.setEnabled(menustates.okToModify());

    boolean tbview = view.isTableView();
    miTableView.setState(tbview);
    miGraphView.setState(!tbview);

    menuBar.revalidate();
    }

  //-----------------------------------------------------------------------
  private JMenu createFileMenu(String tag)
    {
    JMenu m = new JMenu(tag);
    JMenuItem fileexit;

    miFileOpen = CreateMenuItem("Open...", actHandler.OpenListener());
    miFileClose = CreateMenuItem("Close", actHandler.CloseListener());
    miFileSave = CreateMenuItem("Save", actHandler.SaveListener());
    miFileSaveAs = CreateMenuItem("Save As...", actHandler.SaveAsListener());
    fileexit = CreateMenuItem("Exit", actHandler.ExitListener());

    m.add(miFileOpen);
    m.add(miFileClose);
    m.add(miFileSave);
    m.add(miFileSaveAs);
    m.addSeparator();
    m.add(fileexit);

    return m;
    }

  //-----------------------------------------------------------------------
  private JMenu createEditMenu(String tag)
    {
    JMenu m = new JMenu(tag);

    miEdit = CreateMenuItem("Edit States...", actHandler.EditListener());
    m.add(miEdit);

    return m;
    }

  //-----------------------------------------------------------------------
  private JMenu createToolsMenu(String tag)
    {
    JMenu m = new JMenu(tag);

    miGen = CreateMenuItem("Gen!", actHandler.GenListener());
    m.add(miGen);

    return m;
    }

  //-----------------------------------------------------------------------
  private JMenu createViewMenu(String tag)
    {
    JMenu m = new JMenu(tag);
    ButtonGroup group = new ButtonGroup();

    //jaa: get intial view from global options...
    miTableView = CreateCheckBoxMenuItem("Table", actHandler.ViewTableListener(), group, true);
    m.add(miTableView);

    miGraphView = CreateCheckBoxMenuItem("Graph", actHandler.ViewGraphListener(), group, false);
    m.add(miGraphView);
    return m;
    }

  //-----------------------------------------------------------------------
  private JMenuItem CreateMenuItem(String tag, ActionListener al)
    {
    JMenuItem mi = new JMenuItem(tag);
    mi.addActionListener(al);
    return mi;
    }

  //-----------------------------------------------------------------------
  private JCheckBoxMenuItem CreateCheckBoxMenuItem(String tag, ActionListener al, ButtonGroup group, boolean sel)
    {
    JCheckBoxMenuItem mi = new JCheckBoxMenuItem(tag);
    mi.addActionListener(al);
    group.add(mi);
    group.setSelected(mi.getModel(), sel);
    return mi;
    }
  }

MenuStates.java

Synopsis
package gui;

class MenuStates
  {
  private boolean isOpen;
  private boolean isGenned;
  private MenuHandler menu;
  private FsmView view;

  //-----------------------------------------------------------------------
  public MenuStates(FsmView v, MenuHandler m)
    {
    view = v;
    menu = m;
    }

  //-----------------------------------------------------------------------
  public boolean okToClose()
    {
    return isOpen;
    }

  //-----------------------------------------------------------------------
  public boolean okToModify()
    {
    return isOpen;
    }

  //-----------------------------------------------------------------------
  public boolean okToGen()
    {
    return isOpen && !isGenned;
    }

  //-----------------------------------------------------------------------
  public boolean okToSave()
    {
    return view.isDirty();
    }

  //-----------------------------------------------------------------------
  public boolean okToSaveAs()
    {
    return isOpen;
    }

  //-----------------------------------------------------------------------
  public void setGenned()
    {
    isGenned = true;
    menu.setEnabledStates();
    }

  //-----------------------------------------------------------------------
  public void resetOpen()
    {
    isOpen = false;
    menu.setEnabledStates();
    }

  //-----------------------------------------------------------------------
  public void setDirty()
    {
    isGenned = false;
    view.setDirty();
    menu.setEnabledStates();
    }

  //-----------------------------------------------------------------------
  public void setClean()
    {
    view.setClean();
    isOpen = true;
    isGenned = false;
    menu.setEnabledStates();
    }

  //-----------------------------------------------------------------------
  public void resetDirty()
    {
    view.setClean();
    menu.setEnabledStates();
    }

  //-----------------------------------------------------------------------
  public void resetAll()
    {
    view.setClean();
    isOpen = false;
    isGenned = false;
    menu.setEnabledStates();
    }
  }

Vector2D.java

Synopsis
/******************************************************************************************
ENME 489C: 	Java Project to develop an applet that will simulate a 2D Pool like game
	     	that can be played on the same computer by 2 players.

Vector2D.java: 	The Vector2D class includes protected variables for representing the
			x and y components. It also includes the various vector manipulation
			methods like dot product, rotateVector, scalar multiplication, addition,
			subtraction, etc. Vector2D is instantiated by position vector of balls,
			respective velocities and accelerations.

Creators:	Harishbabu Surendranath, Thomas Kurian, Ravi Raghavan
******************************************************************************************/
//Import packages
import java.lang.*;
import java.lang.Math;
import java.util.*;

public class Vector2D
{
	//Declare variables
	private double xComp,yComp;// Variables for x and y components of the vector

	//Empty constructor
	public Vector2D(){}

	//Constructor with two parameters viz. the x and y components of the vector
	public Vector2D(double x,double y)
	{
 	this.xComp=x;
 	this.yComp=y;
	}


	//Constructor with four parameters viz. two sets of x and y components
	public Vector2D(double x1,double y1,double x2,double y2)
	{
	 this.xComp=(x2-x1);
	 this.yComp=(y2-y1);
	}

	//Set the x and y components of the vector
	public void setVector(Vector2D vec)
	{
	 this.xComp=vec.xComp;
	 this.yComp=vec.yComp;
	}

	//Check if the two vectors are equal in magnitude and return result
	public boolean isEqual(Vector2D vec)
	{
 	 double TOL=0.00001;
  	 boolean equal=false;
  	 if(((this.xComp-vec.xComp)*(this.xComp-vec.xComp)+(this.yComp-vec.yComp)*(this.yComp-vec.yComp))<TOL)
	 equal=true;
  	 return(equal);
	}

	//Add two vectors
	public Vector2D add(Vector2D operand)
	{
 	 Vector2D result=new Vector2D();
 	 result.xComp=this.getxComp()+operand.getxComp();
 	 result.yComp=this.getyComp()+operand.getyComp();
 	 return result;
	}

	//Subtract two vectors
	public Vector2D subtract(Vector2D operand)
	{
	 Vector2D result=new Vector2D();
	 result.xComp=this.getxComp()-operand.getxComp();
 	 result.yComp=this.getyComp()-operand.getyComp();
 	 return result;
	}

	//Multiply two vectors
	public Vector2D multiply(double k)
	{
 	 Vector2D result=new Vector2D();
 	 result.xComp=this.getxComp()*k;
 	 result.yComp=this.getyComp()*k;
 	 return result;
	}

	//Get dot product of two vectors
	public double dotProduct(Vector2D operand)
	{
 	 double product;
 	 product=this.getxComp()*operand.getxComp()+this.getyComp()*operand.getyComp();
 	 return product;
	}

	//Get x component of the vector
	public double getxComp()
	{
	 return xComp;
	}

	//Set x component of the vector
	public void setxComp(double x)
	{
	 xComp=x;
	}

	//Get y component of the vector
	public double getyComp()
	{
	 return yComp;
	}

	//Set y component of the vector
	public void setyComp(double y)
	{
	 yComp=y;
	}

	//Rotate a vector by a given angle
	public Vector2D rotateVector(double theta)
	{
	 Vector2D result=new Vector2D();
	 result.xComp=this.getxComp()*Math.cos(theta*Math.PI/180)-this.getyComp()*Math.sin(theta*Math.PI/180);
	 result.yComp=this.getxComp()*Math.sin(theta*Math.PI/180)+this.getyComp()*Math.cos(theta*Math.PI/180);
	 return result;
	}

	//Get the normal vector
	public Vector2D getNormal()
	{
	 Vector2D result=new Vector2D();
	 result=this.rotateVector(90);
	 return result;
	}

	//Get the magnitude
	public double getMagnitude()
	{
	 return Math.sqrt(this.getxComp()*this.getxComp()+this.getyComp()*this.getyComp());
	}

	//Get the unit vector of the given vector
	public Vector2D unitVector()
	{
	 Vector2D result=new Vector2D();
	 result.xComp=this.getxComp()/this.getMagnitude();
	 result.yComp=this.getyComp()/this.getMagnitude();
	 return result;
	}


/*	//Get vector as string
	public String toString()
	{
	 return ("\t"+ xComp +"i" + "+" + yComp +"j");
	}*/

}//End of class Vector2D

FsmAction.java

Synopsis
package fsm;

//-------------------------------------------------------
class FsmAction
  {
  public String name;
  public String desc;
  public String code;

  private int m_count;

  //-------------------------------------------------------
  FsmAction()
    {
    m_count = 0;
    }

  //-------------------------------------------------------
  public boolean isDone()
    {
    return m_count == 3;
    }
  //-------------------------------------------------------
  public void setName(String n)
    {
    name = n;
    m_count++;
    }
  //-------------------------------------------------------
  public void setDesc(String d)
    {
    desc = d;
    m_count++;
    }
  //-------------------------------------------------------
  public void setCode(String c)
    {
    code = c;
    m_count++;
    }
  }

FsmActions.java

Synopsis
package fsm;

import java.util.Vector;
import java.io.BufferedWriter;
import java.io.IOException;

//-------------------------------------------------------
class FsmActions extends Vector
  {
  private FsmAction action;

  //-------------------------------------------------------
  String getActionName(int i)
    {
    return ((FsmAction) elementAt(i)).name;
    }

  //-------------------------------------------------------
  String getActionCode(int i)
    {
    return ((FsmAction) elementAt(i)).code;
    }

  //-------------------------------------------------------
  String getActionDesc(int i)
    {
    return ((FsmAction) elementAt(i)).desc;
    }
  //-------------------------------------------------------
  public FsmAction getAction(int i)
    {
    return (FsmAction) super.elementAt(i);
    }

  //-------------------------------------------------------
  void save(String key, String val)
    {
    if (action == null)
      action = new FsmAction();
    if (key.equals("name"))
      action.setName(val);
    else if (key.equals("desc"))
      action.setDesc(val);
    else if (key.equals("cppcode"))
      action.setCode(val);
    if (action.isDone())
      {
      addElement((Object) action);
      action = null;
      }
    }

  //-------------------------------------------------------
  void prepare()
    {}

  //-------------------------------------------------------
  void dump()
    {
    for (int i = 0; i < size(); ++i)
      {
      System.out.println("   actions[" + i + "].name  : " + getActionName(i));
      System.out.println("   actions[" + i + "].desc  : " + getActionDesc(i));
      System.out.println("   actions[" + i + "].code  : '" + getActionCode(i) + "'");
      System.out.println("");
      }
    }

  //-------------------------------------------------------
  void savexml(BufferedWriter w) throws IOException
    {
    for (int i = 0; i < size(); ++i)
      {
      w.write("<action>");
      w.newLine();
      w.write("  <name>" + getActionName(i) + "</name>"); w.newLine();
      w.write("  <desc>" + getActionDesc(i) + "</desc>"); w.newLine();
      w.write("  <cppcode><![CDATA[" + getActionCode(i) + "]]></cppcode>"); w.newLine();
      w.write("</action>"); w.newLine();
      w.newLine();
      }
    }
  }

FsmGenerator.java

Synopsis
package fsm;

import java.io.*;
import java.io.OutputStreamWriter;
import java.lang.Character;

//-------------------------------------------------------
class FsmGenerator
  {
  private FsmParameters fp;

  //-------------------------------------------------------
  public FsmGenerator(FsmParameters fsmparms)
    {
    fp = fsmparms;
    }

  //-------------------------------------------------------
  public void generate()
    {
    genAFile("fsm.cpp.cpp.tpl", "testcurr\\fsm.cpp");
    genAFile("fsm.h.cpp.tpl", "testcurr\\fsm.h");
    }

  //-------------------------------------------------------
  private void genAFile(String template, String gennedfile)
    {
    try
      {
      GennedFile w = new GennedFile(gennedfile, fp);
      TemplateFile r = new TemplateFile(template);
      for (r.read(); !r.eof(); r.read())
        r.handle(w);

      r.close();
      w.close();
      }
    catch (IOException ioexcp)
      {
      System.out.println("generate: excp thrown: " + ioexcp.getMessage());
      ioexcp.printStackTrace();
      }
    }
  }

FsmModel.java

Synopsis
package fsm;

//----------------------------------------------
public class FsmModel
  {
  private FsmParameters fp;

  //----------------------------------------------
  public FsmModel()
    {
    clear();
    }

  //----------------------------------------------
  public int getRowCount()
    {
    return fp.transitions.size();
    }

  //----------------------------------------------
  public Object getValueAt(int row, int col)
    {
    switch (col)
      {
      case 0:
        return fp.transitions.getTransState(row);
      case 1:
        return fp.transitions.getTransStimulus(row);
      case 2:
        return fp.transitions.getTransAction(row);
      case 3:
        return fp.transitions.getTransNextState(row);
      default:
        System.out.println("getValueAt: unknown value for col: " + col);
        System.exit(1);
      }
    return "";

    }

  //----------------------------------------------
  public void close()
    {
    clear();
    System.out.println("You chose to close this file: " + fp.currFileName);
    }

  //----------------------------------------------
  public void load(String fname)
    {
    clear();
    fp.currFileName = fname;
    System.out.println("You chose to open/load this file: " + fp.currFileName);
    XmlFile xmlf = new XmlFile();
    xmlf.load(fp);

    //System.out.println("fsmgen: analyizing...");
    if (!fp.prepare())
      {
      System.out.println("bad xml file: terminating");
      System.exit(1);
      }
    }

  //----------------------------------------------
  public void edit()
    {
    System.out.println("You chose to edit this file: " + fp.currFileName);
    }

  //----------------------------------------------
  public void gen()
    {
    System.out.println("gen the current file: " + fp.currFileName);
    FsmGenerator fg = new FsmGenerator(fp);
    fg.generate();
    }

  //----------------------------------------------
  public void save()
    {
    System.out.println("You chose to Save the current file: " + fp.currFileName);

    XmlFile xmlf = new XmlFile();
    xmlf.save(fp);
    }

  //----------------------------------------------
  public void saveAs(String newfname)
    {
    fp.currFileName = newfname;
    System.out.println("You chose to SaveAs this file: " + fp.currFileName);
    save();
    }

  //----------------------------------------------
  public void dump()
    {
    System.out.println("fsmgen: ---------------");
    fp.dump();
    System.out.println("fsmgen: ---------------");
    }

  //----------------------------------------------
  private void clear()
    {
    fp = new FsmParameters();
    fp.currFileName = null;
    }
  }

FsmOptions.java

Synopsis
package fsm;

import java.io.BufferedWriter;
import java.io.IOException;

//-------------------------------------------------------
class FsmOptions
  {
  public String startstate;
  public String init;
  public String outdir;
  public String outlang;

  //-------------------------------------------------------
  public FsmOptions()
    {
    // nothing to do.
    }

  //-------------------------------------------------------
  public void save(String key, String val)
    {
    if (key.equals("start"))
      startstate = val;
    else if (key.equals("init"))
      init = val;
    else if (key.equals("outdir"))
      outdir = val;
    else if (key.equals("outlang"))
      outlang = val;
    //else
    //  System.out.println("FsmOptions.save(): error unknown key: '" + key + "'");
    //jaa: todo
    }

  //-------------------------------------------------------
  public void prepare()
  {}

  //-------------------------------------------------------
  public String analyse()
    {
    if (startstate == null ||
        init == null ||
        outdir == null ||
        outlang == null)
      return "missing Options values";

    return null;
    }

  //-------------------------------------------------------
  public void dump()
    {
    System.out.println("  options.startstate: " + startstate);
    System.out.println("  options.init      : " + init);
    System.out.println("  options.outdir    : " + outdir);
    System.out.println("  options.outlang   : " + outlang);
    System.out.println("");
    }

  //-------------------------------------------------------
  void savexml(BufferedWriter w) throws IOException
    {
    w.write("<options>");
    w.newLine();
    w.write("  <start>" + startstate + "</start>"); w.newLine();
    w.write("  <init>" + init + "</init>"); w.newLine();
    w.write("  <outdir>" + outdir + "</outdir>"); w.newLine();
    w.write("  <outlang>" + outlang + "</outlang>"); w.newLine();
    w.write("</options>"); w.newLine();
    w.newLine();
    }
  }

FsmParameters.java

Synopsis
package fsm;

import java.io.BufferedWriter;
import java.io.IOException;

//-------------------------------------------------------
class FsmParameters
  {
  public String currFileName;
  public FsmStates states;
  public FsmTransitions transitions;
  public FsmActions actions;
  public FsmStimulii stimulii;
  public FsmOptions options;

  //-------------------------------------------------------
  public FsmParameters()
    {
    states = new FsmStates();
    actions = new FsmActions();
    stimulii = new FsmStimulii();
    transitions = new FsmTransitions();
    options = new FsmOptions();
    }

  //-------------------------------------------------------
  public void save(String area, String key, String val)
    {
    //System.out.println("parse: area is: '" + area + "'");
    //System.out.println("parse: key  is: '" + key + "'");
    //System.out.println("parse: val  is: '" + val + "'");

    if (area.equals("options"))
      options.save(key, val);
    else if (area.equals("action"))
      actions.save(key, val);
    else if (area.equals("stim"))
      stimulii.save(key, val);
    else if (area.equals("state"))
      states.save(key, val);
    else if (area.equals("transition"))
      transitions.save(key, val);
    //    else
    //      System.out.println("Error: ParserFsmParameters.save(): unknown area: '" +area+ "'");
    //jaa: todo
    }

  //-------------------------------------------------------
  public boolean prepare()
    {
    transitions.prepare();
    stimulii.prepare();
    states.prepare();
    actions.prepare();
    options.prepare();

    if (options.analyse() != null)
      return false;

    CountTransitions();

    return true;
    }

  //-------------------------------------------------------
  private void CountTransitions()
    {
    //states.incInTransition(options.startstate);

    int numtrans = transitions.size();
    for (int i = 0; i < numtrans; ++i)
      {
      states.incOutTransition(transitions.getTransState(i));
      states.incInTransition(transitions.getTransNextState(i));
      }

    //states.dump();
    }

  //-------------------------------------------------------
  public void savexml(BufferedWriter w) throws IOException
    {
    options.savexml(w);
    actions.savexml(w);
    stimulii.savexml(w);
    states.savexml(w);
    transitions.savexml(w);
    }

  //-------------------------------------------------------
  public void dump()
    {
    options.dump();
    actions.dump();
    stimulii.dump();
    states.dump();
    transitions.dump();
    }
  }

FsmState.java

Synopsis
package fsm;

//-------------------------------------------------------
class FsmState
  {
  public String name;
  public String desc;
  public boolean isFinal;
  public int outTransitions;
  public int inTransitions;

  private int m_count;

  //-------------------------------------------------------
  FsmState()
    {
    m_count = 0;
    outTransitions = 0;
    inTransitions = 0;
    }

  //-------------------------------------------------------
  public boolean isDone()
    {
    return m_count == 3;
    }
  //-------------------------------------------------------
  public void setName(String n)
    {
    name = n;
    m_count++;
    }
  //-------------------------------------------------------
  public void setDesc(String d)
    {
    desc = d;
    m_count++;
    }
  //-------------------------------------------------------
  public void setFinal(String f)
    {
    if (f.equals("true"))
      isFinal = true;
    else if (f.equals("false"))
      isFinal = false;
    else
      System.out.println("Error: FsmState: setFinal: string is not true or false: '" + f + "'");
    //jaa: todo
    m_count++;
    }
  }

FsmStates.java

Synopsis
package fsm;

import java.util.Vector;
import java.io.BufferedWriter;
import java.io.IOException;

//-------------------------------------------------------
class FsmStates extends Vector
  {
  private FsmState state;

  //-------------------------------------------------------
  String getStateName(int i)
    {
    return ((FsmState) elementAt(i)).name;
    }

  //-------------------------------------------------------
  String getStateFinal(int i)
    {
    if (((FsmState) elementAt(i)).isFinal)
      return "true";
    else
      return "false";
    }

  //-------------------------------------------------------
  String getStateDesc(int i)
    {
    return ((FsmState) elementAt(i)).desc;
    }

  //-------------------------------------------------------
  public FsmState getState(int i)
    {
    return (FsmState) super.elementAt(i);
    }

  //-------------------------------------------------------
  void save(String key, String val)
    {
    if (state == null)
      state = new FsmState();
    if (key.equals("name"))
      state.setName(val);
    else if (key.equals("desc"))
      state.setDesc(val);
    else if (key.equals("final"))
      state.setFinal(val);
    if (state.isDone())
      {
      add((Object) state);
      state = null;
      }
    }

  //-------------------------------------------------------
  void prepare()
    {}

  //-------------------------------------------------------
  int getOutTransitions(String state)
    {
    for (int i = 0; i < size(); ++i)
      {
      if (state.equals(getStateName(i)))
        return ((FsmState)elementAt(i)).outTransitions;
      }
    return 0;
    }

  //-------------------------------------------------------
  void incOutTransition(String state)
    {
    for (int i = 0; i < size(); ++i)
      {
      if (state.equals(getStateName(i)))
        {
        ((FsmState)elementAt(i)).outTransitions++;
        break;
        }
      }
    }

  //-------------------------------------------------------
  void incInTransition(String state)
    {
    for (int i = 0; i < size(); ++i)
      {
      if (state.equals(getStateName(i)))
        {
        ((FsmState)elementAt(i)).inTransitions++;
        break;
        }
      }
    }

  //-------------------------------------------------------
  void dump()
    {
    for (int i = 0; i < size(); ++i)
      {
      System.out.println("     states[" + i + "].name  : " + getStateName(i));
      System.out.println("     states[" + i + "].desc  : " + getStateDesc(i));
      System.out.println("     states[" + i + "].final : " + getStateFinal(i));
      System.out.println("     states[" + i + "].inTransitions  : " + ((FsmState)elementAt(i)).inTransitions);
      System.out.println("     states[" + i + "].outTransitions : " + ((FsmState)elementAt(i)).outTransitions);
      System.out.println("");
      }
    }

  //-------------------------------------------------------
  void savexml(BufferedWriter w) throws IOException
    {
    for (int i = 0; i < size(); ++i)
      {
      w.write("<state>");
      w.newLine();
      w.write("  <name>" + getStateName(i) + "</name>"); w.newLine();
      w.write("  <desc>" + getStateDesc(i) + "</desc>"); w.newLine();
      w.write("  <final>" + getStateFinal(i) + "</final>"); w.newLine();
      w.write("</state>"); w.newLine();
      w.newLine();
      }
    }
  }

FsmStimulii.java

Synopsis
package fsm;

import java.util.Vector;
import java.io.BufferedWriter;
import java.io.IOException;

//-------------------------------------------------------
class FsmStimulii extends Vector
  {
  private FsmStimulus stim;

  //-------------------------------------------------------
  String getStimulusName(int i)
    {
    return ((FsmStimulus) elementAt(i)).name;
    }

  //-------------------------------------------------------
  String getStimulusDesc(int i)
    {
    return ((FsmStimulus) elementAt(i)).desc;
    }

  //-------------------------------------------------------
  String getStimulusCode(int i)
    {
    return ((FsmStimulus) elementAt(i)).code;
    }

  //-------------------------------------------------------
  public FsmStimulus getStimulus(int i)
    {
    return (FsmStimulus) super.elementAt(i);
    }

  //-------------------------------------------------------
  void save(String key, String val)
    {
    if (stim == null)
      stim = new FsmStimulus();
    if (key.equals("name"))
      stim.setName(val);
    else if (key.equals("desc"))
      stim.setDesc(val);
    else if (key.equals("cppcode"))
      stim.setCode(val);
    if (stim.isDone())
      {
      addElement((Object) stim);
      stim = null;
      }
    }

  //-------------------------------------------------------
  void prepare()
    {}

  //-------------------------------------------------------
  void dump()
    {
    int i;
    for (i = 0; i < size(); ++i)
      {
      System.out.println("  stimulii[" + i + "].name  : " + getStimulusName(i));
      System.out.println("  stimulii[" + i + "].desc  : " + getStimulusDesc(i));
      System.out.println("  stimulii[" + i + "].code  : '" + getStimulusCode(i) + "'");
      System.out.println("");
      }
    }

  //-------------------------------------------------------
  void savexml(BufferedWriter w) throws IOException
    {
    for (int i = 0; i < size(); ++i)
      {
      w.write("<stim>");
      w.newLine();
      w.write("  <name>" + getStimulusName(i) + "</name>"); w.newLine();
      w.write("  <desc>" + getStimulusDesc(i) + "</desc>"); w.newLine();
      w.write("  <cppcode><![CDATA[" + getStimulusCode(i) + "]]></cppcode>"); w.newLine();
      w.write("</stim>"); w.newLine();
      w.newLine();
      }
    }

  }

FsmStimulus.java

Synopsis
package fsm;

//-------------------------------------------------------
class FsmStimulus
  {
  public String name;
  public String desc;
  public String code;

  private int m_count;

  //-------------------------------------------------------
  FsmStimulus()
    {
    m_count = 0;
    }

  //-------------------------------------------------------
  public boolean isDone()
    {
    return m_count == 3;
    }
  //-------------------------------------------------------
  public void setName(String n)
    {
    name = n;
    m_count++;
    }
  //-------------------------------------------------------
  public void setDesc(String d)
    {
    desc = d;
    m_count++;
    }
  //-------------------------------------------------------
  public void setCode(String c)
    {
    code = c;
    m_count++;
    }
  }

FsmTransition.java

Synopsis
package fsm;

//-------------------------------------------------------
class FsmTransition implements Comparable
  {
  public String state;
  public String stim;
  public String action;
  public String next;

  private int m_count;

  //-------------------------------------------------------
  FsmTransition()
    {
    m_count = 0;
    }

  //-------------------------------------------------------
  public int compareTo(Object o)
    {
    //assume o is of Type FsmTransition
    return state.compareTo(((FsmTransition)o).state);
    }

  //-------------------------------------------------------
  public boolean isDone()
    {
    return m_count == 4;
    }
  //-------------------------------------------------------
  public void setState(String s)
    {
    state = s;
    m_count++;
    }
  //-------------------------------------------------------
  public void setStimulus(String s)
    {
    stim = s;
    m_count++;
    }
  //-------------------------------------------------------
  public void setAction(String a)
    {
    action = a;
    m_count++;
    }
  //-------------------------------------------------------
  public void setNextState(String s)
    {
    next = s;
    m_count++;
    }
  }

FsmTransitions.java

Synopsis
package fsm;

import java.util.Collections;
import java.util.ArrayList;
import java.io.BufferedWriter;
import java.io.IOException;

//-------------------------------------------------------
class FsmTransitions extends ArrayList
  {
  private FsmTransition trans;

  //-------------------------------------------------------
  String getTransState(int i)
    {
    return ((FsmTransition) get(i)).state;
    }

  //-------------------------------------------------------
  String getTransStimulus(int i)
    {
    return ((FsmTransition) get(i)).stim;
    }

  //-------------------------------------------------------
  String getTransAction(int i)
    {
    return ((FsmTransition) get(i)).action;
    }

  //-------------------------------------------------------
  String getTransNextState(int i)
    {
    return ((FsmTransition) get(i)).next;
    }

  //-------------------------------------------------------
  FsmTransition getTrans(int i)
    {
    return (FsmTransition) get(i);
    }

  //-------------------------------------------------------
  void save(String key, String val)
    {
    if (trans == null)
      trans = new FsmTransition();
    if (key.equals("state"))
      trans.setState(val);
    else if (key.equals("stim"))
      trans.setStimulus(val);
    else if (key.equals("action"))
      trans.setAction(val);
    else if (key.equals("next"))
      trans.setNextState(val);
    if (trans.isDone())
      {
      add((Object) trans);
      trans = null;
      }
    }

  //-------------------------------------------------------
  void prepare()
    {
    Collections.sort(this);
    }

  //-------------------------------------------------------
  void dump()
    {
    int i;
    for (i = 0; i < size(); ++i)
      {
      System.out.println("      trans[" + i + "].state : " + getTransState(i));
      System.out.println("      trans[" + i + "].stim  : " + getTransStimulus(i));
      System.out.println("      trans[" + i + "].action: " + getTransAction(i));
      System.out.println("      trans[" + i + "].next  : " + getTransNextState(i));
      System.out.println("");
      }
    }

  //-------------------------------------------------------
  void savexml(BufferedWriter w) throws IOException
    {
    for (int i = 0; i < size(); ++i)
      {
      w.write("<transition>");
      w.newLine();
      w.write("  <state>" + getTransState(i) + "</state>"); w.newLine();
      w.write("  <stim>" + getTransStimulus(i) + "</stim>"); w.newLine();
      w.write("  <action>" + getTransAction(i) + "</action>"); w.newLine();
      w.write("  <next>" + getTransNextState(i) + "</next>"); w.newLine();
      w.write("</transition>"); w.newLine();
      w.newLine();
      }
    }
  }

GennedFile.java

Synopsis
package fsm;

import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.BufferedWriter;

//-------------------------------------------------------
class GennedFile extends BufferedWriter
  {
  GenProcessor w;

  public GennedFile(String fn, FsmParameters fsmparms) throws IOException
    {
    super(new OutputStreamWriter(new FileOutputStream(new File(fn))));
    w = new GenProcessor(this, fsmparms);
    }

  //-------------------------------------------------------
  void writeTag(String tag, int delim) throws IOException
    {
    w.writeTag(tag, delim);
    }

  //-------------------------------------------------------
  void handle(String tag, int delim) throws IOException
    {
    w.handle(tag, delim);
    }
  }

GenProcessor.java

Synopsis
package fsm;

import java.io.Writer;
import java.io.IOException;

//-------------------------------------------------------
class GenProcessor
  {
  FsmParameters fp;
  Writer w;

  //-------------------------------------------------------
  public GenProcessor(Writer wt, FsmParameters fsmparms) throws IOException
    {
    w = wt;
    fp = fsmparms;
    }

  //-------------------------------------------------------
  void writeTag(String tag, int delim) throws IOException
    {
    w.write(delim);
    w.write(tag);
    w.write(delim);
    }

  //-------------------------------------------------------
  void handle(String tag, int delim) throws IOException
    {
    //jaa: these may not be appropriate for java gen

    //System.out.println("found tag: '" + tag + "'");
    if (tag.equals("FSM_FILENAME"))
      genFsmFilename();
    else if (tag.equals("ASSERT_HEADER"))
      genAssertHeader();
    else if (tag.equals("STIMULUSID_DECL"))
      genStimulusIdDeclarations();
    else if (tag.equals("STIMULUS_SWITCH"))
      genStimulusSwitch();
    else if (tag.equals("STIMULUS_FUNCS"))
      genStimulusFunctions();
    else if (tag.equals("ACTION_FUNCS"))
      genActionFunctions();
    else if (tag.equals("STATEID_DECL"))
      genStateIdDeclarations();
    else if (tag.equals("STATE_STARTSTATE"))
      genStartState();
    else if (tag.equals("STATE_TABLE"))
      genStateTable();
    else
      writeTag(tag, delim);
    }

  //-------------------------------------------------------
  private void newLine() throws IOException
    {
    w.write("\r\n");
    }

  //-------------------------------------------------------
  private void genFsmFilename() throws IOException
    {
    w.write(fp.currFileName);
    }

  //-------------------------------------------------------
  private void genAssertHeader() throws IOException
    {
    //jaa: check option re: genasserts
    w.write("#include <crtdbg.h>");
    }

  //-------------------------------------------------------
  private void genStimulusIdDeclarations() throws IOException
    {
    int numstim = fp.stimulii.size();

    for (int i = 0; i < numstim; ++i)
      {
      w.write("const StimId STIMID_" + fp.stimulii.getStimulusName(i) + "=" + i + ";");
      newLine();
      }
    w.write("const int NUM_STIMS = " + numstim + ";");
    }

  //-------------------------------------------------------
  private void genStimulusSwitch() throws IOException
    {
    int numstim = fp.stimulii.size();
    newLine();
    for (int i = 0; i < numstim; ++i)
      {
      String name = fp.stimulii.getStimulusName(i);
      w.write("        case STIMID_" + name + ": return is" + name + "(fp);");
      newLine();
      }
    w.write("        default:");
    newLine();
    //jaa: check genasserts option
    w.write("          _ASSERTE(0 && \"error: unmatched stimulus\");");
    newLine();
    w.write("          return STIMID_Other;"); //jaa??
    newLine();
    }

  //-------------------------------------------------------
  private void genStimulusFunctions() throws IOException
    {
    int numstim = fp.stimulii.size();
    newLine();
    for (int i = 0; i < numstim; ++i)
      {
      //jaa: check geninline option
      w.write("    inline bool is" + fp.stimulii.getStimulusName(i) + "(FsmParameters& fp)");
      newLine();
      w.write("      {");
      w.write(fp.stimulii.getStimulusCode(i));
      w.write("      }");
      newLine();
      }
    }

  //-------------------------------------------------------
  private void genActionFunctions() throws IOException
    {
    int numact = fp.actions.size();
    newLine();
    for (int i = 0; i < numact; ++i)
      {
      w.write("//-------------------------------");
      newLine();
      w.write("struct Action_" + fp.actions.getActionName(i) + "  : public Action\r\n");
      w.write("  {");
      newLine();
      //jaa: check geninline option
      w.write("  inline bool operator() (FsmParameters& fp)");
      newLine();
      w.write("    {");
      w.write(fp.actions.getActionCode(i));
      w.write("    }");
      newLine();
      w.write("  } ;");
      newLine();
      }
    }

  //-------------------------------------------------------
  private void genStateIdDeclarations() throws IOException
    {
    int numstates = fp.states.size();
    newLine();
    for (int i = 0; i < numstates; ++i)
      {
      w.write("const State STATE_" + fp.states.getStateName(i) + "=" + i + ";");
      newLine();
      }

    w.write("const int   NUM_STATES=" + numstates + ";");
    newLine();
    }

  //-------------------------------------------------------
  private void genStartState() throws IOException
    {
    w.write(fp.options.startstate);
    }

  //-------------------------------------------------------
  private void genStateTable() throws IOException
    {
    int numtrans = fp.transitions.size();
    newLine();

    String laststate = "";
    for (int i = 0; i < numtrans; ++i)
      {
      String state = fp.transitions.getTransState(i);
      if (!laststate.equals(state))
        {
        if (!laststate.equals(""))
          {
          w.write("      stateidx++;");
          newLine();
          newLine();
          }

        w.write("      CreateRow(" + fp.states.getOutTransitions(state) + ");");
        newLine();
        laststate = state;
        }

      w.write("      InsertRow(STIMID_" +
              fp.transitions.getTransStimulus(i)
              + ", new Action_" +
              fp.transitions.getTransAction(i)
              + ", STATE_" +
              fp.transitions.getTransNextState(i)
              + ");");
      newLine();
      }

    w.write("      stateidx++;");
    newLine();
    newLine();
    }
  }

TemplateFile.java

Synopsis
package fsm;

import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;

//-------------------------------------------------------
class TemplateFile
  {
  InputStreamReader isr;
  TemplateProcessor tp = new TemplateProcessor();
  int ch;

  //-------------------------------------------------------
  public TemplateFile(String fn) throws IOException
    {
    isr = new InputStreamReader(new FileInputStream(new File(fn)));
    }

  //-------------------------------------------------------
  public void read() throws IOException
    {
    ch = isr.read();
    }

  //-------------------------------------------------------
  public void close() throws IOException
    {
    isr.close();
    }

  //-------------------------------------------------------
  public boolean eof()
    {
    return ch == - 1;
    }

  //-------------------------------------------------------
  public void handle(GennedFile w) throws IOException
    {
    tp.handle(ch, w);
    }
  }

TemplateProcessor.java

Synopsis
package fsm;

import java.io.*;

//-------------------------------------------------------
class TemplateProcessor
  {
  private final int cDelimiter = '$';

  private final int sStart = 0;
  private final int sReadingStartDelimiter = 1;
  private final int sReadingTag = 2;
  private final int sReadingEndDelimiter = 3;

  private int state = sStart;
  private String tag = "";

  //-------------------------------------------------------
  public TemplateProcessor()
    {
    state = sStart;
    }

  //-------------------------------------------------------
  public int handle(int ch, GennedFile w) throws IOException
    {
    //tag has form :
    //  tag      ::=  <delim> <tagchars> <delim>
    //  tagchars ::= [a-zA-Z0-9_]
    //  delim    ::= a single char, not alphanumeric
    switch (state)
      {
      case sStart :
        if (ch == cDelimiter)
          {
          tag = "";
          state = sReadingTag;
          }
        else
          w.write(ch);
        break;

      case sReadingTag:
        if (ch == cDelimiter)
          {
          w.handle(tag, cDelimiter);
          state = sStart;
          }
        else if (Character.isLetterOrDigit((char)ch) || ch == '_')
          tag += (char) ch;
        else
          {
          w.writeTag(tag, cDelimiter);
          state = sStart;
          }
        break;

      default:
        System.out.println("error: unknown case: state=" + state + " ch='" + (char)ch + "'");
        break;
      }
    return state;
    }
  }

Token.java

Synopsis
package fsm;

//-------------------------------------------------------
//-- Holds a Lexer token
class Token
  {
  public static final int TUnknown = 0;
  public static final int TStartTag = 1;
  public static final int TEndTag = 2;
  public static final int TValue = 3;
  public static final int TCode = 4;
  public static final int TEof = 5;
  public int ttype;
  public String sval;

  //-----------------------------------------------------
  Token()
    {
    sval = new String("");
    }

  public boolean isEof()
    {
    return ttype == TEof;
    }

  public boolean isStartTag()
    {
    return ttype == TStartTag;
    }

  public boolean isEndTag()
    {
    return ttype == TEndTag;
    }

  public boolean isValue()
    {
    return ttype == TValue || ttype == TCode;
    }

  //-----------------------------------------------------
  public String toString()
    {
    switch (ttype)
      {
      case TUnknown :
        return "Token type=TUnknown  sval='" + sval + "'";
      case TStartTag:
        return "Token type=TStartTag sval='" + sval + "'";
      case TEndTag :
        return "Token type=TEndTag   sval='" + sval + "'";
      case TValue :
        return "Token type=TValue    sval='" + sval + "'";
      case TCode :
        return "Token type=TCode     sval='" + sval + "'";
      case TEof :
        return "Token type=TEof      sval='" + sval + "'";
      default:
        return "Token type=??" + ttype + " sval='" + sval + "'";
      }
    }
  }

XmlFile.java

Synopsis
package fsm;

import java.io.*;

//-----------------------------------------------------
class XmlFile
  {
  private File m_infile;

  //-----------------------------------------------------
  public XmlFile()
    {
    //nothing
    }

  //-----------------------------------------------------
  public void load(FsmParameters fp)
    {
    //jaa: todo System.out.println("loading " + fname + " ...");
    try
      {
      m_infile = new File(fp.currFileName);

      if (!m_infile.exists())
        {
        //jaa: todo System.out.println("file does not exist: " + fname);
        return ;
        }

      if (!m_infile.isFile())
        {
        //jaa: todo System.out.println("it is not a file: " + fname);
        return ;
        }

      PushbackReader r = new PushbackReader(new InputStreamReader(new FileInputStream(m_infile)));
      XmlParser xp = new XmlParser();
      xp.parse(r, fp);
      }
    catch (IOException ioex)
      {
      System.out.println("load threw an exception..." + ioex.getMessage());
      //jaa: todo
      }
    }

  //-----------------------------------------------------
  public void save(FsmParameters fp)
    {
    System.out.println("saving " + fp.currFileName + " ...");  //jaa: todo
    try
      {
      m_infile = new File(fp.currFileName);

      // if (!m_infile.isFile())
      //   {
      //   //jaa: todo System.out.println("it is not a file: " + fname);
      //   return ;
      //   }

      //jaa: ok to overwrite?

      BufferedWriter r = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(m_infile)));
      XmlWriter xw = new XmlWriter();
      xw.save(r, fp);
      }
    catch (IOException ioex)
      {
      System.out.println("save threw an exception..." + ioex.getMessage());
      //jaa: todo
      }
    }
  }



XmlLexer.java

Synopsis
package fsm;

import java.io.IOException;
import java.io.PushbackReader;

//-----------------------------------------------------
class XmlLexer
  {
  private LexerFsmParameters fp;
  private LexerActions act;
  private LexerStimulii stim;

  private final int sStart = 0;
  private final int sReadingVal = 1;
  private final int sReadingTag = 2;
  private final int sReadingXmlDirective = 3;
  private final int sFinal = 4;

  //-----------------------------------------------------
  XmlLexer(PushbackReader r)
    {
    fp = new LexerFsmParameters(r);
    act = new LexerActions(fp);
    stim = new LexerStimulii(fp);
    }

  //-----------------------------------------------------
  Token nextToken() throws IOException
    {
    int state = sStart;

    fp.init();
    fp.load();

    if (stim.isEof())
      {
      act.OnEof();
      state = sFinal;
      }

    while (state != sFinal)
      {
      switch (state)
        {
        case sStart:
          if (stim.isEof())
            {
            act.OnEof();
            state = sFinal;
            }
          else if (stim.isNewLine())
            {
            act.DoNothing();
            state = sStart;
            }
          else if (stim.isWhiteSpace())
            {
            act.SaveChar();
            state = sStart;
            }
          else if (stim.isStartOfTag())
            {
            act.InitForStartTag();
            state = sReadingTag;
            }
          else if (stim.isOther())
            {
            act.InitForValue();
            state = sReadingVal;
            }
          else
            act.OnError();
          break;

        case sReadingTag:
          if (stim.isEof())
            {
            act.OnError();
            state = sFinal;
            }
          else if (stim.isEndTag())
            {
            act.InitForEndTag();
            state = sReadingTag;
            }
          else if (stim.isXmlDirective())
            {
            act.SaveChar();
            state = sReadingXmlDirective;
            }
          else if (stim.isEndOfTag())
            {
            act.DoNothing();
            state = sFinal;
            }
          else if (stim.isOther())
            {
            act.SaveChar();
            state = sReadingTag;
            }
          else
            act.OnError();
          break;

        case sReadingVal:
          if (stim.isEof())
            {
            act.DoNothing();
            state = sFinal;
            }
          else if (stim.isStartOfTag())
            {
            act.OnEndOfValue();
            state = sFinal;
            }
          else if (stim.isNewLine())
            {
            act.DoNothing();
            state = sReadingVal;
            }
          else if (stim.isOther())
            {
            act.SaveChar();
            state = sReadingVal;
            }
          else
            act.OnError();
          break;

        case sReadingXmlDirective:
          if (stim.isEof())
            {
            act.OnError();
            state = sFinal;
            }
          else if (stim.isIgnoredXmlTag())
            {
            act.DoNothing();
            state = sStart;
            }
          else if (stim.isEndOfCode())
            {
            act.OnEndOfCode();
            state = sFinal;
            }
          else if (stim.isOther())
            {
            act.SaveChar();
            state = sReadingXmlDirective;
            }
          else
            act.OnError();
          break;

        default:
          act.OnError();
        }

      if (state != sFinal)
        fp.load();
      }

    Token tok = new Token();
    tok.ttype = fp.type;
    tok.sval = fp.val;
    return tok;
    }

  }

//-----------------------------------------------------
class LexerActions
  {
  public static final int cDoNothing = 0;
  public static final int cSaveChar = 1;
  public static final int cInitForStartTag = 2;
  public static final int cInitForEndTag = 3;
  public static final int cInitForValue = 4;
  public static final int cOnEof = 5;
  public static final int cOnEndOfValue = 6;
  public static final int cOnEndOfCode = 7;
  public static final int cOnError = 8;

  private LexerFsmParameters fp;

  //-----------------------------------------------------
  LexerActions(LexerFsmParameters fp_)
    {
    fp = fp_;
    }

  //-------------------------------------------------------
  void DoNothing()
    {}

  //-------------------------------------------------------
  void SaveChar()
    {
    fp.SaveChar();
    }

  //-----------------------------------------------------
  void InitForStartTag()
    {
    fp.val = new String("");
    fp.type = Token.TStartTag;
    }

  //-----------------------------------------------------
  void InitForEndTag()
    {
    fp.type = Token.TEndTag;
    fp.SaveChar();
    }

  //-------------------------------------------------------
  void InitForValue()
    {
    fp.SaveChar();
    fp.type = Token.TValue;
    }

  //-----------------------------------------------------
  void OnEof()
    {
    fp.type = Token.TEof;
    }

  //-----------------------------------------------------
  void OnEndOfValue() throws IOException
    {
    fp.unread();
    }

  //-----------------------------------------------------
  void OnEndOfCode()
    {
    fp.type = Token.TCode;
    fp.val = fp.val.substring(fp.cXMLDataPrefix.length(), fp.val.length() - fp.cXMLDataSuffix.length());
    }

  //-----------------------------------------------------
  void OnError()
    {
    System.out.println("FsmLexer:nextToken:error: unknown state");
    //jaa: todo
    System.exit(1);
    }
  }

//-----------------------------------------------------
class LexerStimulii
  {
  public static final int cisEof = 0;
  public static final int cisNewLine = 1;
  public static final int cisWhiteSpace = 2;
  public static final int cisStartOfTag = 3;
  public static final int cisEndOfTag = 4;
  public static final int cisEndTag = 5;
  public static final int cisXmlDirective = 6;
  public static final int cisIgnoredXmlTag = 7;
  public static final int cisEndOfCode = 8;
  public static final int cisOther = 9;

  private LexerFsmParameters fp;

  //-------------------------------------------------------
  LexerStimulii(LexerFsmParameters fp_)
    {
    fp = fp_;
    }

  //-----------------------------------------------------
  boolean isOther()
    {
    return true;
    }

  //-----------------------------------------------------
  boolean isEof()
    {
    return fp.isEof();
    }

  //-----------------------------------------------------
  boolean isNewLine()
    {
    return fp.ch == '\r' || fp.ch == '\n';
    }

  //-----------------------------------------------------
  boolean isWhiteSpace()
    {
    return fp.ch == ' ' || fp.ch == '\t';
    }

  //-----------------------------------------------------
  boolean isStartOfTag()
    {
    return fp.ch == '<';
    }

  //-----------------------------------------------------
  boolean isEndOfTag()
    {
    return fp.ch == '>';
    }

  //-----------------------------------------------------
  boolean isEndTag()
    {
    return fp.ch == '/';
    }

  //-----------------------------------------------------
  boolean isXmlDirective()
    {
    return fp.ch == '!' || fp.ch == '?';
    }

  //-----------------------------------------------------
  boolean isIgnoredXmlTag()
    {
    return isEndOfTag() && (fp.val.startsWith("?xml") || fp.val.startsWith("!--"));
    }

  //-----------------------------------------------------
  boolean isEndOfCode()
    {
    return isEndOfTag() && fp.val.startsWith(fp.cXMLDataPrefix);
    }
  }

//-----------------------------------------------------
class LexerFsmParameters
  {
  public final String cXMLDataPrefix = "![CDATA[";
  public final String cXMLDataSuffix = "]]";

  public int ch;
  public int type;
  public String val;
  private PushbackReader m_reader;

  //-------------------------------------------------------
  LexerFsmParameters(PushbackReader r)
    {
    m_reader = r;
    init();
    }

  //-------------------------------------------------------
  void init()
    {
    type = Token.TUnknown;
    val = new String("");
    }

  //-------------------------------------------------------
  void load() throws IOException
    {
    ch = m_reader.read();
    }

  //-------------------------------------------------------
  void unread() throws IOException
    {
    m_reader.unread(ch);
    }

  //-------------------------------------------------------
  boolean isEof()
    {
    return ch == - 1;
    }

  //-------------------------------------------------------
  void SaveChar()
    {
    val += (char) ch;
    }
  }

XmlParser.java

Synopsis
package fsm;

import java.io.*;
import java.io.PushbackReader;
import java.util.Stack;

class XmlParser
  {
  private final int sStart = 0;
  private final int sStartTagSeen = 1;
  private final int sValueSeen = 2;
  private final int sEndTagSeen = 3;
  private final int sEof = 4;
  private final int sError = 5;

  //-------------------------------------------------------
  XmlParser()
    {
    //empty
    }

  //-------------------------------------------------------
  public void parse(PushbackReader r, FsmParameters fsmparms)
    {
    XmlLexer lex = new XmlLexer(r);
    ParserFsmParameters fp = new ParserFsmParameters(fsmparms);
    ParserStimulii stim = new ParserStimulii(fp);
    ParserActions act = new ParserActions(fp);

    int state = sStart;

    while (state != sEof && state != sError)
      {
      try
        {
        fp.tok = lex.nextToken();
        }
      catch (IOException ioex)
        {
        System.out.println("parse: nextToken() threw an excp: " + ioex.getMessage());
        //jaa: todo
        return ;
        }

      //System.out.println("parse:  " + fp.tok.toString());
      switch (state)
        {
        case sStart:
          if (stim.isEof())
            {
            act.onEof();
            state = sEof;
            }
          else if (stim.isStartTag())
            {
            act.saveToken();
            state = sStartTagSeen;
            }
          else
            {
            act.onError();
            state = sError;
            }
          break;

        case sStartTagSeen:
          if (stim.isEof())
            {
            act.onEofMissingEndTag();
            state = sError;
            }
          else if (stim.isStartTag())
            {
            act.saveToken();
            state = sStartTagSeen;
            }
          else if (stim.isEndTag())
            {
            act.saveEmptyVal();
            state = sStart;
            }
          else if (stim.isValue())
            {
            act.saveLastValue();
            state = sValueSeen;
            }
          else
            {
            act.onError();
            state = sError;
            }
          break;

        case sValueSeen:
          if (stim.isEof())
            {
            act.onEofMissingEndTag();
            state = sError;
            }
          else if (stim.isEndTag())
            {
            act.saveValue();
            state = sEndTagSeen;
            }
          else
            {
            act.onError();
            state = sError;
            }
          break;

        case sEndTagSeen:
          if (stim.isEof())
            {
            act.onEof();
            state = sEof;
            }
          else if (stim.isStartTag())
            {
            act.saveToken();
            state = sStartTagSeen;
            }
          else if (stim.isEndTag())
            {
            act.pop();
            state = sEndTagSeen;
            }
          else
            {
            act.onError();
            state = sError;
            }
          break;
        }
      }

    //System.out.println("parse: done");
    //System.out.println("parse: -------------");
    //fp.dump();
    //System.out.println("parse: -------------");
    }
  }


//-------------------------------------------------------
class ParserActions
  {
  private ParserFsmParameters fp;

  private FsmStimulus stim;
  private FsmState state;
  private FsmTransition trans;

  ParserActions(ParserFsmParameters _fp)
    {
    fp = _fp;
    }

  public void onEof()
    {
    //System.out.println("parse:     eof.");
    }

  public void saveToken()
    {
    fp.push();
    }

  public void pop()
    {
    fp.pop();
    }

  public void saveEmptyVal()
    {
    //System.out.println("parse:   chain=" + fp.getChain());
    }

  public void saveValue()
    {
    fp.save();
    //System.out.println("parse:   chain=" + fp.getChain());
    }

  public void onError()
    {
    //System.out.println("parse: Error chain=" + fp.getChain());
    //jaa: todo
    }

  public void onEofMissingEndTag()
    {
    //System.out.println("parse:     eof. Missing end tag!");
    //jaa: todo
    }

  public void saveLastValue()
    {
    fp.saveLastValue();
    }

  }

//-------------------------------------------------------
class ParserStimulii
  {
  ParserFsmParameters fp;
  ParserStimulii(ParserFsmParameters _fp)
    {
    fp = _fp;
    }

  public boolean isEof()
    {
    return fp.tok.isEof();
    }

  public boolean isStartTag()
    {
    return fp.tok.isStartTag();
    }

  public boolean isEndTag()
    {
    return fp.tok.isEndTag();
    }

  public boolean isValue()
    {
    return fp.tok.isValue();
    }
  }

//-------------------------------------------------------
class ParserFsmParameters
  {
  public Token tok;
  private Stack stack;
  private String lastval;

  private FsmParameters fsmparms;

  ParserFsmParameters(FsmParameters fp)
    {
    stack = new Stack();
    lastval = "";
    fsmparms = fp;
    }

  public void save()
    {
    //System.out.println("parse: stack.size()=" + stack.size());

    String area = ((Token)stack.elementAt(1)).sval;
    String key = ((Token)stack.elementAt(2)).sval;
    stack.pop();
    //System.out.println("parse: area is: '" + area + "'");
    //System.out.println("parse: key  is: '" + key + "'");
    //System.out.println("parse: val  is: '" + lastval + "'");

    fsmparms.save(area, key, lastval);
    }

  public void dump()
    {
    fsmparms.dump();
    }

  public void push()
    {
    stack.push(tok);
    }

  public void pop()
    {
    stack.pop();
    }

  public String getChain()
    {
    String chain = "";
    for (int i = 0; i < stack.size() - 1; ++i)
      {
      if (i != 0)
        chain += ".";
      chain += ((Token)stack.elementAt(i)).sval;
      }

    if (!stack.empty())
      {
      Token lasttok = (Token) stack.pop();
      chain += "." + lasttok.sval;
      }
    if (lastval == null || lastval == "")
      chain += ": (empty element)";
    else
      chain += ": '" + lastval + "'";
    return chain;
    }

  void saveLastValue()
    {
    lastval = tok.sval;
    }
  }

XmlWriter.java

Synopsis
package fsm;

import java.io.*;

class XmlWriter
  {
  FsmParameters fp;
  XmlWriter()
    {}



  void save(BufferedWriter w, FsmParameters fsmparms) throws IOException
    {
    w.write("<?xml version=\"1.0\" standalone=\"yes\"?>");
    w.newLine();
    w.write("<!-- WARNING! Do not modify this file!"); w.newLine();
    w.write("     WARNING! This file is not XML."); w.newLine();
    w.write("     It looks like XML but if any other XML constructs are used,"); w.newLine();
    w.write("     fsmgen will fail!"); w.newLine();
    w.write("-->"); w.newLine();
    w.write("<?xml-stylesheet type=\"text/xsl\" href=\"jaa.xsl\" ?>"); w.newLine();
    w.newLine();
    w.write("<fsm>"); w.newLine();
    fsmparms.savexml(w);
    //write xml footer
    w.write("</fsm>"); w.newLine();
    w.close();
    }
  }

Globals.java

Synopsis
package common;

public class Globals
  {
  public static fsm.FsmModel model = new fsm.FsmModel();
  }

fsm.cpp.cpp.tpl

Synopsis
//DO NOT MODIFY!
//This file was generated by fsmgen from the following file:
// $FSM_FILENAME$
//

#include "fsm.h"
#include "FsmParameters.h"
$ASSERT_HEADER$

//-------------------------------
class Action;
typedef long StimId;
typedef long State;

//-------------------------------
$STIMULUSID_DECL$

//-------------------------------
class Stimulii
{
  public:
    inline bool isStimulus(StimId id, FsmParameters& fp)
      {
      switch(id)
        {
        $STIMULUS_SWITCH$
        }
      }

  private:
    $STIMULUS_FUNCS$
} ;

//-------------------------------
class Action
{
  public:
  virtual bool operator() (FsmParameters& fp) = 0;
} ;

$ACTION_FUNCS$

//-------------------------------
$STATEID_DECL$

//-------------------------------
class FsmRow
{
public:
  StimId  stim;
  Action* action;
  State   next;
};

//-------------------------------
class Fsm::Private
{
private:
    int stateidx;
    int rowidx;

public:
    FsmRow** table[NUM_STATES];
    State  state;

    //-------------------------------
    Private()
       : state($STATE_STARTSTATE$)
       {}

    //-------------------------------
    ~Private()
      {
      for(stateidx = 0; stateidx < NUM_STATES; ++stateidx)
        {
        for(int rowidx = 0; table[stateidx][rowidx] != 0; ++rowidx)
          {
          delete table[stateidx][rowidx]->action;
          delete table[stateidx][rowidx];
          }
        delete table[stateidx];
        }
      }

    //-------------------------------
    inline void CreateRow(int numrows)
      {
      table[stateidx] = new FsmRow*[numrows + 1];
      rowidx = 0;
      table[stateidx][rowidx] = 0;
      }

    //-------------------------------
    inline void InsertRow(StimId _st, Action* _act, State _ns)
      {
      table[stateidx][rowidx] = new FsmRow();
      table[stateidx][rowidx]->stim = _st;
      table[stateidx][rowidx]->action = _act;
      table[stateidx][rowidx]->next   = _ns;
      rowidx++;
      table[stateidx][rowidx] = 0;
      }

    //-------------------------------
    void init()
      {
      stateidx = 0;
      rowidx = 0;

      $STATE_TABLE$

      _ASSERTE(stateidx == NUM_STATES);
      }
} ;

//-------------------------------
Fsm::Fsm()
: m_impl(* new Fsm::Private)
  {
  m_impl.init();
  }

//-------------------------------
Fsm::~Fsm()
  {
  delete &m_impl;
  }

#define _rowiter   m_impl.table[m_impl.state][rowidx]
#define _stimid    _rowiter->stim
#define _action    _rowiter->action
#define _nextstate _rowiter->next

//-------------------------------
void Fsm::run(FsmParameters& fp)
  {
  Stimulii stim;
  StimId stimid;
  int rowidx;

  for(;;)
    {
    _ASSERTE(m_impl.state != STATE_FINAL);
    _ASSERTE((m_impl.state >= 0 && m_impl.state < NUM_STATES) && "the initial state or nextstate is invalid in the FSM");

    fp.load();

    for (rowidx = 0; _rowiter != 0; rowidx++)
      {
      if (stim.isStimulus(_stimid, fp))
        break;
      }
    _ASSERTE(_rowiter != 0 && "a stimulus id is not defined for the current state");
    _ASSERTE(_action != 0 && "an action is not defined for the current state/stimulus");

    // fprintf(stderr, "state=%-02ld stimid=%-02ld act=%p next=%ld eof=%c ch=%c\n",
    //   (long) m_impl.state, (long)_stimid, _action, (long) _nextstate, fp.m_eof ? 'T' : 'F', fp.m_ch);

    (*_action)(fp);
    m_impl.state = _nextstate;

    if (m_impl.state == STATE_FINAL)
      return;
    }
  }


fsm.h.cpp.tpl

Synopsis
#pragma once

//DO NOT MODIFY!
//This file was generated by fsmgen from the following file:
// $FSM_FILENAME$
//

class FsmParameters;
class Fsm
  {
  public:
    Fsm();
    ~Fsm();
    void run(FsmParameters& fp);

  private:
    class Private;
    Private& m_impl;
  };






Contact me about content on this page using john_web-at-arrizza-dot-com
For Web Master or site problems contact: webadmin-at-arrizza-dot-com
Copyright John Arrizza (c) 2001-2010