/* 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 */