Skip navigation links
monq-2.0.0

Package monq.jfa.ctx

adds support for recursive parsing to jfa that in particular allows easy XML parsing as an alternative to SAX.

See: Description

Package monq.jfa.ctx Description

adds support for recursive parsing to jfa that in particular allows easy XML parsing as an alternative to SAX. The classes supplied do not rely on XML. Rather they provide a more general concept of which XML is a special case. The concept implemented is called a parsing context. It is defined by the stretch of text between matches of two regular expressions for the start and the end of the context. The classes in this package set up and maintain a stack of such parsing contexts. More importantly, they allow context specific action callbacks via IfContext.

Parsing contexts are set up by adding Context actions to a Nfa. While this could in principle be done directly with calls to Nfa.or(), it would be tedious and error prone. Instead, a ContextManager must be used to populate the Nfa. A typical call to a ContextManager looks like this:

  ContextManager cmgr = new ContextManager(nfa);
  Context ctx = cmgr.addXml("server")

This will add two actions to nfa that push/pop a context to/from a stack when matching an XML start/end tag with the name server. The context can then be used in combination with a conditional action:

  nfa.or(Xml.GoofedElement("hostname"), 
         new IfContext(ctx, new StoreHostname())

The IfContext action makes sure that StoreHostname is only called if the hostname XML element is found in the given context ctx. Additional contexts can be added with IfContext.ifthen() and IfContext.elsedo().

A context can be used as the parent of another context by calling addXml with the parent context as a parameter:

  Context child = cmgr.addXml(ctx, "propertyList")

This will wrap the push operation for the generated child context into an IfContext action to make sure it is only performed in the given parent context. The internally generated IfContext object is not available for direct manipulation, e.g. for adding an elsdo(), but it is safe to directly add an unconditional action to the nfa which will then serve as the default action. Similarly, it is ok to add an additional IfContext object for the same match but for a different context.

By default, the text matching the start and the end of a context is copied untouched to the output. This can be generally changed with ContextManager.setDefaultAction() and similar methods, as well as per context with Context.setStartAction() etc.

Where is the stack

During operation of the automaton with a DfaRun, the field DfaRun.clientData must contain an object which implements the ContextStackProvider interface. The Context actions use the List provided by this interface as a stack. Client actions added to a Context with e.g. Context.setStartAction() may also use the stack for their own business, as long as they perform paired push and pop operations.

For convenience, the method ContextManager.createStackProvider() returns a trivial implementation of a ContextStackProvider:

  DfaRun r = new DfaRun(dfa, ...);
  r.clientData = ContextManager.createStackProvider();

If, however, the clientData field has to carry your own information, the object you store in clientData need for example only contain an ArrayList and the method ContextStackProvider.getStack() which returns it.

Skip navigation links
monq-2.0.0