diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2003-09-12 23:55:32 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2003-09-12 23:55:32 (GMT) |
commit | da60f636030ff5e28efdfe34eb534c9dd46e2fb3 (patch) | |
tree | 2f2c7e65505a410bb72e9cc37de0a6baab73939f /generic/tclParseExpr.c | |
parent | 15cd6e14858186b0fc6748418f0c92ee5c1495ab (diff) | |
download | tcl-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.c | 90 |
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 '/': |