From 157519d722cefbc98c7aea754dd4ecb6270e426d Mon Sep 17 00:00:00 2001 From: John Beard Date: Wed, 28 Nov 2018 14:40:33 +0000 Subject: [PATCH] Libeval: leading + is a sign, not an operator Due to (presumably) a different lemon version, there are some formatting changes in the grammar, and some manual debug left in has been removed. --- common/libeval/grammar.c | 530 ++++++++----------- common/libeval/grammar.lemon | 1 + qa/common/libeval/test_numeric_evaluator.cpp | 5 +- 3 files changed, 234 insertions(+), 302 deletions(-) diff --git a/common/libeval/grammar.c b/common/libeval/grammar.c index 4551f2d38f..47c649a14b 100644 --- a/common/libeval/grammar.c +++ b/common/libeval/grammar.c @@ -1,92 +1,63 @@ -/* -** 2000-05-29 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Driver template for the LEMON parser generator. -** -** The "lemon" program processes an LALR(1) input grammar file, then uses -** this template to construct a parser. The "lemon" program inserts text -** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the -** interstitial "-" characters) contained in this template is changed into -** the value of the %name directive from the grammar. Otherwise, the content -** of this template is copied straight through into the generate parser -** source file. -** -** The following is the concatenation of all %include directives from the -** input grammar file: +/* Driver template for the LEMON parser generator. +** The author disclaims copyright to this source code. */ +/* First off, code is included that follows the "include" declaration +** in the input grammar file. */ #include -/************ Begin %include sections from the grammar ************************/ #line 28 "grammar.lemon" #include #include -#line 32 "grammar.c" -/**************** End of %include directives **********************************/ -/* These constants specify the various numeric values for terminal symbols -** in a format understandable to "makeheaders". This section is blank unless -** "lemon" is run with the "-m" command-line option. -***************** Begin makeheaders token definitions *************************/ -/**************** End makeheaders token definitions ***************************/ - -/* The next sections is a series of control #defines. +#line 12 "grammar.c" +/* Next is all token values, in a form suitable for use by makeheaders. +** This section will be null unless lemon is run with the -m switch. +*/ +/* +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands. +** +** Each symbol here is a terminal symbol in the grammar. +*/ +/* Make sure the INTERFACE macro is defined. +*/ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/* The next thing included is series of defines which control ** various aspects of the generated parser. -** YYCODETYPE is the data type used to store the integer codes -** that represent terminal and non-terminal symbols. -** "unsigned char" is used if there are fewer than -** 256 symbols. Larger types otherwise. -** YYNOCODE is a number of type YYCODETYPE that is not used for -** any terminal or nonterminal symbol. +** YYCODETYPE is the data type used for storing terminal +** and nonterminal numbers. "unsigned char" is +** used if there are fewer than 250 terminals +** and nonterminals. "int" is used otherwise. +** YYNOCODE is a number of type YYCODETYPE which corresponds +** to no legal terminal or nonterminal number. This +** number is used to fill in empty slots of the hash +** table. ** YYFALLBACK If defined, this indicates that one or more tokens -** (also known as: "terminal symbols") have fall-back -** values which should be used if the original symbol -** would not parse. This permits keywords to sometimes -** be used as identifiers, for example. -** YYACTIONTYPE is the data type used for "action codes" - numbers -** that indicate what to do in response to the next -** token. -** ParseTOKENTYPE is the data type used for minor type for terminal -** symbols. Background: A "minor type" is a semantic -** value associated with a terminal or non-terminal -** symbols. For example, for an "ID" terminal symbol, -** the minor type might be the name of the identifier. -** Each non-terminal can have a different minor type. -** Terminal symbols all have the same minor type, though. -** This macros defines the minor type for terminal -** symbols. -** YYMINORTYPE is the data type used for all minor types. +** have fall-back values which should be used if the +** original value of the token will not parse. +** YYACTIONTYPE is the data type used for storing terminal +** and nonterminal numbers. "unsigned char" is +** used if there are fewer than 250 rules and +** states combined. "int" is used otherwise. +** ParseTOKENTYPE is the data type used for minor tokens given +** directly to the parser from the tokenizer. +** YYMINORTYPE is the data type used for all minor tokens. ** This is typically a union of many types, one of ** which is ParseTOKENTYPE. The entry in the union -** for terminal symbols is called "yy0". +** for base tokens is called "yy0". ** YYSTACKDEPTH is the maximum depth of the parser's stack. If ** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument ** ParseARG_PDECL A parameter declaration for the %extra_argument ** ParseARG_STORE Code to store %extra_argument into yypParser ** ParseARG_FETCH Code to extract %extra_argument from yypParser -** YYERRORSYMBOL is the code number of the error symbol. If not -** defined, then do no error processing. ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar -** YY_MAX_SHIFT Maximum value for shift actions -** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions -** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions -** YY_MIN_REDUCE Maximum value for reduce actions -** YY_ERROR_ACTION The yy_action[] code for syntax error -** YY_ACCEPT_ACTION The yy_action[] code for accept -** YY_NO_ACTION The yy_action[] code for no-op +** YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. */ -#ifndef INTERFACE -# define INTERFACE 1 -#endif -/************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned char #define YYNOCODE 19 #define YYACTIONTYPE unsigned char @@ -99,20 +70,14 @@ typedef union { #define YYSTACKDEPTH 100 #endif #define ParseARG_SDECL NUMERIC_EVALUATOR* pEval ; -#define ParseARG_PDECL , NUMERIC_EVALUATOR* pEval -#define ParseARG_FETCH NUMERIC_EVALUATOR* pEval = yypParser->pEval +#define ParseARG_PDECL , NUMERIC_EVALUATOR* pEval +#define ParseARG_FETCH NUMERIC_EVALUATOR* pEval = yypParser->pEval #define ParseARG_STORE yypParser->pEval = pEval -#define YYNSTATE 16 -#define YYNRULE 16 -#define YY_MAX_SHIFT 15 -#define YY_MIN_SHIFTREDUCE 26 -#define YY_MAX_SHIFTREDUCE 41 -#define YY_MIN_REDUCE 42 -#define YY_MAX_REDUCE 57 -#define YY_ERROR_ACTION 58 -#define YY_ACCEPT_ACTION 59 -#define YY_NO_ACTION 60 -/************* End control #defines *******************************************/ +#define YYNSTATE 28 +#define YYNRULE 17 +#define YY_NO_ACTION (YYNSTATE+YYNRULE+2) +#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) +#define YY_ERROR_ACTION (YYNSTATE+YYNRULE) /* The yyzerominor constant is used to initialize instances of ** YYMINORTYPE objects to zero. */ @@ -139,20 +104,16 @@ static const YYMINORTYPE yyzerominor = { 0 }; ** Suppose the action integer is N. Then the action is determined as ** follows ** -** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead +** 0 <= N < YYNSTATE Shift N. That is, push the lookahead ** token onto the stack and goto state N. ** -** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then -** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. +** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. ** -** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE -** and YY_MAX_REDUCE - -** N == YY_ERROR_ACTION A syntax error has occurred. +** N == YYNSTATE+YYNRULE A syntax error has occurred. ** -** N == YY_ACCEPT_ACTION The parser accepts its input. +** N == YYNSTATE+YYNRULE+1 The parser accepts its input. ** -** N == YY_NO_ACTION No such action. Denotes unused +** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused ** slots in the yy_action[] table. ** ** The action table is constructed as a single large table named yy_action[]. @@ -181,48 +142,47 @@ static const YYMINORTYPE yyzerominor = { 0 }; ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. -** -*********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (51) +*/ +#define YY_ACTTAB_COUNT (58) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 31, 8, 7, 33, 5, 6, 30, 42, 15, 10, - /* 10 */ 15, 11, 4, 12, 4, 40, 29, 32, 2, 32, - /* 20 */ 2, 8, 7, 33, 5, 6, 15, 28, 9, 41, - /* 30 */ 4, 39, 13, 14, 29, 32, 2, 44, 3, 8, - /* 40 */ 7, 33, 5, 6, 59, 1, 27, 9, 33, 5, - /* 50 */ 6, + /* 0 */ 24, 9, 8, 23, 6, 7, 25, 28, 17, 16, + /* 10 */ 17, 4, 5, 4, 5, 3, 26, 22, 2, 22, + /* 20 */ 2, 9, 8, 23, 6, 7, 47, 17, 15, 19, + /* 30 */ 4, 5, 21, 20, 47, 26, 22, 2, 27, 10, + /* 40 */ 9, 8, 23, 6, 7, 46, 1, 18, 10, 23, + /* 50 */ 6, 7, 47, 47, 14, 13, 12, 11, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 3, 4, 5, 6, 7, 8, 9, 0, 1, 17, - /* 10 */ 1, 17, 5, 17, 5, 17, 9, 10, 11, 10, - /* 20 */ 11, 4, 5, 6, 7, 8, 1, 16, 17, 12, - /* 30 */ 5, 17, 17, 17, 9, 10, 11, 18, 2, 4, - /* 40 */ 5, 6, 7, 8, 14, 15, 16, 17, 6, 7, - /* 50 */ 8, + /* 10 */ 1, 4, 5, 4, 5, 2, 9, 10, 11, 10, + /* 20 */ 11, 4, 5, 6, 7, 8, 18, 1, 17, 12, + /* 30 */ 4, 5, 17, 17, 18, 9, 10, 11, 16, 17, + /* 40 */ 4, 5, 6, 7, 8, 14, 15, 16, 17, 6, + /* 50 */ 7, 8, 18, 18, 17, 17, 17, 17, }; #define YY_SHIFT_USE_DFLT (-4) -#define YY_SHIFT_COUNT (15) +#define YY_SHIFT_COUNT (17) #define YY_SHIFT_MIN (-3) -#define YY_SHIFT_MAX (42) +#define YY_SHIFT_MAX (43) static const signed char yy_shift_ofst[] = { - /* 0 */ 25, 7, 9, 9, 9, 9, 9, 9, 9, -3, - /* 10 */ 17, 35, 42, 42, 42, 36, + /* 0 */ 26, 7, 9, 9, 9, 9, 9, 9, 9, 9, + /* 10 */ -3, 17, 36, 43, 43, 43, 43, 13, }; #define YY_REDUCE_USE_DFLT (-9) -#define YY_REDUCE_COUNT (8) +#define YY_REDUCE_COUNT (9) #define YY_REDUCE_MIN (-8) -#define YY_REDUCE_MAX (30) +#define YY_REDUCE_MAX (40) static const signed char yy_reduce_ofst[] = { - /* 0 */ 30, 11, -8, -6, -4, -2, 14, 15, 16, + /* 0 */ 31, 22, 40, 39, 38, 37, 16, 15, 11, -8, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, - /* 10 */ 58, 52, 50, 54, 53, 51, + /* 0 */ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, + /* 10 */ 45, 45, 39, 37, 36, 41, 40, 38, 29, 44, + /* 20 */ 43, 42, 34, 35, 33, 32, 31, 30, }; -/********** End of lemon-generated parsing tables *****************************/ -/* The next table maps tokens (terminal symbols) into fallback tokens. -** If a construct like the following: +/* The next table maps tokens into fallback tokens. If a construct +** like the following: ** ** %fallback ID X Y Z. ** @@ -230,10 +190,6 @@ static const YYACTIONTYPE yy_default[] = { ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and ** the parse is retried before an error is thrown. -** -** This feature can be used, for example, to cause some keywords in a language -** to revert to identifiers if they keyword does not apply in the context where -** it appears. */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { @@ -251,13 +207,9 @@ static const YYCODETYPE yyFallback[] = { ** + The semantic value stored at this level of the stack. This is ** the information used by the action routines in the grammar. ** It is sometimes called the "minor" token. -** -** After the "shift" half of a SHIFTREDUCE action, the stateno field -** actually contains the reduce action for the second half of the -** SHIFTREDUCE. */ struct yyStackEntry { - YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */ + YYACTIONTYPE stateno; /* The state-number */ YYCODETYPE major; /* The major token value. This is the code ** number for the token at this stack level */ YYMINORTYPE minor; /* The user-supplied minor token value. This @@ -340,13 +292,14 @@ static const char *const yyRuleName[] = { /* 6 */ "expr ::= VALUE", /* 7 */ "expr ::= expr UNIT", /* 8 */ "expr ::= MINUS expr", - /* 9 */ "expr ::= VAR", - /* 10 */ "expr ::= VAR ASSIGN expr", - /* 11 */ "expr ::= expr PLUS expr", - /* 12 */ "expr ::= expr MINUS expr", - /* 13 */ "expr ::= expr MULT expr", - /* 14 */ "expr ::= expr DIVIDE expr", - /* 15 */ "expr ::= PARENL expr PARENR", + /* 9 */ "expr ::= PLUS expr", + /* 10 */ "expr ::= VAR", + /* 11 */ "expr ::= VAR ASSIGN expr", + /* 12 */ "expr ::= expr PLUS expr", + /* 13 */ "expr ::= expr MINUS expr", + /* 14 */ "expr ::= expr MULT expr", + /* 15 */ "expr ::= expr DIVIDE expr", + /* 16 */ "expr ::= PARENL expr PARENR", }; #endif /* NDEBUG */ @@ -374,15 +327,6 @@ static void yyGrowStack(yyParser *p){ } #endif -/* Datatype of the argument to the memory allocated passed as the -** second argument to ParseAlloc() below. This can be changed by -** putting an appropriate #define in the %include section of the input -** grammar. -*/ -#ifndef YYMALLOCARGTYPE -# define YYMALLOCARGTYPE size_t -#endif - /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like @@ -395,9 +339,9 @@ static void yyGrowStack(yyParser *p){ ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ -void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ +void *ParseAlloc(void *(*mallocProc)(size_t)){ yyParser *pParser; - pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); + pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); if( pParser ){ pParser->yyidx = -1; #ifdef YYTRACKMAXSTACKDEPTH @@ -412,12 +356,10 @@ void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ return pParser; } -/* The following function deletes the "minor type" or semantic value -** associated with a symbol. The symbol can be either a terminal -** or nonterminal. "yymajor" is the symbol code, and "yypminor" is -** a pointer to the value to be deleted. The code used to do the -** deletions is derived from the %destructor and/or %token_destructor -** directives of the input grammar. +/* The following function deletes the value associated with a +** symbol. The symbol can be either a terminal or nonterminal. +** "yymajor" is the symbol code, and "yypminor" is a pointer to +** the value. */ static void yy_destructor( yyParser *yypParser, /* The parser */ @@ -433,11 +375,9 @@ static void yy_destructor( ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those - ** which appear on the RHS of the rule, but which are *not* used + ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ -/********* Begin destructor definitions ***************************************/ -/********* End destructor definitions *****************************************/ default: break; /* If no destructor action specified: do nothing */ } } @@ -447,37 +387,45 @@ static void yy_destructor( ** ** If there is a destructor routine associated with the token which ** is popped from the stack, then call it. +** +** Return the major token number for the symbol popped. */ -static void yy_pop_parser_stack(yyParser *pParser){ - yyStackEntry *yytos; - assert( pParser->yyidx>=0 ); - yytos = &pParser->yystack[pParser->yyidx--]; +static int yy_pop_parser_stack(yyParser *pParser){ + YYCODETYPE yymajor; + yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; + + if( pParser->yyidx<0 ) return 0; #ifndef NDEBUG - if( yyTraceFILE ){ + if( yyTraceFILE && pParser->yyidx>=0 ){ fprintf(yyTraceFILE,"%sPopping %s\n", yyTracePrompt, yyTokenName[yytos->major]); } #endif - yy_destructor(pParser, yytos->major, &yytos->minor); + yymajor = yytos->major; + yy_destructor(pParser, yymajor, &yytos->minor); + pParser->yyidx--; + return yymajor; } /* -** Deallocate and destroy a parser. Destructors are called for +** Deallocate and destroy a parser. Destructors are all called for ** all stack elements before shutting the parser down. ** -** If the YYPARSEFREENEVERNULL macro exists (for example because it -** is defined in a %include section of the input grammar) then it is -** assumed that the input pointer is never NULL. +** Inputs: +**
    +**
  • A pointer to the parser. This should be a pointer +** obtained from ParseAlloc. +**
  • A pointer to a function used to reclaim memory obtained +** from malloc. +**
*/ void ParseFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ ){ yyParser *pParser = (yyParser*)p; -#ifndef YYPARSEFREENEVERNULL if( pParser==0 ) return; -#endif while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); #if YYSTACKDEPTH<=0 free(pParser->yystack); @@ -498,6 +446,10 @@ int ParseStackPeak(void *p){ /* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead. If it is, return the action, otherwise +** return YY_NO_ACTION. */ static int yy_find_shift_action( yyParser *pParser, /* The parser */ @@ -506,64 +458,63 @@ static int yy_find_shift_action( int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - if( stateno>=YY_MIN_REDUCE ) return stateno; - assert( stateno <= YY_SHIFT_COUNT ); - do{ - i = yy_shift_ofst[stateno]; - if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno]; - assert( iLookAhead!=YYNOCODE ); - i += iLookAhead; - if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ - if( iLookAhead>0 ){ + if( stateno>YY_SHIFT_COUNT + || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ + return yy_default[stateno]; + } + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + if( iLookAhead>0 ){ #ifdef YYFALLBACK - YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", - yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); - } -#endif - assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ - iLookAhead = iFallback; - continue; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } +#endif + return yy_find_shift_action(pParser, iFallback); + } #endif #ifdef YYWILDCARD - { - int j = i - iLookAhead + YYWILDCARD; - if( + { + int j = i - iLookAhead + YYWILDCARD; + if( #if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && + j>=0 && #endif #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j %s\n", - yyTracePrompt, yyTokenName[iLookAhead], - yyTokenName[YYWILDCARD]); - } -#endif /* NDEBUG */ - return yy_action[j]; + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); } +#endif /* NDEBUG */ + return yy_action[j]; } -#endif /* YYWILDCARD */ } - return yy_default[stateno]; - }else{ - return yy_action[i]; +#endif /* YYWILDCARD */ } - }while(1); + return yy_default[stateno]; + }else{ + return yy_action[i]; + } } /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead. If it is, return the action, otherwise +** return YY_NO_ACTION. */ static int yy_find_reduce_action( int stateno, /* Current state number */ @@ -606,31 +557,9 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){ while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ -/******** Begin %stack_overflow code ******************************************/ -/******** End %stack_overflow code ********************************************/ ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ } -/* -** Print tracing information for a SHIFT action -*/ -#ifndef NDEBUG -static void yyTraceShift(yyParser *yypParser, int yyNewState){ - if( yyTraceFILE ){ - if( yyNewStateyystack[yypParser->yyidx].major], - yyNewState); - }else{ - fprintf(yyTraceFILE,"%sShift '%s'\n", - yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]); - } - } -} -#else -# define yyTraceShift(X,Y) -#endif - /* ** Perform a shift action. */ @@ -665,7 +594,16 @@ static void yy_shift( yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->major = (YYCODETYPE)yyMajor; yytos->minor = *yypMinor; - yyTraceShift(yypParser, yyNewState); +#ifndef NDEBUG + if( yyTraceFILE && yypParser->yyidx>0 ){ + int i; + fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); + fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); + for(i=1; i<=yypParser->yyidx; i++) + fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); + fprintf(yyTraceFILE,"\n"); + } +#endif } /* The following table contains information about every rule that @@ -684,6 +622,7 @@ static const struct { { 17, 1 }, { 17, 2 }, { 17, 2 }, + { 17, 2 }, { 17, 1 }, { 17, 3 }, { 17, 3 }, @@ -713,13 +652,29 @@ static void yy_reduce( #ifndef NDEBUG if( yyTraceFILE && yyruleno>=0 && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ - yysize = yyRuleInfo[yyruleno].nrhs; - fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, - yyRuleName[yyruleno], yymsp[-yysize].stateno); + fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, + yyRuleName[yyruleno]); } #endif /* NDEBUG */ + + /* Silence complaints from purify about yygotominor being uninitialized + ** in some cases when it is copied into the stack after the following + ** switch. yygotominor is uninitialized when a rule reduces that does + ** not set the value of its left-hand side nonterminal. Leaving the + ** value of the nonterminal uninitialized is utterly harmless as long + ** as the value is never used. So really the only thing this code + ** accomplishes is to quieten purify. + ** + ** 2007-01-16: The wireshark project (www.wireshark.org) reports that + ** without this code, their parser segfaults. I'm not sure what there + ** parser is doing to make this happen. This is the second bug report + ** from wireshark this week. Clearly they are stressing Lemon in ways + ** that it has not been previously stressed... (SQLite ticket #2172) + */ + /*memset(&yygotominor, 0, sizeof(yygotominor));*/ yygotominor = yyzerominor; + switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: @@ -729,59 +684,63 @@ static void yy_reduce( ** #line ** break; */ -/********** Begin reduce actions **********************************************/ case 4: /* stmt ::= expr ENDS */ #line 49 "grammar.lemon" { pEval->parseSetResult(yymsp[-1].minor.yy0.valid ? yymsp[-1].minor.yy0.dValue : NAN); } -#line 737 "grammar.c" +#line 691 "grammar.c" break; case 5: /* stmt ::= expr SEMCOL */ #line 50 "grammar.lemon" { pEval->parseSetResult(NAN); } -#line 742 "grammar.c" +#line 696 "grammar.c" break; case 6: /* expr ::= VALUE */ #line 52 "grammar.lemon" { yygotominor.yy0.dValue = yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=true; } -#line 747 "grammar.c" +#line 701 "grammar.c" break; case 7: /* expr ::= expr UNIT */ #line 53 "grammar.lemon" { yygotominor.yy0.dValue = yymsp[-1].minor.yy0.dValue * yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[-1].minor.yy0.valid; } -#line 752 "grammar.c" +#line 706 "grammar.c" break; case 8: /* expr ::= MINUS expr */ #line 54 "grammar.lemon" { yygotominor.yy0.dValue = -yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } -#line 757 "grammar.c" +#line 711 "grammar.c" break; - case 9: /* expr ::= VAR */ + case 9: /* expr ::= PLUS expr */ #line 55 "grammar.lemon" -{ yygotominor.yy0.dValue = pEval->GetVar(yymsp[0].minor.yy0.text); yygotominor.yy0.valid=true; } -#line 762 "grammar.c" +{ yygotominor.yy0.dValue = yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } +#line 716 "grammar.c" break; - case 10: /* expr ::= VAR ASSIGN expr */ + case 10: /* expr ::= VAR */ #line 56 "grammar.lemon" -{ pEval->SetVar(yymsp[-2].minor.yy0.text, yymsp[0].minor.yy0.dValue); yygotominor.yy0.dValue = yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=false; } -#line 767 "grammar.c" +{ yygotominor.yy0.dValue = pEval->GetVar(yymsp[0].minor.yy0.text); yygotominor.yy0.valid=true; } +#line 721 "grammar.c" break; - case 11: /* expr ::= expr PLUS expr */ + case 11: /* expr ::= VAR ASSIGN expr */ #line 57 "grammar.lemon" -{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue + yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } -#line 772 "grammar.c" +{ pEval->SetVar(yymsp[-2].minor.yy0.text, yymsp[0].minor.yy0.dValue); yygotominor.yy0.dValue = yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=false; } +#line 726 "grammar.c" break; - case 12: /* expr ::= expr MINUS expr */ + case 12: /* expr ::= expr PLUS expr */ #line 58 "grammar.lemon" -{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue - yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } -#line 777 "grammar.c" +{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue + yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } +#line 731 "grammar.c" break; - case 13: /* expr ::= expr MULT expr */ + case 13: /* expr ::= expr MINUS expr */ #line 59 "grammar.lemon" -{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue * yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } -#line 782 "grammar.c" +{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue - yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } +#line 736 "grammar.c" break; - case 14: /* expr ::= expr DIVIDE expr */ + case 14: /* expr ::= expr MULT expr */ #line 60 "grammar.lemon" +{ yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue * yymsp[0].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } +#line 741 "grammar.c" + break; + case 15: /* expr ::= expr DIVIDE expr */ +#line 61 "grammar.lemon" { if (yymsp[0].minor.yy0.dValue != 0.0) { yygotominor.yy0.dValue = yymsp[-2].minor.yy0.dValue / yymsp[0].minor.yy0.dValue; @@ -789,12 +748,12 @@ static void yy_reduce( else pEval->parseError("Div by zero"); yygotominor.yy0.valid=yymsp[0].minor.yy0.valid; } -#line 793 "grammar.c" +#line 752 "grammar.c" break; - case 15: /* expr ::= PARENL expr PARENR */ -#line 67 "grammar.lemon" + case 16: /* expr ::= PARENL expr PARENR */ +#line 68 "grammar.lemon" { yygotominor.yy0.dValue = yymsp[-1].minor.yy0.dValue; yygotominor.yy0.valid=yymsp[-1].minor.yy0.valid; } -#line 798 "grammar.c" +#line 757 "grammar.c" break; default: /* (0) main ::= in */ yytestcase(yyruleno==0); @@ -802,16 +761,14 @@ static void yy_reduce( /* (2) in ::= in stmt */ yytestcase(yyruleno==2); /* (3) stmt ::= ENDS */ yytestcase(yyruleno==3); break; -/********** End reduce actions ************************************************/ }; - assert( yyruleno>=0 && yyrulenoyyidx -= yysize; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); - if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; - /* If the reduce action popped at least + if( yyact < YYNSTATE ){ +#ifdef NDEBUG + /* If we are not debugging and the reduce action popped at least ** one element off the stack, then we can push the new element back ** onto the stack here, and skip the stack overflow test in yy_shift(). ** That gives a significant speed improvement. */ @@ -821,12 +778,13 @@ static void yy_reduce( yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yymsp->minor = yygotominor; - yyTraceShift(yypParser, yyact); - }else{ + }else +#endif + { yy_shift(yypParser,yyact,yygoto,&yygotominor); } }else{ - assert( yyact == YY_ACCEPT_ACTION ); + assert( yyact == YYNSTATE + YYNRULE + 1 ); yy_accept(yypParser); } } @@ -847,8 +805,6 @@ static void yy_parse_failed( while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ -/************ Begin %parse_failure code ***************************************/ -/************ End %parse_failure code *****************************************/ ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } #endif /* YYNOERRORRECOVERY */ @@ -863,12 +819,10 @@ static void yy_syntax_error( ){ ParseARG_FETCH; #define TOKEN (yyminor.yy0) -/************ Begin %syntax_error code ****************************************/ #line 33 "grammar.lemon" pEval->parseError("Syntax error"); -#line 871 "grammar.c" -/************ End %syntax_error code ******************************************/ +#line 826 "grammar.c" ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } @@ -887,12 +841,10 @@ static void yy_accept( while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser accepts */ -/*********** Begin %parse_accept code *****************************************/ #line 37 "grammar.lemon" pEval->parseOk(); -#line 895 "grammar.c" -/*********** End %parse_accept code *******************************************/ +#line 848 "grammar.c" ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } @@ -923,9 +875,7 @@ void Parse( ){ YYMINORTYPE yyminorunion; int yyact; /* The parser action. */ -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) int yyendofinput; /* True if we are at the end of input */ -#endif #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif @@ -946,34 +896,26 @@ void Parse( yypParser->yyerrcnt = -1; yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; -#ifndef NDEBUG - if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n", - yyTracePrompt); - } -#endif } yyminorunion.yy0 = yyminor; -#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) yyendofinput = (yymajor==0); -#endif ParseARG_STORE; #ifndef NDEBUG if( yyTraceFILE ){ - fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); } #endif do{ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); - if( yyact <= YY_MAX_SHIFTREDUCE ){ - if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + if( yyactyyerrcnt--; yymajor = YYNOCODE; - }else if( yyact <= YY_MAX_REDUCE ){ - yy_reduce(yypParser,yyact-YY_MIN_REDUCE); + }else if( yyact < YYNSTATE + YYNRULE ){ + yy_reduce(yypParser,yyact-YYNSTATE); }else{ assert( yyact == YY_ERROR_ACTION ); #ifdef YYERRORSYMBOL @@ -1023,7 +965,7 @@ void Parse( yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yystack[yypParser->yyidx].stateno, - YYERRORSYMBOL)) >= YY_MIN_REDUCE + YYERRORSYMBOL)) >= YYNSTATE ){ yy_pop_parser_stack(yypParser); } @@ -1073,15 +1015,5 @@ void Parse( #endif } }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); -#ifndef NDEBUG - if( yyTraceFILE ){ - int i; - fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); - for(i=1; i<=yypParser->yyidx; i++) - fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ', - yyTokenName[yypParser->yystack[i].major]); - fprintf(yyTraceFILE,"]\n"); - } -#endif return; } diff --git a/common/libeval/grammar.lemon b/common/libeval/grammar.lemon index b5a7a22fb3..44516005c1 100644 --- a/common/libeval/grammar.lemon +++ b/common/libeval/grammar.lemon @@ -52,6 +52,7 @@ stmt ::= expr SEMCOL. { pEval->parseSetResult(NAN); } expr(A) ::= VALUE(B). { A.dValue = B.dValue; A.valid=true; } expr(A) ::= expr(B) UNIT(C). { A.dValue = B.dValue * C.dValue; A.valid=B.valid; } expr(A) ::= MINUS expr(B). { A.dValue = -B.dValue; A.valid=B.valid; } +expr(A) ::= PLUS expr(B). { A.dValue = B.dValue; A.valid=B.valid; } expr(A) ::= VAR(B). { A.dValue = pEval->GetVar(B.text); A.valid=true; } expr(A) ::= VAR(B) ASSIGN expr(C). { pEval->SetVar(B.text, C.dValue); A.dValue = C.dValue; A.valid=false; } expr(A) ::= expr(B) PLUS expr(C). { A.dValue = B.dValue + C.dValue; A.valid=C.valid; } diff --git a/qa/common/libeval/test_numeric_evaluator.cpp b/qa/common/libeval/test_numeric_evaluator.cpp index f6edec29b4..b550e6c1c1 100644 --- a/qa/common/libeval/test_numeric_evaluator.cpp +++ b/qa/common/libeval/test_numeric_evaluator.cpp @@ -143,8 +143,8 @@ static const std::vector eval_cases_valid = { { "(1)", "1" }, // Parens affect precedence { "-(1 + (2 - 4)) * 20.8 / 2", "10.4" }, - // Unary addition, not a leading operator - //{ "+2 - 1", "1" } // TODO: This does not come out as valid + // Unary addition is a sign, not a leading operator + { "+2 - 1", "1" }, // Unknown vars are 0.0 { "1 + unknown", "1" }, // Set var in-string @@ -187,7 +187,6 @@ static const std::vector eval_cases_invalid = { // Trailing operator { "1+" }, // Leading operator - { "+2 + 1" }, { "*2 + 1" }, // No operator { "1 2" },