summaryrefslogtreecommitdiffstats
path: root/generic/tclParseExpr.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2003-09-12 23:55:32 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2003-09-12 23:55:32 (GMT)
commitda60f636030ff5e28efdfe34eb534c9dd46e2fb3 (patch)
tree2f2c7e65505a410bb72e9cc37de0a6baab73939f /generic/tclParseExpr.c
parent15cd6e14858186b0fc6748418f0c92ee5c1495ab (diff)
downloadtcl-da60f636030ff5e28efdfe34eb534c9dd46e2fb3.zip
tcl-da60f636030ff5e28efdfe34eb534c9dd46e2fb3.tar.gz
tcl-da60f636030ff5e28efdfe34eb534c9dd46e2fb3.tar.bz2
TIP#123 Implementation based on work by Arjen Markus. [Patch 655176]
Diffstat (limited to 'generic/tclParseExpr.c')
-rw-r--r--generic/tclParseExpr.c90
1 files changed, 83 insertions, 7 deletions
diff --git a/generic/tclParseExpr.c b/generic/tclParseExpr.c
index bb88159..a0c0316 100644
--- a/generic/tclParseExpr.c
+++ b/generic/tclParseExpr.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclParseExpr.c,v 1.17 2003/02/16 01:36:32 msofer Exp $
+ * RCS: @(#) $Id: tclParseExpr.c,v 1.18 2003/09/12 23:55:34 dkf Exp $
*/
#include "tclInt.h"
@@ -130,6 +130,12 @@ typedef struct ParseInfo {
#define STRNEQ 35
/*
+ * Exponentiation operator:
+ */
+
+#define EXPON 36
+
+/*
* Mapping from lexemes to strings; used for debugging messages. These
* entries must match the order and number of the lexeme definitions above.
*/
@@ -140,7 +146,7 @@ static char *lexemeStrings[] = {
"*", "/", "%", "+", "-",
"<<", ">>", "<", ">", "<=", ">=", "==", "!=",
"&", "^", "|", "&&", "||", "?", ":",
- "!", "~", "eq", "ne",
+ "!", "~", "eq", "ne", "**"
};
/*
@@ -164,6 +170,7 @@ static int ParseMultiplyExpr _ANSI_ARGS_((ParseInfo *infoPtr));
static int ParsePrimaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
static int ParseRelationalExpr _ANSI_ARGS_((ParseInfo *infoPtr));
static int ParseShiftExpr _ANSI_ARGS_((ParseInfo *infoPtr));
+static int ParseExponentialExpr _ANSI_ARGS_((ParseInfo *infoPtr));
static int ParseUnaryExpr _ANSI_ARGS_((ParseInfo *infoPtr));
static void PrependSubExprTokens _ANSI_ARGS_((CONST char *op,
int opBytes, CONST char *src, int srcBytes,
@@ -976,7 +983,7 @@ ParseAddExpr(infoPtr)
* ParseMultiplyExpr --
*
* This procedure parses a Tcl multiply expression:
- * multiplyExpr ::= unaryExpr {('*' | '/' | '%') unaryExpr}
+ * multiplyExpr ::= exponentialExpr {('*' | '/' | '%') exponentialExpr}
*
* Results:
* The return value is TCL_OK on a successful parse and TCL_ERROR
@@ -1004,7 +1011,7 @@ ParseMultiplyExpr(infoPtr)
srcStart = infoPtr->start;
firstIndex = parsePtr->numTokens;
- code = ParseUnaryExpr(infoPtr);
+ code = ParseExponentialExpr(infoPtr);
if (code != TCL_OK) {
return code;
}
@@ -1016,7 +1023,7 @@ ParseMultiplyExpr(infoPtr)
if (code != TCL_OK) {
return code;
}
- code = ParseUnaryExpr(infoPtr);
+ code = ParseExponentialExpr(infoPtr);
if (code != TCL_OK) {
return code;
}
@@ -1035,6 +1042,69 @@ ParseMultiplyExpr(infoPtr)
/*
*----------------------------------------------------------------------
*
+ * ParseExponentialExpr --
+ *
+ * This procedure parses a Tcl exponential expression:
+ * exponentialExpr ::= unaryExpr {'**' unaryExpr}
+ *
+ * Results:
+ * The return value is TCL_OK on a successful parse and TCL_ERROR
+ * on failure. If TCL_ERROR is returned, then the interpreter's result
+ * contains an error message.
+ *
+ * Side effects:
+ * If there is insufficient space in parsePtr to hold all the
+ * information about the subexpression, then additional space is
+ * malloc-ed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ParseExponentialExpr(infoPtr)
+ ParseInfo *infoPtr; /* Holds the parse state for the
+ * expression being parsed. */
+{
+ Tcl_Parse *parsePtr = infoPtr->parsePtr;
+ int firstIndex, lexeme, code;
+ CONST char *srcStart, *operator;
+
+ HERE("exponentiateExpr", 12);
+ srcStart = infoPtr->start;
+ firstIndex = parsePtr->numTokens;
+
+ code = ParseUnaryExpr(infoPtr);
+ if (code != TCL_OK) {
+ return code;
+ }
+
+ lexeme = infoPtr->lexeme;
+ while (lexeme == EXPON) {
+ operator = infoPtr->start;
+ code = GetLexeme(infoPtr); /* skip over ** */
+ if (code != TCL_OK) {
+ return code;
+ }
+ code = ParseUnaryExpr(infoPtr);
+ if (code != TCL_OK) {
+ return code;
+ }
+
+ /*
+ * Generate tokens for the subexpression and ** operator.
+ */
+
+ PrependSubExprTokens(operator, 2, srcStart,
+ (infoPtr->prevEnd - srcStart), firstIndex, infoPtr);
+ lexeme = infoPtr->lexeme;
+ }
+ return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
* ParseUnaryExpr --
*
* This procedure parses a Tcl unary expression:
@@ -1062,7 +1132,7 @@ ParseUnaryExpr(infoPtr)
int firstIndex, lexeme, code;
CONST char *srcStart, *operator;
- HERE("unaryExpr", 12);
+ HERE("unaryExpr", 13);
srcStart = infoPtr->start;
firstIndex = parsePtr->numTokens;
@@ -1132,7 +1202,7 @@ ParsePrimaryExpr(infoPtr)
* We simply recurse on parenthesized subexpressions.
*/
- HERE("primaryExpr", 13);
+ HERE("primaryExpr", 14);
lexeme = infoPtr->lexeme;
if (lexeme == OPEN_PAREN) {
code = GetLexeme(infoPtr); /* skip over the '(' */
@@ -1681,6 +1751,12 @@ GetLexeme(infoPtr)
case '*':
infoPtr->lexeme = MULT;
+ if ((infoPtr->lastChar - src)>1 && src[1]=='*') {
+ infoPtr->lexeme = EXPON;
+ infoPtr->size = 2;
+ infoPtr->next = src+2;
+ parsePtr->term = infoPtr->next;
+ }
return TCL_OK;
case '/':