| ︙ | | |
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
-
+
|
* Copyright (c) 1997 Sun Microsystems, Inc.
* Copyright (c) 1998-2000 by Scriptics Corporation.
* Contributions from Don Porter, NIST, 2006. (not subject to US copyright)
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id: tclCompExpr.c,v 1.63 2007/07/10 16:57:34 dgp Exp $
* RCS: @(#) $Id: tclCompExpr.c,v 1.64 2007/07/10 17:07:37 dgp Exp $
*/
#include "tclInt.h"
#include "tclCompile.h" /* CompileEnv */
/*
* Expression parsing takes place in the routine ParseExpr(). It takes a
|
| ︙ | | |
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
|
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
|
-
+
|
OpNode *nodes = NULL; /* Pointer to the OpNode storage array where
* we build the parse tree. */
int nodesAvailable = 64; /* Initial size of the storage array. This
* value establishes a minimum tree memory cost
* of only about 1 kibyte, and is large enough
* for most expressions to parse with no need
* for array growth and reallocation. */
int nodesUsed = 0, numLiterals = 0, numFuncs = 0; /* Counters */
int nodesUsed = 0; /* Number of OpNodes filled. */
int code = TCL_OK; /* Return code */
int scanned = 0; /* Capture number of byte scanned by
* parsing routines. */
/* These variables hold the state of the parser */
unsigned char lexeme = START; /* Most recent lexeme parsed. */
int lastOpen = 0; /* Index of the OpNode of the OPEN_PAREN
|
| ︙ | | |
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
|
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
|
-
+
|
* the location of the syntax error in the
* expression. */
int insertMark = 0; /* A boolean controlling whether the "mark"
* should be inserted. */
const int limit = 25; /* Portions of the error message are
* constructed out of substrings of the
* original expression. In order to keep the
* error message readable, we impost this limit
* error message readable, we impose this limit
* on the substring size we extract. */
if (numBytes < 0) {
numBytes = (start ? strlen(start) : 0);
}
TclParseInit(interp, start, numBytes, parsePtr);
|
| ︙ | | |
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
|
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
|
continue;
case INCOMPLETE:
msg = Tcl_ObjPrintf(
"incomplete operator \"%.*s\"", scanned, start);
code = TCL_ERROR;
continue;
case BAREWORD:
/*
* Most barewords in an expression are a syntax error.
* The exceptions are that when a bareword is followed by
* an open paren, it might be a function call, and when the
* bareword is a legal literal boolean value, we accept that
* as well.
*/
if (start[scanned+TclParseAllWhiteSpace(
start+scanned, numBytes-scanned)] == '(') {
lexeme = FUNCTION;
/*
* When we compile the expression we'll need the function
* name, and there's no place in the parse tree to store
* it, so we keep a separate list of all the function
* names we've parsed in the order we found them.
*/
Tcl_ListObjAppendElement(NULL, funcList, literal);
numFuncs++;
} else {
int b;
if (Tcl_GetBooleanFromObj(NULL, literal, &b) == TCL_OK) {
lexeme = BOOLEAN;
} else {
Tcl_DecrRefCount(literal);
msg = Tcl_ObjPrintf(
|
| ︙ | | |
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
|
630
631
632
633
634
635
636
637
638
639
640
641
642
643
|
-
|
* of this routine. [Bug 1705778, leak K23]
*/
switch (lexeme) {
case NUMBER:
case BOOLEAN:
Tcl_ListObjAppendElement(NULL, litList, literal);
numLiterals++;
break;
default:
break;
}
if (lastWas < 0) {
msg = Tcl_ObjPrintf("missing operator at %s", mark);
|
| ︙ | | |
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
|
775
776
777
778
779
780
781
782
783
784
785
786
787
788
|
-
|
if ((lexeme == QUOTED) || (lexeme == BRACED)) {
literal = Tcl_NewObj();
/* TODO: allow all compile-time known words */
if (tokenPtr->numComponents == 1
&& tokenPtr[1].type == TCL_TOKEN_TEXT
&& TclWordKnownAtCompileTime(tokenPtr, literal)) {
Tcl_ListObjAppendElement(NULL, litList, literal);
numLiterals++;
lastWas = OT_LITERAL;
parsePtr->numTokens = wordIndex;
break;
}
Tcl_DecrRefCount(literal);
}
lastWas = OT_TOKENS;
|
| ︙ | | |