/* nfa.h - decls for manipulating regexps as NFAs
*
****************************************************************
* Copyright (C) 1998, 2000 Thomas Lord
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#ifndef INCLUDE__RX__NFA_H
#define INCLUDE__RX__NFA_H
struct rx_nfa;
struct rx_nfa_state;
struct rx_superset;
#include "hackerlab/hash/hashtree.h"
#include "hackerlab/bitsets/bits.h"
#include "hackerlab/rx/bits-tree-rules.h"
#include "hackerlab/rx/tree.h"
#include "hackerlab/rx/nfa-cache.h"
#include "hackerlab/rx/super.h"
/************************************************************************
*(h1 "The NFA Data Types")
*
*
*
*/
/*(c #s"struct rx_nfa" :category type)
*
* This structure type is used to hold a non-deterministic
* finite automata.
*
insert*/
struct rx_nfa
{
unsigned long rx_id;
/* Each NFA has a unique ID assigned by `rx_nfa_xalloc'. */
int local_cset_size;
/* Either 256 (8-bit ascii) or 1<<21 (Unicode). */
struct bits_tree_rule * bitset_rule;
struct rx_nfa_state * nfa_states;
/* The list of states in this NFA, linked by the field `next'.
This is filled in by `rx_nfa_state'. */
int nfa_state_id;
/* NFA states are assigned sequential ids. This is the id of the
next state.*/
struct rx_nfa_state * start_nfa_state;
/* The starting state of the NFA. This field must be filled in
by a call to `rx_set_start_state' once the start state has
been created. */
struct hashtree set_list_memo;
/* A hash table used to allocate NFA state sets with the property
that equal sets are `=='. */
};
/*end-insert
*/
/*(c #s"struct rx_nfa_state" :category type)
*
* This structure type holds one state of an NFA.
*
insert*/
struct rx_nfa_state
{
unsigned int id;
/* NFA states are assigned sequential ids.*/
long state_label;
/* Each state has a label. If the label is non-0, the state is a
final state. In the DFA, a superstate is given a state label
which is the smallest magnitude of the non-0 state labels of
the NFA states it contains. If all of the NFA states have a
state label 0, then so does the DFA state. */
struct rx_nfa_edge *edges;
/* A list of NFA edges originating in this state.
The edges are linked by the field `next'. */
t_uchar is_start;
/* Set to `1' by `rx_set_start_state' and is otherwise 0.*/
t_uchar has_cset_edges;
/* Set to `1' by `rx_nfa_edge' and is otherwise 0. This is used
during DFA matching to recognize dead-end states.*/
t_uchar closure_computed;
/* Set to `1' by `rx_state_closure' and is otherwise 0.*/
struct rx_nfa_state_set * closure;
/* This is set to the state's epsilon closure by
`rx_state_closure' and is otherwise 0.*/
struct rx_superset * superstate_set;
/* This field is set by `rx_nfa_state_to_superstate' to cache
the superstate set of the eclosure of this NFA state.
This field does not have a reference count to the set.
Instead, if the set is freed, this field is set to 0.
The superstate set points back to this state in the field
`nfa_state'. */
t_uchar mark;
/* This is used by various graph traversal algorithms. */
struct rx_nfa_state *next;
/* This link is to the next state of the same NFA in the list
of all states starting at `nfa->nfa_states'. */
};
/*end-insert
*/
/*(c #s"struct rx_nfa_edge" :other-terms "enum rx_nfa_etype" :category type)
* enum rx_nfa_etype;
* struct rx_nfa_edge;
*
* This structure type holds one edge of an NFA.
*
insert*/
/* enum rx_nfa_etype;
*
* There are two types of NFA edges: character sets and "epsilon". An
* epsilon edge represents a transition that can be taken immediately
* whenever the source state is reached. A character set transition
* can be taken only by matching character in the set.
*/
enum rx_nfa_etype
{
ne_cset,
ne_epsilon
};
/* struct rx_nfa_edge;
*
* One NFA edge.
*/
struct rx_nfa_edge
{
enum rx_nfa_etype type; /* Which type of edge? */
struct rx_nfa_state *dest; /* What is the destination state? */
bits cset;
/* If the edge is a character set edge (`ne_cset'),
this is the set of characters it matches. */
struct rx_nfa_edge *next;
/* Next edge for the same source node. */
};
/*end-insert
*/
/*(c #s"struct rx_nfa_state_set" :category type)
*
* This structure type holds a set of NFA states, represented as a
* list. It is used to represent the epsilon closure of an NFA node.
* Any two NFA sets with the same elements are equal in the sense of
* `==' if they were returned by `rx_state_closure'.
*
insert*/
struct rx_nfa_state_set
{
struct rx_nfa_state * car;
struct rx_nfa_state_set * cdr;
};
/*end-insert
*/
/************************************************************************
*(h1 "Shared NFA Data Structures")
*
*
* We have a structure type which represents a cached NFA:
*/
/*(c #s"struct rx_unfa" :category type)
* struct rx_unfa;
*
* This structure holds a regexp expression tree and an NFA for that
* expression. There is at most one of these structures for each
* expression.
*
insert*/
struct rx_unfa
{
int refs; /* A reference count. */
struct rx_exp_node * exp; /* A queue of regexps with the same NFA. */
struct rx_nfa * nfa; /* The NFA. */
};
/*end-insert
*/
/* automatically generated __STDC__ prototypes */
extern int rx_build_nfa (struct rx_nfa *rx,
struct rx_exp_node *rexp,
struct rx_nfa_state **start,
struct rx_nfa_state **end);
extern void rx__nfa_cache_statistics (size_t * threshold,
size_t * failure_pt,
size_t * in_use,
size_t * high_water_mark,
int * hits,
int * misses,
int * saves);
extern struct rx_unfa * rx_unfa (struct rx_exp_node * exp,
int cset_size);
extern void rx_save_unfa (struct rx_unfa * unfa);
extern void rx_free_unfa (struct rx_unfa * unfa);
extern int rx__really_free_unfa (void);
extern struct rx_nfa * rx_nfa_xalloc (int cset_size);
extern void rx_free_nfa (struct rx_nfa * rx);
extern struct rx_nfa_state * rx_nfa_state (struct rx_nfa *rx);
extern struct rx_nfa_edge * rx_nfa_edge (struct rx_nfa *rx,
enum rx_nfa_etype type,
struct rx_nfa_state *start,
struct rx_nfa_state *dest);
extern struct rx_nfa_edge * rx_nfa_cset_edge (struct rx_nfa *rx,
enum rx_nfa_etype type,
bits cset,
struct rx_nfa_state *start,
struct rx_nfa_state *dest);
extern void rx_set_start_state (struct rx_nfa * rx, struct rx_nfa_state * n);
extern void rx_set_state_label (struct rx_nfa * rx,
struct rx_nfa_state * n,
int label);
extern struct rx_nfa_state_set * rx_state_closure (struct rx_nfa * rx,
struct rx_nfa_state * n);
#endif /* INCLUDE__RX__NFA_H */
syntax highlighted by Code2HTML, v. 0.9.1