See: Description
Interface | Description |
---|---|
ContextStackProvider |
is the interface to be implemented by an object put into
DfaRun.clientData when any of the actions in monq.jfa.ctx package are used in a Nfa . |
Class | Description |
---|---|
Context |
manages a context when running a
DfaRun . |
ContextManager |
populates a
Nfa with regex/action pairs
which keep track of nested matching contexts. |
IfContext |
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.
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.