4 * This file contains procedures that parse Tcl expressions. They
5 * do so in a general-purpose fashion that can be used for many
6 * different purposes, including compilation, direct execution,
9 * Copyright (c) 1997 Sun Microsystems, Inc.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
18 #include "tclCompile.h"
21 * The stuff below is a bit of a hack so that this file can be used in
22 * environments that include no UNIX, i.e. no errno: just arrange to use
23 * the errno from tclExecute.c here.
26 #ifndef TCL_GENERIC_ONLY
33 extern int errno; /* Use errno from tclExecute.c. */
38 * Boolean variable that controls whether expression parse tracing
42 #ifdef TCL_COMPILE_DEBUG
43 static int traceParseExpr = 0;
44 #endif /* TCL_COMPILE_DEBUG */
47 * The ParseInfo structure holds state while parsing an expression.
48 * A pointer to an ParseInfo record is passed among the routines in
52 typedef struct ParseInfo {
53 Tcl_Parse *parsePtr; /* Points to structure to fill in with
54 * information about the expression. */
55 int lexeme; /* Type of last lexeme scanned in expr.
56 * See below for definitions. Corresponds to
57 * size characters beginning at start. */
58 char *start; /* First character in lexeme. */
59 int size; /* Number of bytes in lexeme. */
60 char *next; /* Position of the next character to be
61 * scanned in the expression string. */
62 char *prevEnd; /* Points to the character just after the
63 * last one in the previous lexeme. Used to
64 * compute size of subexpression tokens. */
65 char *originalExpr; /* Points to the start of the expression
66 * originally passed to Tcl_ParseExpr. */
67 char *lastChar; /* Points just after last byte of expr. */
71 * Definitions of the different lexemes that appear in expressions. The
72 * order of these must match the corresponding entries in the
73 * operatorStrings array below.
78 #define OPEN_BRACKET 2
98 #define RIGHT_SHIFT 17
114 * Unary operators. Unary minus and plus are represented by the (binary)
115 * lexemes MINUS and PLUS.
122 * Mapping from lexemes to strings; used for debugging messages. These
123 * entries must match the order and number of the lexeme definitions above.
126 #ifdef TCL_COMPILE_DEBUG
127 static char *lexemeStrings[] = {
128 "LITERAL", "FUNCNAME",
129 "[", "{", "(", ")", "$", "\"", ",", "END", "UNKNOWN",
130 "*", "/", "%", "+", "-",
131 "<<", ">>", "<", ">", "<=", ">=", "==", "!=",
132 "&", "^", "|", "&&", "||", "?", ":",
135 #endif /* TCL_COMPILE_DEBUG */
138 * Declarations for local procedures to this file:
141 static int GetLexeme _ANSI_ARGS_((ParseInfo *infoPtr));
142 static void LogSyntaxError _ANSI_ARGS_((ParseInfo *infoPtr));
143 static int ParseAddExpr _ANSI_ARGS_((ParseInfo *infoPtr));
144 static int ParseBitAndExpr _ANSI_ARGS_((ParseInfo *infoPtr));
145 static int ParseBitOrExpr _ANSI_ARGS_((ParseInfo *infoPtr));
146 static int ParseBitXorExpr _ANSI_ARGS_((ParseInfo *infoPtr));
147 static int ParseCondExpr _ANSI_ARGS_((ParseInfo *infoPtr));
148 static int ParseEqualityExpr _ANSI_ARGS_((ParseInfo *infoPtr));
149 static int ParseLandExpr _ANSI_ARGS_((ParseInfo *infoPtr));
150 static int ParseLorExpr _ANSI_ARGS_((ParseInfo *infoPtr));
151 static int ParseMultiplyExpr _ANSI_ARGS_((ParseInfo *infoPtr));
152 static int ParsePrimaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
153 static int ParseRelationalExpr _ANSI_ARGS_((ParseInfo *infoPtr));
154 static int ParseShiftExpr _ANSI_ARGS_((ParseInfo *infoPtr));
155 static int ParseUnaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
156 static void PrependSubExprTokens _ANSI_ARGS_((char *op,
157 int opBytes, char *src, int srcBytes,
158 int firstIndex, ParseInfo *infoPtr));
161 * Macro used to debug the execution of the recursive descent parser used
162 * to parse expressions.
165 #ifdef TCL_COMPILE_DEBUG
166 #define HERE(production, level) \
167 if (traceParseExpr) { \
168 fprintf(stderr, "%*s%s: lexeme=%s, next=\"%.20s\"\n", \
169 (level), " ", (production), \
170 lexemeStrings[infoPtr->lexeme], infoPtr->next); \
173 #define HERE(production, level)
174 #endif /* TCL_COMPILE_DEBUG */
177 *----------------------------------------------------------------------
181 * Given a string, this procedure parses the first Tcl expression
182 * in the string and returns information about the structure of
183 * the expression. This procedure is the top-level interface to the
184 * the expression parsing module.
187 * The return value is TCL_OK if the command was parsed successfully
188 * and TCL_ERROR otherwise. If an error occurs and interp isn't NULL
189 * then an error message is left in its result. On a successful return,
190 * parsePtr is filled in with information about the expression that
194 * If there is insufficient space in parsePtr to hold all the
195 * information about the expression, then additional space is
196 * malloc-ed. If the procedure returns TCL_OK then the caller must
197 * eventually invoke Tcl_FreeParse to release any additional space
198 * that was allocated.
200 *----------------------------------------------------------------------
204 Tcl_ParseExpr(interp, string, numBytes, parsePtr)
205 Tcl_Interp *interp; /* Used for error reporting. */
206 char *string; /* The source string to parse. */
207 int numBytes; /* Number of bytes in string. If < 0, the
208 * string consists of all bytes up to the
209 * first null character. */
210 Tcl_Parse *parsePtr; /* Structure to fill with information about
211 * the parsed expression; any previous
212 * information in the structure is
220 numBytes = (string? strlen(string) : 0);
222 #ifdef TCL_COMPILE_DEBUG
223 if (traceParseExpr) {
224 fprintf(stderr, "Tcl_ParseExpr: string=\"%.*s\"\n",
227 #endif /* TCL_COMPILE_DEBUG */
229 parsePtr->commentStart = NULL;
230 parsePtr->commentSize = 0;
231 parsePtr->commandStart = NULL;
232 parsePtr->commandSize = 0;
233 parsePtr->numWords = 0;
234 parsePtr->tokenPtr = parsePtr->staticTokens;
235 parsePtr->numTokens = 0;
236 parsePtr->tokensAvailable = NUM_STATIC_TOKENS;
237 parsePtr->string = string;
238 parsePtr->end = (string + numBytes);
239 parsePtr->interp = interp;
240 parsePtr->term = string;
241 parsePtr->incomplete = 0;
244 * Temporarily overwrite the character just after the end of the
245 * string with a 0 byte. This acts as a sentinel and reduces the
246 * number of places where we have to check for the end of the
247 * input string. The original value of the byte is restored at
248 * the end of the parse.
251 savedChar = string[numBytes];
252 string[numBytes] = 0;
255 * Initialize the ParseInfo structure that holds state while parsing
259 info.parsePtr = parsePtr;
260 info.lexeme = UNKNOWN;
264 info.prevEnd = string;
265 info.originalExpr = string;
266 info.lastChar = (string + numBytes); /* just after last char of expr */
269 * Get the first lexeme then parse the expression.
272 code = GetLexeme(&info);
273 if (code != TCL_OK) {
276 code = ParseCondExpr(&info);
277 if (code != TCL_OK) {
280 if (info.lexeme != END) {
281 LogSyntaxError(&info);
284 string[numBytes] = (char) savedChar;
288 string[numBytes] = (char) savedChar;
289 if (parsePtr->tokenPtr != parsePtr->staticTokens) {
290 ckfree((char *) parsePtr->tokenPtr);
296 *----------------------------------------------------------------------
300 * This procedure parses a Tcl conditional expression:
301 * condExpr ::= lorExpr ['?' condExpr ':' condExpr]
303 * Note that this is the topmost recursive-descent parsing routine used
304 * by TclParseExpr to parse expressions. This avoids an extra procedure
305 * call since such a procedure would only return the result of calling
306 * ParseCondExpr. Other recursive-descent procedures that need to parse
307 * complete expressions also call ParseCondExpr.
310 * The return value is TCL_OK on a successful parse and TCL_ERROR
311 * on failure. If TCL_ERROR is returned, then the interpreter's result
312 * contains an error message.
315 * If there is insufficient space in parsePtr to hold all the
316 * information about the subexpression, then additional space is
319 *----------------------------------------------------------------------
323 ParseCondExpr(infoPtr)
324 ParseInfo *infoPtr; /* Holds the parse state for the
325 * expression being parsed. */
327 Tcl_Parse *parsePtr = infoPtr->parsePtr;
328 Tcl_Token *tokenPtr, *firstTokenPtr, *condTokenPtr;
329 int firstIndex, numToMove, code;
333 srcStart = infoPtr->start;
334 firstIndex = parsePtr->numTokens;
336 code = ParseLorExpr(infoPtr);
337 if (code != TCL_OK) {
341 if (infoPtr->lexeme == QUESTY) {
343 * Emit two tokens: one TCL_TOKEN_SUB_EXPR token for the entire
344 * conditional expression, and a TCL_TOKEN_OPERATOR token for
345 * the "?" operator. Note that these two tokens must be inserted
346 * before the LOR operand tokens generated above.
349 if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) {
350 TclExpandTokenArray(parsePtr);
352 firstTokenPtr = &parsePtr->tokenPtr[firstIndex];
353 tokenPtr = (firstTokenPtr + 2);
354 numToMove = (parsePtr->numTokens - firstIndex);
355 memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr,
356 (size_t) (numToMove * sizeof(Tcl_Token)));
357 parsePtr->numTokens += 2;
359 tokenPtr = firstTokenPtr;
360 tokenPtr->type = TCL_TOKEN_SUB_EXPR;
361 tokenPtr->start = srcStart;
364 tokenPtr->type = TCL_TOKEN_OPERATOR;
365 tokenPtr->start = infoPtr->start;
367 tokenPtr->numComponents = 0;
373 code = GetLexeme(infoPtr);
374 if (code != TCL_OK) {
379 * Parse the "then" expression.
382 code = ParseCondExpr(infoPtr);
383 if (code != TCL_OK) {
386 if (infoPtr->lexeme != COLON) {
387 LogSyntaxError(infoPtr);
390 code = GetLexeme(infoPtr); /* skip over the ':' */
391 if (code != TCL_OK) {
396 * Parse the "else" expression.
399 code = ParseCondExpr(infoPtr);
400 if (code != TCL_OK) {
405 * Now set the size-related fields in the '?' subexpression token.
408 condTokenPtr = &parsePtr->tokenPtr[firstIndex];
409 condTokenPtr->size = (infoPtr->prevEnd - srcStart);
410 condTokenPtr->numComponents = parsePtr->numTokens - (firstIndex+1);
416 *----------------------------------------------------------------------
420 * This procedure parses a Tcl logical or expression:
421 * lorExpr ::= landExpr {'||' landExpr}
424 * The return value is TCL_OK on a successful parse and TCL_ERROR
425 * on failure. If TCL_ERROR is returned, then the interpreter's result
426 * contains an error message.
429 * If there is insufficient space in parsePtr to hold all the
430 * information about the subexpression, then additional space is
433 *----------------------------------------------------------------------
437 ParseLorExpr(infoPtr)
438 ParseInfo *infoPtr; /* Holds the parse state for the
439 * expression being parsed. */
441 Tcl_Parse *parsePtr = infoPtr->parsePtr;
442 int firstIndex, code;
443 char *srcStart, *operator;
446 srcStart = infoPtr->start;
447 firstIndex = parsePtr->numTokens;
449 code = ParseLandExpr(infoPtr);
450 if (code != TCL_OK) {
454 while (infoPtr->lexeme == OR) {
455 operator = infoPtr->start;
456 code = GetLexeme(infoPtr); /* skip over the '||' */
457 if (code != TCL_OK) {
460 code = ParseLandExpr(infoPtr);
461 if (code != TCL_OK) {
466 * Generate tokens for the LOR subexpression and the '||' operator.
469 PrependSubExprTokens(operator, 2, srcStart,
470 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
476 *----------------------------------------------------------------------
480 * This procedure parses a Tcl logical and expression:
481 * landExpr ::= bitOrExpr {'&&' bitOrExpr}
484 * The return value is TCL_OK on a successful parse and TCL_ERROR
485 * on failure. If TCL_ERROR is returned, then the interpreter's result
486 * contains an error message.
489 * If there is insufficient space in parsePtr to hold all the
490 * information about the subexpression, then additional space is
493 *----------------------------------------------------------------------
497 ParseLandExpr(infoPtr)
498 ParseInfo *infoPtr; /* Holds the parse state for the
499 * expression being parsed. */
501 Tcl_Parse *parsePtr = infoPtr->parsePtr;
502 int firstIndex, code;
503 char *srcStart, *operator;
506 srcStart = infoPtr->start;
507 firstIndex = parsePtr->numTokens;
509 code = ParseBitOrExpr(infoPtr);
510 if (code != TCL_OK) {
514 while (infoPtr->lexeme == AND) {
515 operator = infoPtr->start;
516 code = GetLexeme(infoPtr); /* skip over the '&&' */
517 if (code != TCL_OK) {
520 code = ParseBitOrExpr(infoPtr);
521 if (code != TCL_OK) {
526 * Generate tokens for the LAND subexpression and the '&&' operator.
529 PrependSubExprTokens(operator, 2, srcStart,
530 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
536 *----------------------------------------------------------------------
540 * This procedure parses a Tcl bitwise or expression:
541 * bitOrExpr ::= bitXorExpr {'|' bitXorExpr}
544 * The return value is TCL_OK on a successful parse and TCL_ERROR
545 * on failure. If TCL_ERROR is returned, then the interpreter's result
546 * contains an error message.
549 * If there is insufficient space in parsePtr to hold all the
550 * information about the subexpression, then additional space is
553 *----------------------------------------------------------------------
557 ParseBitOrExpr(infoPtr)
558 ParseInfo *infoPtr; /* Holds the parse state for the
559 * expression being parsed. */
561 Tcl_Parse *parsePtr = infoPtr->parsePtr;
562 int firstIndex, code;
563 char *srcStart, *operator;
565 HERE("bitOrExpr", 4);
566 srcStart = infoPtr->start;
567 firstIndex = parsePtr->numTokens;
569 code = ParseBitXorExpr(infoPtr);
570 if (code != TCL_OK) {
574 while (infoPtr->lexeme == BIT_OR) {
575 operator = infoPtr->start;
576 code = GetLexeme(infoPtr); /* skip over the '|' */
577 if (code != TCL_OK) {
581 code = ParseBitXorExpr(infoPtr);
582 if (code != TCL_OK) {
587 * Generate tokens for the BITOR subexpression and the '|' operator.
590 PrependSubExprTokens(operator, 1, srcStart,
591 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
597 *----------------------------------------------------------------------
601 * This procedure parses a Tcl bitwise exclusive or expression:
602 * bitXorExpr ::= bitAndExpr {'^' bitAndExpr}
605 * The return value is TCL_OK on a successful parse and TCL_ERROR
606 * on failure. If TCL_ERROR is returned, then the interpreter's result
607 * contains an error message.
610 * If there is insufficient space in parsePtr to hold all the
611 * information about the subexpression, then additional space is
614 *----------------------------------------------------------------------
618 ParseBitXorExpr(infoPtr)
619 ParseInfo *infoPtr; /* Holds the parse state for the
620 * expression being parsed. */
622 Tcl_Parse *parsePtr = infoPtr->parsePtr;
623 int firstIndex, code;
624 char *srcStart, *operator;
626 HERE("bitXorExpr", 5);
627 srcStart = infoPtr->start;
628 firstIndex = parsePtr->numTokens;
630 code = ParseBitAndExpr(infoPtr);
631 if (code != TCL_OK) {
635 while (infoPtr->lexeme == BIT_XOR) {
636 operator = infoPtr->start;
637 code = GetLexeme(infoPtr); /* skip over the '^' */
638 if (code != TCL_OK) {
642 code = ParseBitAndExpr(infoPtr);
643 if (code != TCL_OK) {
648 * Generate tokens for the XOR subexpression and the '^' operator.
651 PrependSubExprTokens(operator, 1, srcStart,
652 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
658 *----------------------------------------------------------------------
662 * This procedure parses a Tcl bitwise and expression:
663 * bitAndExpr ::= equalityExpr {'&' equalityExpr}
666 * The return value is TCL_OK on a successful parse and TCL_ERROR
667 * on failure. If TCL_ERROR is returned, then the interpreter's result
668 * contains an error message.
671 * If there is insufficient space in parsePtr to hold all the
672 * information about the subexpression, then additional space is
675 *----------------------------------------------------------------------
679 ParseBitAndExpr(infoPtr)
680 ParseInfo *infoPtr; /* Holds the parse state for the
681 * expression being parsed. */
683 Tcl_Parse *parsePtr = infoPtr->parsePtr;
684 int firstIndex, code;
685 char *srcStart, *operator;
687 HERE("bitAndExpr", 6);
688 srcStart = infoPtr->start;
689 firstIndex = parsePtr->numTokens;
691 code = ParseEqualityExpr(infoPtr);
692 if (code != TCL_OK) {
696 while (infoPtr->lexeme == BIT_AND) {
697 operator = infoPtr->start;
698 code = GetLexeme(infoPtr); /* skip over the '&' */
699 if (code != TCL_OK) {
702 code = ParseEqualityExpr(infoPtr);
703 if (code != TCL_OK) {
708 * Generate tokens for the BITAND subexpression and '&' operator.
711 PrependSubExprTokens(operator, 1, srcStart,
712 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
718 *----------------------------------------------------------------------
720 * ParseEqualityExpr --
722 * This procedure parses a Tcl equality (inequality) expression:
723 * equalityExpr ::= relationalExpr {('==' | '!=') relationalExpr}
726 * The return value is TCL_OK on a successful parse and TCL_ERROR
727 * on failure. If TCL_ERROR is returned, then the interpreter's result
728 * contains an error message.
731 * If there is insufficient space in parsePtr to hold all the
732 * information about the subexpression, then additional space is
735 *----------------------------------------------------------------------
739 ParseEqualityExpr(infoPtr)
740 ParseInfo *infoPtr; /* Holds the parse state for the
741 * expression being parsed. */
743 Tcl_Parse *parsePtr = infoPtr->parsePtr;
744 int firstIndex, lexeme, code;
745 char *srcStart, *operator;
747 HERE("equalityExpr", 7);
748 srcStart = infoPtr->start;
749 firstIndex = parsePtr->numTokens;
751 code = ParseRelationalExpr(infoPtr);
752 if (code != TCL_OK) {
756 lexeme = infoPtr->lexeme;
757 while ((lexeme == EQUAL) || (lexeme == NEQ)) {
758 operator = infoPtr->start;
759 code = GetLexeme(infoPtr); /* skip over == or != */
760 if (code != TCL_OK) {
763 code = ParseRelationalExpr(infoPtr);
764 if (code != TCL_OK) {
769 * Generate tokens for the subexpression and '==' or '!=' operator.
772 PrependSubExprTokens(operator, 2, srcStart,
773 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
774 lexeme = infoPtr->lexeme;
780 *----------------------------------------------------------------------
782 * ParseRelationalExpr --
784 * This procedure parses a Tcl relational expression:
785 * relationalExpr ::= shiftExpr {('<' | '>' | '<=' | '>=') shiftExpr}
788 * The return value is TCL_OK on a successful parse and TCL_ERROR
789 * on failure. If TCL_ERROR is returned, then the interpreter's result
790 * contains an error message.
793 * If there is insufficient space in parsePtr to hold all the
794 * information about the subexpression, then additional space is
797 *----------------------------------------------------------------------
801 ParseRelationalExpr(infoPtr)
802 ParseInfo *infoPtr; /* Holds the parse state for the
803 * expression being parsed. */
805 Tcl_Parse *parsePtr = infoPtr->parsePtr;
806 int firstIndex, lexeme, operatorSize, code;
807 char *srcStart, *operator;
809 HERE("relationalExpr", 8);
810 srcStart = infoPtr->start;
811 firstIndex = parsePtr->numTokens;
813 code = ParseShiftExpr(infoPtr);
814 if (code != TCL_OK) {
818 lexeme = infoPtr->lexeme;
819 while ((lexeme == LESS) || (lexeme == GREATER) || (lexeme == LEQ)
820 || (lexeme == GEQ)) {
821 operator = infoPtr->start;
822 if ((lexeme == LEQ) || (lexeme == GEQ)) {
827 code = GetLexeme(infoPtr); /* skip over the operator */
828 if (code != TCL_OK) {
831 code = ParseShiftExpr(infoPtr);
832 if (code != TCL_OK) {
837 * Generate tokens for the subexpression and the operator.
840 PrependSubExprTokens(operator, operatorSize, srcStart,
841 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
842 lexeme = infoPtr->lexeme;
848 *----------------------------------------------------------------------
852 * This procedure parses a Tcl shift expression:
853 * shiftExpr ::= addExpr {('<<' | '>>') addExpr}
856 * The return value is TCL_OK on a successful parse and TCL_ERROR
857 * on failure. If TCL_ERROR is returned, then the interpreter's result
858 * contains an error message.
861 * If there is insufficient space in parsePtr to hold all the
862 * information about the subexpression, then additional space is
865 *----------------------------------------------------------------------
869 ParseShiftExpr(infoPtr)
870 ParseInfo *infoPtr; /* Holds the parse state for the
871 * expression being parsed. */
873 Tcl_Parse *parsePtr = infoPtr->parsePtr;
874 int firstIndex, lexeme, code;
875 char *srcStart, *operator;
877 HERE("shiftExpr", 9);
878 srcStart = infoPtr->start;
879 firstIndex = parsePtr->numTokens;
881 code = ParseAddExpr(infoPtr);
882 if (code != TCL_OK) {
886 lexeme = infoPtr->lexeme;
887 while ((lexeme == LEFT_SHIFT) || (lexeme == RIGHT_SHIFT)) {
888 operator = infoPtr->start;
889 code = GetLexeme(infoPtr); /* skip over << or >> */
890 if (code != TCL_OK) {
893 code = ParseAddExpr(infoPtr);
894 if (code != TCL_OK) {
899 * Generate tokens for the subexpression and '<<' or '>>' operator.
902 PrependSubExprTokens(operator, 2, srcStart,
903 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
904 lexeme = infoPtr->lexeme;
910 *----------------------------------------------------------------------
914 * This procedure parses a Tcl addition expression:
915 * addExpr ::= multiplyExpr {('+' | '-') multiplyExpr}
918 * The return value is TCL_OK on a successful parse and TCL_ERROR
919 * on failure. If TCL_ERROR is returned, then the interpreter's result
920 * contains an error message.
923 * If there is insufficient space in parsePtr to hold all the
924 * information about the subexpression, then additional space is
927 *----------------------------------------------------------------------
931 ParseAddExpr(infoPtr)
932 ParseInfo *infoPtr; /* Holds the parse state for the
933 * expression being parsed. */
935 Tcl_Parse *parsePtr = infoPtr->parsePtr;
936 int firstIndex, lexeme, code;
937 char *srcStart, *operator;
940 srcStart = infoPtr->start;
941 firstIndex = parsePtr->numTokens;
943 code = ParseMultiplyExpr(infoPtr);
944 if (code != TCL_OK) {
948 lexeme = infoPtr->lexeme;
949 while ((lexeme == PLUS) || (lexeme == MINUS)) {
950 operator = infoPtr->start;
951 code = GetLexeme(infoPtr); /* skip over + or - */
952 if (code != TCL_OK) {
955 code = ParseMultiplyExpr(infoPtr);
956 if (code != TCL_OK) {
961 * Generate tokens for the subexpression and '+' or '-' operator.
964 PrependSubExprTokens(operator, 1, srcStart,
965 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
966 lexeme = infoPtr->lexeme;
972 *----------------------------------------------------------------------
974 * ParseMultiplyExpr --
976 * This procedure parses a Tcl multiply expression:
977 * multiplyExpr ::= unaryExpr {('*' | '/' | '%') unaryExpr}
980 * The return value is TCL_OK on a successful parse and TCL_ERROR
981 * on failure. If TCL_ERROR is returned, then the interpreter's result
982 * contains an error message.
985 * If there is insufficient space in parsePtr to hold all the
986 * information about the subexpression, then additional space is
989 *----------------------------------------------------------------------
993 ParseMultiplyExpr(infoPtr)
994 ParseInfo *infoPtr; /* Holds the parse state for the
995 * expression being parsed. */
997 Tcl_Parse *parsePtr = infoPtr->parsePtr;
998 int firstIndex, lexeme, code;
999 char *srcStart, *operator;
1001 HERE("multiplyExpr", 11);
1002 srcStart = infoPtr->start;
1003 firstIndex = parsePtr->numTokens;
1005 code = ParseUnaryExpr(infoPtr);
1006 if (code != TCL_OK) {
1010 lexeme = infoPtr->lexeme;
1011 while ((lexeme == MULT) || (lexeme == DIVIDE) || (lexeme == MOD)) {
1012 operator = infoPtr->start;
1013 code = GetLexeme(infoPtr); /* skip over * or / or % */
1014 if (code != TCL_OK) {
1017 code = ParseUnaryExpr(infoPtr);
1018 if (code != TCL_OK) {
1023 * Generate tokens for the subexpression and * or / or % operator.
1026 PrependSubExprTokens(operator, 1, srcStart,
1027 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
1028 lexeme = infoPtr->lexeme;
1034 *----------------------------------------------------------------------
1038 * This procedure parses a Tcl unary expression:
1039 * unaryExpr ::= ('+' | '-' | '~' | '!') unaryExpr | primaryExpr
1042 * The return value is TCL_OK on a successful parse and TCL_ERROR
1043 * on failure. If TCL_ERROR is returned, then the interpreter's result
1044 * contains an error message.
1047 * If there is insufficient space in parsePtr to hold all the
1048 * information about the subexpression, then additional space is
1051 *----------------------------------------------------------------------
1055 ParseUnaryExpr(infoPtr)
1056 ParseInfo *infoPtr; /* Holds the parse state for the
1057 * expression being parsed. */
1059 Tcl_Parse *parsePtr = infoPtr->parsePtr;
1060 int firstIndex, lexeme, code;
1061 char *srcStart, *operator;
1063 HERE("unaryExpr", 12);
1064 srcStart = infoPtr->start;
1065 firstIndex = parsePtr->numTokens;
1067 lexeme = infoPtr->lexeme;
1068 if ((lexeme == PLUS) || (lexeme == MINUS) || (lexeme == BIT_NOT)
1069 || (lexeme == NOT)) {
1070 operator = infoPtr->start;
1071 code = GetLexeme(infoPtr); /* skip over the unary operator */
1072 if (code != TCL_OK) {
1075 code = ParseUnaryExpr(infoPtr);
1076 if (code != TCL_OK) {
1081 * Generate tokens for the subexpression and the operator.
1084 PrependSubExprTokens(operator, 1, srcStart,
1085 (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
1086 } else { /* must be a primaryExpr */
1087 code = ParsePrimaryExpr(infoPtr);
1088 if (code != TCL_OK) {
1096 *----------------------------------------------------------------------
1098 * ParsePrimaryExpr --
1100 * This procedure parses a Tcl primary expression:
1101 * primaryExpr ::= literal | varReference | quotedString |
1102 * '[' command ']' | mathFuncCall | '(' condExpr ')'
1105 * The return value is TCL_OK on a successful parse and TCL_ERROR
1106 * on failure. If TCL_ERROR is returned, then the interpreter's result
1107 * contains an error message.
1110 * If there is insufficient space in parsePtr to hold all the
1111 * information about the subexpression, then additional space is
1114 *----------------------------------------------------------------------
1118 ParsePrimaryExpr(infoPtr)
1119 ParseInfo *infoPtr; /* Holds the parse state for the
1120 * expression being parsed. */
1122 Tcl_Parse *parsePtr = infoPtr->parsePtr;
1123 Tcl_Interp *interp = parsePtr->interp;
1124 Tcl_Token *tokenPtr, *exprTokenPtr;
1126 char *dollarPtr, *stringStart, *termPtr, *src;
1127 int lexeme, exprIndex, firstIndex, numToMove, code;
1130 * We simply recurse on parenthesized subexpressions.
1133 HERE("primaryExpr", 13);
1134 lexeme = infoPtr->lexeme;
1135 if (lexeme == OPEN_PAREN) {
1136 code = GetLexeme(infoPtr); /* skip over the '(' */
1137 if (code != TCL_OK) {
1140 code = ParseCondExpr(infoPtr);
1141 if (code != TCL_OK) {
1144 if (infoPtr->lexeme != CLOSE_PAREN) {
1147 code = GetLexeme(infoPtr); /* skip over the ')' */
1148 if (code != TCL_OK) {
1155 * Start a TCL_TOKEN_SUB_EXPR token for the primary.
1158 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1159 TclExpandTokenArray(parsePtr);
1161 exprIndex = parsePtr->numTokens;
1162 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1163 exprTokenPtr->type = TCL_TOKEN_SUB_EXPR;
1164 exprTokenPtr->start = infoPtr->start;
1165 parsePtr->numTokens++;
1168 * Process the primary then finish setting the fields of the
1169 * TCL_TOKEN_SUB_EXPR token. Note that we can't use the pointer now
1170 * stored in "exprTokenPtr" in the code below since the token array
1171 * might be reallocated.
1174 firstIndex = parsePtr->numTokens;
1178 * Int or double number.
1181 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1182 TclExpandTokenArray(parsePtr);
1184 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1185 tokenPtr->type = TCL_TOKEN_TEXT;
1186 tokenPtr->start = infoPtr->start;
1187 tokenPtr->size = infoPtr->size;
1188 tokenPtr->numComponents = 0;
1189 parsePtr->numTokens++;
1191 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1192 exprTokenPtr->size = infoPtr->size;
1193 exprTokenPtr->numComponents = 1;
1198 * $var variable reference.
1201 dollarPtr = (infoPtr->next - 1);
1202 code = Tcl_ParseVarName(interp, dollarPtr,
1203 (infoPtr->lastChar - dollarPtr), parsePtr, 1);
1204 if (code != TCL_OK) {
1207 infoPtr->next = dollarPtr + parsePtr->tokenPtr[firstIndex].size;
1209 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1210 exprTokenPtr->size = parsePtr->tokenPtr[firstIndex].size;
1211 exprTokenPtr->numComponents =
1212 (parsePtr->tokenPtr[firstIndex].numComponents + 1);
1220 stringStart = infoPtr->next;
1221 code = Tcl_ParseQuotedString(interp, infoPtr->start,
1222 (infoPtr->lastChar - stringStart), parsePtr, 1, &termPtr);
1223 if (code != TCL_OK) {
1226 infoPtr->next = termPtr;
1228 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1229 exprTokenPtr->size = (termPtr - exprTokenPtr->start);
1230 exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
1233 * If parsing the quoted string resulted in more than one token,
1234 * insert a TCL_TOKEN_WORD token before them. This indicates that
1235 * the quoted string represents a concatenation of multiple tokens.
1238 if (exprTokenPtr->numComponents > 1) {
1239 if (parsePtr->numTokens >= parsePtr->tokensAvailable) {
1240 TclExpandTokenArray(parsePtr);
1242 tokenPtr = &parsePtr->tokenPtr[firstIndex];
1243 numToMove = (parsePtr->numTokens - firstIndex);
1244 memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr,
1245 (size_t) (numToMove * sizeof(Tcl_Token)));
1246 parsePtr->numTokens++;
1248 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1249 exprTokenPtr->numComponents++;
1251 tokenPtr->type = TCL_TOKEN_WORD;
1252 tokenPtr->start = exprTokenPtr->start;
1253 tokenPtr->size = exprTokenPtr->size;
1254 tokenPtr->numComponents = (exprTokenPtr->numComponents - 1);
1260 * '[' command {command} ']'
1263 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1264 TclExpandTokenArray(parsePtr);
1266 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1267 tokenPtr->type = TCL_TOKEN_COMMAND;
1268 tokenPtr->start = infoPtr->start;
1269 tokenPtr->numComponents = 0;
1270 parsePtr->numTokens++;
1273 * Call Tcl_ParseCommand repeatedly to parse the nested command(s)
1274 * to find their end, then throw away that parse information.
1277 src = infoPtr->next;
1279 if (Tcl_ParseCommand(interp, src, (parsePtr->end - src), 1,
1280 &nested) != TCL_OK) {
1281 parsePtr->term = nested.term;
1282 parsePtr->errorType = nested.errorType;
1283 parsePtr->incomplete = nested.incomplete;
1286 src = (nested.commandStart + nested.commandSize);
1287 if (nested.tokenPtr != nested.staticTokens) {
1288 ckfree((char *) nested.tokenPtr);
1290 if ((src[-1] == ']') && !nested.incomplete) {
1293 if (src == parsePtr->end) {
1294 if (parsePtr->interp != NULL) {
1295 Tcl_SetResult(interp, "missing close-bracket",
1298 parsePtr->term = tokenPtr->start;
1299 parsePtr->errorType = TCL_PARSE_MISSING_BRACKET;
1300 parsePtr->incomplete = 1;
1304 tokenPtr->size = (src - tokenPtr->start);
1305 infoPtr->next = src;
1307 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1308 exprTokenPtr->size = (src - tokenPtr->start);
1309 exprTokenPtr->numComponents = 1;
1317 code = Tcl_ParseBraces(interp, infoPtr->start,
1318 (infoPtr->lastChar - infoPtr->start), parsePtr, 1,
1320 if (code != TCL_OK) {
1323 infoPtr->next = termPtr;
1325 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1326 exprTokenPtr->size = (termPtr - infoPtr->start);
1327 exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
1330 * If parsing the braced string resulted in more than one token,
1331 * insert a TCL_TOKEN_WORD token before them. This indicates that
1332 * the braced string represents a concatenation of multiple tokens.
1335 if (exprTokenPtr->numComponents > 1) {
1336 if (parsePtr->numTokens >= parsePtr->tokensAvailable) {
1337 TclExpandTokenArray(parsePtr);
1339 tokenPtr = &parsePtr->tokenPtr[firstIndex];
1340 numToMove = (parsePtr->numTokens - firstIndex);
1341 memmove((VOID *) (tokenPtr + 1), (VOID *) tokenPtr,
1342 (size_t) (numToMove * sizeof(Tcl_Token)));
1343 parsePtr->numTokens++;
1345 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1346 exprTokenPtr->numComponents++;
1348 tokenPtr->type = TCL_TOKEN_WORD;
1349 tokenPtr->start = exprTokenPtr->start;
1350 tokenPtr->size = exprTokenPtr->size;
1351 tokenPtr->numComponents = exprTokenPtr->numComponents-1;
1357 * math_func '(' expr {',' expr} ')'
1360 if (parsePtr->numTokens == parsePtr->tokensAvailable) {
1361 TclExpandTokenArray(parsePtr);
1363 tokenPtr = &parsePtr->tokenPtr[parsePtr->numTokens];
1364 tokenPtr->type = TCL_TOKEN_OPERATOR;
1365 tokenPtr->start = infoPtr->start;
1366 tokenPtr->size = infoPtr->size;
1367 tokenPtr->numComponents = 0;
1368 parsePtr->numTokens++;
1370 code = GetLexeme(infoPtr); /* skip over function name */
1371 if (code != TCL_OK) {
1374 if (infoPtr->lexeme != OPEN_PAREN) {
1377 code = GetLexeme(infoPtr); /* skip over '(' */
1378 if (code != TCL_OK) {
1382 while (infoPtr->lexeme != CLOSE_PAREN) {
1383 code = ParseCondExpr(infoPtr);
1384 if (code != TCL_OK) {
1388 if (infoPtr->lexeme == COMMA) {
1389 code = GetLexeme(infoPtr); /* skip over , */
1390 if (code != TCL_OK) {
1393 } else if (infoPtr->lexeme != CLOSE_PAREN) {
1398 exprTokenPtr = &parsePtr->tokenPtr[exprIndex];
1399 exprTokenPtr->size = (infoPtr->next - exprTokenPtr->start);
1400 exprTokenPtr->numComponents = parsePtr->numTokens - firstIndex;
1408 * Advance to the next lexeme before returning.
1411 code = GetLexeme(infoPtr);
1412 if (code != TCL_OK) {
1415 parsePtr->term = infoPtr->next;
1419 LogSyntaxError(infoPtr);
1424 *----------------------------------------------------------------------
1428 * Lexical scanner for Tcl expressions: scans a single operator or
1429 * other syntactic element from an expression string.
1432 * TCL_OK is returned unless an error occurred. In that case a standard
1433 * Tcl error code is returned and, if infoPtr->parsePtr->interp is
1434 * non-NULL, the interpreter's result is set to hold an error
1435 * message. TCL_ERROR is returned if an integer overflow, or a
1436 * floating-point overflow or underflow occurred while reading in a
1437 * number. If the lexical analysis is successful, infoPtr->lexeme
1438 * refers to the next symbol in the expression string, and
1439 * infoPtr->next is advanced past the lexeme. Also, if the lexeme is a
1440 * LITERAL or FUNC_NAME, then infoPtr->start is set to the first
1441 * character of the lexeme; otherwise it is set NULL.
1444 * If there is insufficient space in parsePtr to hold all the
1445 * information about the subexpression, then additional space is
1448 *----------------------------------------------------------------------
1453 ParseInfo *infoPtr; /* Holds state needed to parse the expr,
1454 * including the resulting lexeme. */
1456 register char *src; /* Points to current source char. */
1457 char *termPtr; /* Points to char terminating a literal. */
1458 double doubleValue; /* Value of a scanned double literal. */
1460 int startsWithDigit, offset;
1461 Tcl_Parse *parsePtr = infoPtr->parsePtr;
1462 Tcl_Interp *interp = parsePtr->interp;
1466 * Record where the previous lexeme ended. Since we always read one
1467 * lexeme ahead during parsing, this helps us know the source length of
1468 * subexpression tokens.
1471 infoPtr->prevEnd = infoPtr->next;
1474 * Scan over leading white space at the start of a lexeme. Note that a
1475 * backslash-newline is treated as a space.
1478 src = infoPtr->next;
1480 while (isspace(UCHAR(c)) || (c == '\\')) { /* INTL: ISO space */
1482 if (src[1] == '\n') {
1485 break; /* no longer white space */
1492 parsePtr->term = src;
1493 if (src >= infoPtr->lastChar) {
1494 infoPtr->lexeme = END;
1495 infoPtr->next = src;
1500 * Try to parse the lexeme first as an integer or floating-point
1501 * number. Don't check for a number if the first character c is
1502 * "+" or "-". If we did, we might treat a binary operator as unary
1503 * by mistake, which would eventually cause a syntax error.
1506 if ((c != '+') && (c != '-')) {
1507 startsWithDigit = isdigit(UCHAR(c)); /* INTL: digit */
1508 if (startsWithDigit && TclLooksLikeInt(src, -1)) {
1510 (void) strtoul(src, &termPtr, 0);
1511 if (errno == ERANGE) {
1512 if (interp != NULL) {
1513 char *s = "integer value too large to represent";
1514 Tcl_ResetResult(interp);
1515 Tcl_AppendToObj(Tcl_GetObjResult(interp), s, -1);
1516 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s,
1519 parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
1522 if (termPtr != src) {
1524 * src was the start of a valid integer, but was it
1525 * a bad octal? Stopping at a digit would cause that.
1527 if (isdigit(UCHAR(*termPtr))) { /* INTL: digit. */
1529 * We only want to report an error for the number,
1530 * but we may have something like "08+1"
1532 if (interp != NULL) {
1533 while (isdigit(UCHAR(*(++termPtr)))) {} /* INTL: digit. */
1534 Tcl_ResetResult(interp);
1535 offset = termPtr - src;
1538 Tcl_AppendResult(interp, "\"", src,
1539 "\" is an invalid octal number",
1543 parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
1547 infoPtr->lexeme = LITERAL;
1548 infoPtr->start = src;
1549 infoPtr->size = (termPtr - src);
1550 infoPtr->next = termPtr;
1551 parsePtr->term = termPtr;
1554 } else if (startsWithDigit || (c == '.')
1555 || (c == 'n') || (c == 'N')) {
1557 doubleValue = strtod(src, &termPtr);
1558 if (termPtr != src) {
1560 if (interp != NULL) {
1561 TclExprFloatError(interp, doubleValue);
1563 parsePtr->errorType = TCL_PARSE_BAD_NUMBER;
1568 * src was the start of a valid double.
1571 infoPtr->lexeme = LITERAL;
1572 infoPtr->start = src;
1573 infoPtr->size = (termPtr - src);
1574 infoPtr->next = termPtr;
1575 parsePtr->term = termPtr;
1582 * Not an integer or double literal. Initialize the lexeme's fields
1583 * assuming the common case of a single character lexeme.
1586 infoPtr->start = src;
1588 infoPtr->next = src+1;
1589 parsePtr->term = infoPtr->next;
1593 infoPtr->lexeme = OPEN_BRACKET;
1597 infoPtr->lexeme = OPEN_BRACE;
1601 infoPtr->lexeme = OPEN_PAREN;
1605 infoPtr->lexeme = CLOSE_PAREN;
1609 infoPtr->lexeme = DOLLAR;
1613 infoPtr->lexeme = QUOTE;
1617 infoPtr->lexeme = COMMA;
1621 infoPtr->lexeme = MULT;
1625 infoPtr->lexeme = DIVIDE;
1629 infoPtr->lexeme = MOD;
1633 infoPtr->lexeme = PLUS;
1637 infoPtr->lexeme = MINUS;
1641 infoPtr->lexeme = QUESTY;
1645 infoPtr->lexeme = COLON;
1651 infoPtr->lexeme = LEFT_SHIFT;
1653 infoPtr->next = src+2;
1656 infoPtr->lexeme = LEQ;
1658 infoPtr->next = src+2;
1661 infoPtr->lexeme = LESS;
1664 parsePtr->term = infoPtr->next;
1670 infoPtr->lexeme = RIGHT_SHIFT;
1672 infoPtr->next = src+2;
1675 infoPtr->lexeme = GEQ;
1677 infoPtr->next = src+2;
1680 infoPtr->lexeme = GREATER;
1683 parsePtr->term = infoPtr->next;
1687 if (src[1] == '=') {
1688 infoPtr->lexeme = EQUAL;
1690 infoPtr->next = src+2;
1692 infoPtr->lexeme = UNKNOWN;
1694 parsePtr->term = infoPtr->next;
1698 if (src[1] == '=') {
1699 infoPtr->lexeme = NEQ;
1701 infoPtr->next = src+2;
1703 infoPtr->lexeme = NOT;
1705 parsePtr->term = infoPtr->next;
1709 if (src[1] == '&') {
1710 infoPtr->lexeme = AND;
1712 infoPtr->next = src+2;
1714 infoPtr->lexeme = BIT_AND;
1716 parsePtr->term = infoPtr->next;
1720 infoPtr->lexeme = BIT_XOR;
1724 if (src[1] == '|') {
1725 infoPtr->lexeme = OR;
1727 infoPtr->next = src+2;
1729 infoPtr->lexeme = BIT_OR;
1731 parsePtr->term = infoPtr->next;
1735 infoPtr->lexeme = BIT_NOT;
1739 offset = Tcl_UtfToUniChar(src, &ch);
1741 if (isalpha(UCHAR(c))) { /* INTL: ISO only. */
1742 infoPtr->lexeme = FUNC_NAME;
1743 while (isalnum(UCHAR(c)) || (c == '_')) { /* INTL: ISO only. */
1745 offset = Tcl_UtfToUniChar(src, &ch);
1748 infoPtr->size = (src - infoPtr->start);
1749 infoPtr->next = src;
1750 parsePtr->term = infoPtr->next;
1753 infoPtr->lexeme = UNKNOWN;
1759 *----------------------------------------------------------------------
1761 * PrependSubExprTokens --
1763 * This procedure is called after the operands of an subexpression have
1764 * been parsed. It generates two tokens: a TCL_TOKEN_SUB_EXPR token for
1765 * the subexpression, and a TCL_TOKEN_OPERATOR token for its operator.
1766 * These two tokens are inserted before the operand tokens.
1772 * If there is insufficient space in parsePtr to hold the new tokens,
1773 * additional space is malloc-ed.
1775 *----------------------------------------------------------------------
1779 PrependSubExprTokens(op, opBytes, src, srcBytes, firstIndex, infoPtr)
1780 char *op; /* Points to first byte of the operator
1781 * in the source script. */
1782 int opBytes; /* Number of bytes in the operator. */
1783 char *src; /* Points to first byte of the subexpression
1784 * in the source script. */
1785 int srcBytes; /* Number of bytes in subexpression's
1787 int firstIndex; /* Index of first token already emitted for
1788 * operator's first (or only) operand. */
1789 ParseInfo *infoPtr; /* Holds the parse state for the
1790 * expression being parsed. */
1792 Tcl_Parse *parsePtr = infoPtr->parsePtr;
1793 Tcl_Token *tokenPtr, *firstTokenPtr;
1796 if ((parsePtr->numTokens + 1) >= parsePtr->tokensAvailable) {
1797 TclExpandTokenArray(parsePtr);
1799 firstTokenPtr = &parsePtr->tokenPtr[firstIndex];
1800 tokenPtr = (firstTokenPtr + 2);
1801 numToMove = (parsePtr->numTokens - firstIndex);
1802 memmove((VOID *) tokenPtr, (VOID *) firstTokenPtr,
1803 (size_t) (numToMove * sizeof(Tcl_Token)));
1804 parsePtr->numTokens += 2;
1806 tokenPtr = firstTokenPtr;
1807 tokenPtr->type = TCL_TOKEN_SUB_EXPR;
1808 tokenPtr->start = src;
1809 tokenPtr->size = srcBytes;
1810 tokenPtr->numComponents = parsePtr->numTokens - (firstIndex + 1);
1813 tokenPtr->type = TCL_TOKEN_OPERATOR;
1814 tokenPtr->start = op;
1815 tokenPtr->size = opBytes;
1816 tokenPtr->numComponents = 0;
1820 *----------------------------------------------------------------------
1824 * This procedure is invoked after an error occurs when parsing an
1825 * expression. It sets the interpreter result to an error message
1826 * describing the error.
1832 * Sets the interpreter result to an error message describing the
1833 * expression that was being parsed when the error occurred.
1835 *----------------------------------------------------------------------
1839 LogSyntaxError(infoPtr)
1840 ParseInfo *infoPtr; /* Holds the parse state for the
1841 * expression being parsed. */
1843 int numBytes = (infoPtr->lastChar - infoPtr->originalExpr);
1846 sprintf(buffer, "syntax error in expression \"%.*s\"",
1847 ((numBytes > 60)? 60 : numBytes), infoPtr->originalExpr);
1848 Tcl_AppendStringsToObj(Tcl_GetObjResult(infoPtr->parsePtr->interp),
1849 buffer, (char *) NULL);
1850 infoPtr->parsePtr->errorType = TCL_PARSE_SYNTAX;
1851 infoPtr->parsePtr->term = infoPtr->start;