Bläddra i källkod

math: Reject unexpected expression input explicitly

Switch to C++ exceptions for lexer/parser error handling.
Teach the lexer/parser to fail on unexpected input.
Daniel Franke 7 år sedan
förälder
incheckning
7c4c13ffef

+ 60 - 50
Source/LexerParser/cmExprLexer.cxx

@@ -548,8 +548,8 @@ static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
 	yyg->yy_hold_char = *yy_cp; \
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 15
-#define YY_END_OF_BUFFER 16
+#define YY_NUM_RULES 17
+#define YY_END_OF_BUFFER 18
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -557,29 +557,29 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static const flex_int16_t yy_accept[23] =
+static const flex_int16_t yy_accept[25] =
     {   0,
-        0,    0,   16,   15,    6,    8,   13,   14,    4,    2,
-        3,    5,    1,   15,   15,    9,    7,   10,    1,   11,
-       12,    0
+        0,    0,   18,   16,    1,   17,    7,    9,   14,   15,
+        5,    3,    4,    6,    2,   16,   16,   10,    8,   11,
+        2,   12,   13,    0
     } ;
 
 static const YY_CHAR yy_ec[256] =
     {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    1,    1,    1,    4,    5,    1,    6,
+        7,    8,    9,    1,   10,    1,   11,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,   12,    1,    1,   13,
+        1,   14,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    2,    3,    1,    4,
-        5,    6,    7,    1,    8,    1,    9,   10,   10,   10,
-       10,   10,   10,   10,   10,   10,   10,    1,    1,   11,
-        1,   12,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,   13,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,   15,    1,    1,    1,    1,    1,    1,
 
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,   14,    1,   15,    1,    1,    1,    1,
+        1,    1,    1,   16,    1,   17,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -596,40 +596,40 @@ static const YY_CHAR yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static const YY_CHAR yy_meta[16] =
+static const YY_CHAR yy_meta[18] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
+        1,    1,    1,    1,    1,    1,    1
     } ;
 
-static const flex_int16_t yy_base[23] =
+static const flex_int16_t yy_base[25] =
     {   0,
-        0,    0,   20,   21,   21,   21,   21,   21,   21,   21,
-       21,   21,    9,    7,    5,   21,   21,   21,    6,   21,
-       21,   21
+        0,    0,   22,   23,   23,   23,   23,   23,   23,   23,
+       23,   23,   23,   23,    9,    7,    5,   23,   23,   23,
+        6,   23,   23,   23
     } ;
 
-static const flex_int16_t yy_def[23] =
+static const flex_int16_t yy_def[25] =
     {   0,
-       22,    1,   22,   22,   22,   22,   22,   22,   22,   22,
-       22,   22,   22,   22,   22,   22,   22,   22,   22,   22,
-       22,    0
+       24,    1,   24,   24,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,    0
     } ;
 
-static const flex_int16_t yy_nxt[37] =
+static const flex_int16_t yy_nxt[41] =
     {   0,
         4,    5,    6,    7,    8,    9,   10,   11,   12,   13,
-       14,   15,   16,   17,   18,   19,   21,   20,   19,   22,
-        3,   22,   22,   22,   22,   22,   22,   22,   22,   22,
-       22,   22,   22,   22,   22,   22
+       14,   15,   16,   17,   18,   19,   20,   21,   23,   22,
+       21,   24,    3,   24,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   24,   24,   24
     } ;
 
-static const flex_int16_t yy_chk[37] =
+static const flex_int16_t yy_chk[41] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,   19,   15,   14,   13,    3,
-       22,   22,   22,   22,   22,   22,   22,   22,   22,   22,
-       22,   22,   22,   22,   22,   22
+        1,    1,    1,    1,    1,    1,    1,   21,   17,   16,
+       15,    3,   24,   24,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   24,   24,   24
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -668,6 +668,8 @@ Modify cmExprLexer.cxx:
 /* Include the set of tokens from the parser.  */
 #include "cmExprParserTokens.h"
 
+#include <string>
+
 /*--------------------------------------------------------------------------*/
 
 #define INITIAL 0
@@ -946,13 +948,13 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 23 )
+				if ( yy_current_state >= 25 )
 					yy_c = yy_meta[yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
 			++yy_cp;
 			}
-		while ( yy_base[yy_current_state] != 21 );
+		while ( yy_base[yy_current_state] != 23 );
 
 yy_find_action:
 		yy_act = yy_accept[yy_current_state];
@@ -978,62 +980,70 @@ do_action:	/* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-{ yylvalp->Number = atoi(yytext); return exp_NUMBER; }
+{}
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-{ return exp_PLUS; }
+{ yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; }
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-{ return exp_MINUS; }
+{ return exp_PLUS; }
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-{ return exp_TIMES; }
+{ return exp_MINUS; }
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-{ return exp_DIVIDE; }
+{ return exp_TIMES; }
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-{ return exp_MOD; }
+{ return exp_DIVIDE; }
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-{ return exp_OR; }
+{ return exp_MOD; }
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-{ return exp_AND; }
+{ return exp_OR; }
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-{ return exp_XOR; }
+{ return exp_AND; }
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-{ return exp_NOT; }
+{ return exp_XOR; }
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-{ return exp_SHIFTLEFT; }
+{ return exp_NOT; }
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-{ return exp_SHIFTRIGHT; }
+{ return exp_SHIFTLEFT; }
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-{ return exp_OPENPARENT; }
+{ return exp_SHIFTRIGHT; }
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-{ return exp_CLOSEPARENT; }
+{ return exp_OPENPARENT; }
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
+{ return exp_CLOSEPARENT; }
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+{return exp_UNEXPECTED;}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
 ECHO;
 	YY_BREAK
 case YY_STATE_EOF(INITIAL):
@@ -1334,7 +1344,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 23 )
+			if ( yy_current_state >= 25 )
 				yy_c = yy_meta[yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -1363,11 +1373,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 23 )
+		if ( yy_current_state >= 25 )
 			yy_c = yy_meta[yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
-	yy_is_jam = (yy_current_state == 22);
+	yy_is_jam = (yy_current_state == 24);
 
 	(void)yyg;
 	return yy_is_jam ? 0 : yy_current_state;

+ 5 - 1
Source/LexerParser/cmExprLexer.in.l

@@ -28,6 +28,8 @@ Modify cmExprLexer.cxx:
 /* Include the set of tokens from the parser.  */
 #include "cmExprParserTokens.h"
 
+#include <string>
+
 /*--------------------------------------------------------------------------*/
 %}
 
@@ -38,8 +40,9 @@ Modify cmExprLexer.cxx:
 %pointer
 
 %%
+[ \t]  {}
 
-[0-9][0-9]* { yylvalp->Number = atoi(yytext); return exp_NUMBER; }
+[0-9][0-9]* { yylvalp->Number = std::stoll(yytext, nullptr, 10); return exp_NUMBER; }
 
 "+" { return exp_PLUS; }
 "-" { return exp_MINUS; }
@@ -54,5 +57,6 @@ Modify cmExprLexer.cxx:
 ">>" { return exp_SHIFTRIGHT; }
 "(" { return exp_OPENPARENT; }
 ")" { return exp_CLOSEPARENT; }
+. {return exp_UNEXPECTED;}
 
 %%

+ 67 - 64
Source/LexerParser/cmExprParser.cxx

@@ -156,7 +156,8 @@ extern int cmExpr_yydebug;
     exp_AND = 268,
     exp_XOR = 269,
     exp_NOT = 270,
-    exp_NUMBER = 271
+    exp_NUMBER = 271,
+    exp_UNEXPECTED = 272
   };
 #endif
 /* Tokens.  */
@@ -174,6 +175,7 @@ extern int cmExpr_yydebug;
 #define exp_XOR 269
 #define exp_NOT 270
 #define exp_NUMBER 271
+#define exp_UNEXPECTED 272
 
 /* Value type.  */
 
@@ -185,7 +187,7 @@ int cmExpr_yyparse (yyscan_t yyscanner);
 
 /* Copy the second part of user declarations.  */
 
-#line 189 "cmExprParser.cxx" /* yacc.c:358  */
+#line 191 "cmExprParser.cxx" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -430,7 +432,7 @@ union yyalloc
 #define YYLAST   30
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  17
+#define YYNTOKENS  18
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  10
 /* YYNRULES -- Number of rules.  */
@@ -441,7 +443,7 @@ union yyalloc
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   271
+#define YYMAXUTOK   272
 
 #define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -477,16 +479,16 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16
+      15,    16,    17
 };
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint8 yyrline[] =
 {
-       0,    73,    73,    78,    81,    86,    89,    94,    97,   102,
-     105,   108,   113,   116,   119,   124,   127,   130,   133,   138,
-     141,   144,   149,   152
+       0,    74,    74,    79,    82,    87,    90,    95,    98,   103,
+     106,   109,   114,   117,   120,   125,   128,   131,   134,   139,
+     142,   145,   150,   153
 };
 #endif
 
@@ -498,8 +500,9 @@ static const char *const yytname[] =
   "$end", "error", "$undefined", "exp_PLUS", "exp_MINUS", "exp_TIMES",
   "exp_DIVIDE", "exp_MOD", "exp_SHIFTLEFT", "exp_SHIFTRIGHT",
   "exp_OPENPARENT", "exp_CLOSEPARENT", "exp_OR", "exp_AND", "exp_XOR",
-  "exp_NOT", "exp_NUMBER", "$accept", "start", "exp", "bitwiseor",
-  "bitwisexor", "bitwiseand", "shift", "term", "unary", "factor", YY_NULLPTR
+  "exp_NOT", "exp_NUMBER", "\"character\"", "$accept", "start", "exp",
+  "bitwiseor", "bitwisexor", "bitwiseand", "shift", "term", "unary",
+  "factor", YY_NULLPTR
 };
 #endif
 
@@ -509,7 +512,7 @@ static const char *const yytname[] =
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271
+     265,   266,   267,   268,   269,   270,   271,   272
 };
 # endif
 
@@ -579,18 +582,18 @@ static const yytype_int8 yycheck[] =
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,     4,    10,    16,    18,    19,    20,    21,    22,
-      23,    24,    25,    26,    25,    25,    19,     0,    12,    14,
-      13,     8,     9,     3,     4,     5,     6,     7,    11,    20,
-      21,    22,    23,    23,    24,    24,    25,    25,    25
+       0,     3,     4,    10,    16,    19,    20,    21,    22,    23,
+      24,    25,    26,    27,    26,    26,    20,     0,    12,    14,
+      13,     8,     9,     3,     4,     5,     6,     7,    11,    21,
+      22,    23,    24,    24,    25,    25,    26,    26,    26
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    17,    18,    19,    19,    20,    20,    21,    21,    22,
-      22,    22,    23,    23,    23,    24,    24,    24,    24,    25,
-      25,    25,    26,    26
+       0,    18,    19,    20,    20,    21,    21,    22,    22,    23,
+      23,    23,    24,    24,    24,    25,    25,    25,    25,    26,
+      26,    26,    27,    27
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
@@ -1281,183 +1284,183 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 73 "cmExprParser.y" /* yacc.c:1646  */
+#line 74 "cmExprParser.y" /* yacc.c:1646  */
     {
     cmExpr_yyget_extra(yyscanner)->SetResult((yyvsp[0].Number));
   }
-#line 1289 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1292 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 3:
-#line 78 "cmExprParser.y" /* yacc.c:1646  */
+#line 79 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1297 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1300 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 4:
-#line 81 "cmExprParser.y" /* yacc.c:1646  */
+#line 82 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) | (yyvsp[0].Number);
   }
-#line 1305 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1308 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 5:
-#line 86 "cmExprParser.y" /* yacc.c:1646  */
+#line 87 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1313 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1316 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 89 "cmExprParser.y" /* yacc.c:1646  */
+#line 90 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) ^ (yyvsp[0].Number);
   }
-#line 1321 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1324 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 94 "cmExprParser.y" /* yacc.c:1646  */
+#line 95 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1329 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1332 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 97 "cmExprParser.y" /* yacc.c:1646  */
+#line 98 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) & (yyvsp[0].Number);
   }
-#line 1337 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1340 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 102 "cmExprParser.y" /* yacc.c:1646  */
+#line 103 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1345 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1348 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 105 "cmExprParser.y" /* yacc.c:1646  */
+#line 106 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) << (yyvsp[0].Number);
   }
-#line 1353 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1356 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 108 "cmExprParser.y" /* yacc.c:1646  */
+#line 109 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) >> (yyvsp[0].Number);
   }
-#line 1361 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1364 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 113 "cmExprParser.y" /* yacc.c:1646  */
+#line 114 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1369 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1372 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 116 "cmExprParser.y" /* yacc.c:1646  */
+#line 117 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) + (yyvsp[0].Number);
   }
-#line 1377 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1380 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 119 "cmExprParser.y" /* yacc.c:1646  */
+#line 120 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) - (yyvsp[0].Number);
   }
-#line 1385 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1388 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 124 "cmExprParser.y" /* yacc.c:1646  */
+#line 125 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1393 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1396 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 127 "cmExprParser.y" /* yacc.c:1646  */
+#line 128 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) * (yyvsp[0].Number);
   }
-#line 1401 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1404 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 130 "cmExprParser.y" /* yacc.c:1646  */
+#line 131 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) / (yyvsp[0].Number);
   }
-#line 1409 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1412 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 133 "cmExprParser.y" /* yacc.c:1646  */
+#line 134 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-2].Number) % (yyvsp[0].Number);
   }
-#line 1417 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1420 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 138 "cmExprParser.y" /* yacc.c:1646  */
+#line 139 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1425 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1428 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 141 "cmExprParser.y" /* yacc.c:1646  */
+#line 142 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = + (yyvsp[0].Number);
   }
-#line 1433 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1436 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 144 "cmExprParser.y" /* yacc.c:1646  */
+#line 145 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = - (yyvsp[0].Number);
   }
-#line 1441 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1444 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 149 "cmExprParser.y" /* yacc.c:1646  */
+#line 150 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[0].Number);
   }
-#line 1449 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1452 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 152 "cmExprParser.y" /* yacc.c:1646  */
+#line 153 "cmExprParser.y" /* yacc.c:1646  */
     {
     (yyval.Number) = (yyvsp[-1].Number);
   }
-#line 1457 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1460 "cmExprParser.cxx" /* yacc.c:1646  */
     break;
 
 
-#line 1461 "cmExprParser.cxx" /* yacc.c:1646  */
+#line 1464 "cmExprParser.cxx" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1687,7 +1690,7 @@ yyreturn:
 #endif
   return yyresult;
 }
-#line 157 "cmExprParser.y" /* yacc.c:1906  */
+#line 158 "cmExprParser.y" /* yacc.c:1906  */
 
 /* End of grammar */
 

+ 1 - 0
Source/LexerParser/cmExprParser.y

@@ -63,6 +63,7 @@ static void cmExpr_yyerror(yyscan_t yyscanner, const char* message);
 %token exp_XOR;
 %token exp_NOT;
 %token exp_NUMBER;
+%token exp_UNEXPECTED "character";
 
 /*-------------------------------------------------------------------------*/
 /* grammar */

+ 3 - 1
Source/LexerParser/cmExprParserTokens.h

@@ -58,7 +58,8 @@ extern int cmExpr_yydebug;
     exp_AND = 268,
     exp_XOR = 269,
     exp_NOT = 270,
-    exp_NUMBER = 271
+    exp_NUMBER = 271,
+    exp_UNEXPECTED = 272
   };
 #endif
 /* Tokens.  */
@@ -76,6 +77,7 @@ extern int cmExpr_yydebug;
 #define exp_XOR 269
 #define exp_NOT 270
 #define exp_NUMBER 271
+#define exp_UNEXPECTED 272
 
 /* Value type.  */
 

+ 34 - 1
Source/cmExprParserHelper.cxx

@@ -6,6 +6,8 @@
 
 #include <iostream>
 #include <sstream>
+#include <stdexcept>
+#include <utility>
 
 int cmExpr_yyparse(yyscan_t yyscanner);
 //
@@ -38,7 +40,33 @@ int cmExprParserHelper::ParseString(const char* str, int verb)
   yyscan_t yyscanner;
   cmExpr_yylex_init(&yyscanner);
   cmExpr_yyset_extra(this, yyscanner);
-  int res = cmExpr_yyparse(yyscanner);
+  int res;
+
+  try {
+    res = cmExpr_yyparse(yyscanner);
+    if (res != 0) {
+      std::string e = "cannot parse the expression: \"" + InputBuffer + "\": ";
+      e += ErrorString;
+      e += ".";
+      this->SetError(std::move(e));
+    }
+  } catch (std::runtime_error const& fail) {
+    std::string e =
+      "cannot evaluate the expression: \"" + InputBuffer + "\": ";
+    e += fail.what();
+    e += ".";
+    this->SetError(std::move(e));
+    res = 1;
+  } catch (std::out_of_range const&) {
+    std::string e = "cannot evaluate the expression: \"" + InputBuffer +
+      "\": a numeric value is out of range.";
+    this->SetError(std::move(e));
+    res = 1;
+  } catch (...) {
+    std::string e = "cannot parse the expression: \"" + InputBuffer + "\".";
+    this->SetError(std::move(e));
+    res = 1;
+  }
   cmExpr_yylex_destroy(yyscanner);
   if (res != 0) {
     // str << "CAL_Parser returned: " << res << std::endl;
@@ -90,3 +118,8 @@ void cmExprParserHelper::SetResult(KWIML_INT_int64_t value)
 {
   this->Result = value;
 }
+
+void cmExprParserHelper::SetError(std::string errorString)
+{
+  this->ErrorString = std::move(errorString);
+}

+ 1 - 0
Source/cmExprParserHelper.h

@@ -42,6 +42,7 @@ private:
   void Print(const char* place, const char* str);
 
   void CleanupParser();
+  void SetError(std::string errorString);
 
   KWIML_INT_int64_t Result;
   const char* FileName;

+ 3 - 3
Source/cmMathCommand.cxx

@@ -36,11 +36,11 @@ bool cmMathCommand::HandleExprCommand(std::vector<std::string> const& args)
   const std::string& outputVariable = args[1];
   const std::string& expression = args[2];
 
+  this->Makefile->AddDefinition(outputVariable, "ERROR");
+
   cmExprParserHelper helper;
   if (!helper.ParseString(expression.c_str(), 0)) {
-    std::string e = "cannot parse the expression: \"" + expression + "\": ";
-    e += helper.GetError();
-    this->SetError(e);
+    this->SetError(helper.GetError());
     return false;
   }
 

+ 1 - 0
Tests/RunCMake/math/MATH-InvalidExpression-result.txt

@@ -0,0 +1 @@
+1

+ 6 - 0
Tests/RunCMake/math/MATH-InvalidExpression-stderr.txt

@@ -0,0 +1,6 @@
+^CMake Error at MATH-InvalidExpression.cmake:1 \(math\):
+ *math cannot parse the expression: "INVALID": syntax error, unexpected
+ *character, expecting exp_PLUS or exp_MINUS or exp_OPENPARENT or exp_NUMBER
+ *\(1\).
+Call Stack \(most recent call first\):
+  CMakeLists.txt:3 \(include\)$

+ 1 - 0
Tests/RunCMake/math/MATH-InvalidExpression.cmake

@@ -0,0 +1 @@
+math(EXPR var "INVALID")

+ 1 - 0
Tests/RunCMake/math/RunCMakeTest.cmake

@@ -1,3 +1,4 @@
 include(RunCMake)
 
 run_cmake(MATH)
+run_cmake(MATH-InvalidExpression)