1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
|
/*
* tcLex.h --
*
* This is the header file for the module that implements lexer for Tcl.
* This file defines the public interface of the tcLex module.
*
* Copyright (c) 1998 Frdric BONNET <frederic.bonnet@ciril.fr>
*
* See the file "license.txt" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#ifndef _TCLEX_H_
#define _TCLEX_H_
#include <tcl.h>
/*
* if the BUILD_tcLex macro is defined, the assumption is that we are
* building the dynamic library.
*/
#ifdef BUILD_tcLex
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLEXPORT
#endif
/*
*--------------------------------------------------------------
*
* Various stuff
*
*--------------------------------------------------------------
*/
#define EXPORT(a,b) a b
#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef WIN32_LEAN_AND_MEAN
# ifndef STATIC_BUILD
# if defined(__BORLANDC__)
# undef EXPORT
# define EXPORT(a,b) a _export b
# endif
# endif
#endif /* WIN32 */
/*
*--------------------------------------------------------------
*
* Structures
*
*--------------------------------------------------------------
*/
/*
* Lexer rules
*
* Each lexer is made by a collection of rules. Each rule is
* described by the TcLex_Rule structure.
*/
typedef struct TcLex_Rule {
/*
* Each rule is active only within one or several conditions.
* Here we store the indices of the valid conditions in the
* array <conditionsIndices> of length <conditionsIndicesLength>,
* w.r.t the lexer's TcLex_Lexer <inclusiveConditions> and
* <exclusiveConditions> arrays
*/
int *conditionsIndices;
int conditionsIndicesLength;
Tcl_Obj *reObj; /* Object containing the regexp */
Tcl_RegExp re; /* Regular expression of the rule */
Tcl_Obj *matchVars; /* List of match var names */
int nbRanges; /* Max number of ranges in the regexp, approximately */
/* equal to the number of parentheses pairs */
Tcl_Obj *script; /* Script eval'd when the rule is matched */
} TcLex_Rule;
/*
* Lexer buffers
*
* Buffers are used to handle input: Tcl strings, files, channels...
*/
#if (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0)
typedef char Char;
#else
typedef Tcl_UniChar Char;
#endif
typedef struct TcLex_Buffer {
Tcl_DString chars;
int index; /* Current byte position within <chars> */
int nextIndex;
int bMatchedEmpty; /* Set when we match an empty string
* (such as an empty line). To avoid
* endless loops we can't match two
* consecutive empty strings */
} TcLex_Buffer;
/*
* Lexer states
*
* When a lexer is active, its state is described using the
* TcLex_State structure. It is used when the same lexer is
* called recursively or in parallel (eg. incrementally)
*/
typedef struct TcLex_State {
/*
* The lexer's condition can change during its execution. We
* need to store these conditions in a stack
*/
int *conditionsStack; /* Array used to store conditions,
* current condition is the last
* element */
int conditionsStackLength; /* Length of the above stack */
char *bFailed; /* Rule failure indicators. We need to
* store it for incremental processing
* to work properly */
Tcl_HashTable *varTablePtr; /* Used to store the lexer's local
* variables for continuation,
* eg. for incremental evaluation */
TcLex_Buffer inputBuffer; /* Buffer from which to take input */
TcLex_Buffer *currentBuffer;
int bRejected; /* Used when the rule is rejected, using
* the "reject" subcommand */
int nbRanges; /* Number of matches ranges/subranges */
int *startIndices; /* When a rule matches, used to store */
int *endIndices; /* the matching strings' indices */
Tcl_Obj *pendingResult; /* Used when the lexer returns a
* result before reaching the end of
* the string */
} TcLex_State;
/*
* Lexer
*/
#define LEXER_FLAG_LINES 1
#define LEXER_FLAG_NOCASE 2
#define LEXER_FLAG_LONGEST 4
typedef struct TcLex_Lexer {
Tcl_Command command; /* Token to the created Tcl command, used
* with [lexer current] */
/*
* There are 2 types of conditions: inclusive, and exclusive.
* We store both types in the <conditions> array. Inclusive
* conditions are stored in the first <nbInclusiveConditions>
* elements, and the remaining <nbExclusiveConditions> elements
* are used to store exclusive conditions. We also pre-process
* the active rules for each condition in the <activeRules> array
* for optimization; that way we don't have to search for active
* rules at every match, we just look into the <activeRules> array.
*/
Tcl_Obj **conditions;
int **activeRules;
int nbInclusiveConditions, nbExclusiveConditions;
int flags; /* OR-ed values of LEXER_FLAG_????? */
/*
* The scripts <preScript> and <postScript> are evaluated
* resp. before and after the string lexing. <preScript> is
* mainly used for initialization, and <postScript> for
* returning a result.
* The script <midScript> is only evaluated during an incremental
* lexing, at the end of each intermediary lexing, ie calls to
* "start" or "continue". A call to "finish" return the result
* of <postScript>.
* If none of these scripts return a value, the content of
* the variable named <resultVariable> is returned, if any
*/
Tcl_Obj *preScript, *midScript, *postScript;
Tcl_Obj *args;
Tcl_Obj *resultVariable;
TcLex_Rule *rules; /* Array used to store the lexer's rules */
int nbRules; /* Number of rules, ie length of the
* above array */
/*
* Since one lexer can have several active instances at a time,
* we need to store their states, in the <states> array
*/
TcLex_State **states;
int nbStates; /* Length of the above array */
int curState; /* Index of the current state in the array */
} TcLex_Lexer;
/*
*--------------------------------------------------------------
*
* Functions
*
*--------------------------------------------------------------
*/
/*
* The main entry point
*/
EXTERN EXPORT(int,Tclex_Init) _ANSI_ARGS_((Tcl_Interp *interp));
EXTERN EXPORT(int,Tclex_SafeInit) _ANSI_ARGS_((Tcl_Interp *interp));
/*
* Lexer Tcl command
*/
int LexerObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
/*
* Lexer management functions
*/
void LexerDelete _ANSI_ARGS_((TcLex_Lexer *lexer));
TcLex_Lexer * LexerNew _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *inclusiveConditions, Tcl_Obj *exclusiveConditions,
Tcl_Obj *resultVariable,
Tcl_Obj *preScript, Tcl_Obj *midScript, Tcl_Obj *postScript,
Tcl_Obj *args, int flags,
int rulec, Tcl_Obj *CONST *rulev));
void LexerCmdDeleteProc _ANSI_ARGS_((ClientData clientData));
int LexerMainObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
int LexerCreateObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[], int start));
int LexerCurrentObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
/*
* Conditions management functions
*/
int ConditionCurrent _ANSI_ARGS_((Tcl_Interp *interp, TcLex_Lexer *lexer));
/*
* Lexer evaluation functions
*/
/* LexerEval op's */
#define LEXER_EVAL 0
#define LEXER_START 1
#define LEXER_CONTINUE 2
#define LEXER_FINISH 3
int LexerEval _ANSI_ARGS_((Tcl_Interp *interp, TcLex_Lexer *lexer,
int bCheckOverrun));
int LexerEvalObjCmd _ANSI_ARGS_((Tcl_Interp *interp, TcLex_Lexer *lexer,
int objc, Tcl_Obj *CONST objv[], int op));
/*
* Lexer state functions
*/
int LexerBeginObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
int LexerEndObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
int LexerConditionsObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
int LexerRejectObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
int LexerIndexObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
int LexerInputObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
int LexerUnputObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]));
/*
* end of tcLex.h
* reset TCL_STORAGE_CLASS to DLLIMPORT.
*/
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLIMPORT
#endif /* _TCLEX_H_ */
|