1# Checking Push Parsing. -*- Autotest -*- 2 3# Copyright (C) 2007, 2009-2015, 2018-2021 Free Software Foundation, 4# Inc. 5 6# This program is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <https://www.gnu.org/licenses/>. 18 19AT_BANNER([[Push Parsing Tests]]) 20 21## -------------------------------- ## 22## Memory Leak for Early Deletion. ## 23## -------------------------------- ## 24 25AT_SETUP([[Memory Leak for Early Deletion]]) 26 27# Requires Valgrind. 28AT_BISON_OPTION_PUSHDEFS([%define api.push-pull push]) 29AT_DATA_GRAMMAR([[input.y]], 30[[ 31%{ 32 #include <assert.h> 33 #include <stdio.h> 34 #define YYINITDEPTH 1 35]AT_YYERROR_DECLARE[ 36%} 37 38%define api.pure 39%define api.push-pull push 40 41%% 42 43start: 'a' 'b' 'c' ; 44 45%% 46 47]AT_YYERROR_DEFINE[ 48 49int 50main (void) 51{ 52 yypstate *ps; 53 54 /* Make sure we don't try to free ps->yyss in this case. */ 55 ps = yypstate_new (); 56 yypstate_delete (ps); 57 58 /* yypstate_delete used to leak ps->yyss if the stack was reallocated but the 59 parse did not return on success, syntax error, or memory exhaustion. */ 60 ps = yypstate_new (); 61 assert (yypush_parse (ps, 'a', YY_NULLPTR) == YYPUSH_MORE); 62 yypstate_delete (ps); 63 64 ps = yypstate_new (); 65 assert (yypush_parse (ps, 'a', YY_NULLPTR) == YYPUSH_MORE); 66 assert (yypush_parse (ps, 'b', YY_NULLPTR) == YYPUSH_MORE); 67 yypstate_delete (ps); 68 69 return 0; 70} 71]]) 72AT_BISON_OPTION_POPDEFS 73 74AT_BISON_CHECK([[-o input.c input.y]]) 75AT_COMPILE([[input]]) 76AT_PARSER_CHECK([[input]]) 77 78AT_CLEANUP 79 80## --------------------------- ## 81## Multiple impure instances. ## 82## --------------------------- ## 83 84AT_SETUP([[Multiple impure instances]]) 85 86m4_pushdef([AT_MULTIPLE_IMPURE_INSTANCES_CHECK], [ 87AT_BISON_OPTION_PUSHDEFS([%define api.push-pull $1]) 88AT_DATA_GRAMMAR([[input.y]], 89[[ 90%{ 91 #include <assert.h> 92 #include <stdio.h> 93]AT_YYERROR_DECLARE[ 94]m4_if([$1], [[both]], [AT_YYLEX_DECLARE([])])[ 95%} 96 97%define api.push-pull ]$1[ 98 99%% 100 101start: ; 102 103%% 104]AT_YYERROR_DEFINE[ 105]m4_if([$1], [[both]], [AT_YYLEX_DEFINE])[ 106 107int 108main (void) 109{ 110 int i; 111 for (i = 0; i < 2; ++i) 112 { 113 yypstate *ps = yypstate_new (); 114 assert (ps); 115 assert (yypstate_new () == YY_NULLPTR); 116 ]m4_if([$1], [[both]], [[assert (yyparse () == 2)]])[; 117 yychar = 0; 118 assert (yypush_parse (ps) == 0); 119 assert (yypstate_new () == YY_NULLPTR); 120 ]m4_if([$1], [[both]], [[assert (yyparse () == 2)]])[; 121 yypstate_delete (ps); 122 } 123 124 return 0; 125} 126]]) 127 128AT_BISON_CHECK([[-o input.c input.y]]) 129AT_COMPILE([[input]]) 130AT_PARSER_CHECK([[input]]) 131AT_BISON_OPTION_POPDEFS 132]) 133 134AT_MULTIPLE_IMPURE_INSTANCES_CHECK([[both]]) 135AT_MULTIPLE_IMPURE_INSTANCES_CHECK([[push]]) 136 137m4_popdef([AT_MULTIPLE_IMPURE_INSTANCES_CHECK]) 138 139AT_CLEANUP 140 141## ----------------------- ## 142## Unsupported Skeletons. ## 143## ----------------------- ## 144 145AT_SETUP([[Unsupported Skeletons]]) 146 147AT_BISON_OPTION_PUSHDEFS([%define api.push-pull push]) 148AT_DATA([[input.y]], 149[[%glr-parser 150%define api.push-pull push 151%% 152start: ; 153]]) 154AT_BISON_OPTION_POPDEFS 155 156AT_BISON_CHECK([[input.y]], [[1]], [], 157[[input.y:2.1-26: error: %define variable 'api.push-pull' is not used 158]]) 159 160AT_CLEANUP 161 162 163## -------------- ## 164## Pstate reuse. ## 165## -------------- ## 166 167AT_SETUP([[Pstate reuse]]) 168 169# Make sure that when a single pstate is used for multiple successive 170# parses, no state from a previous run leaks into the following one. 171# 172# See https://lists.gnu.org/r/bug-bison/2021-03/msg00000.html. 173 174AT_BISON_OPTION_PUSHDEFS([%define api.push-pull push]) 175AT_DATA_GRAMMAR([[input.y]], 176[[%code top { 177 #include <stdlib.h> 178 #include <string.h> 179 180 static char *string_concat (char *a, char *b); 181 ]AT_YYERROR_DECLARE[ 182} 183 184%define parse.trace 185%define api.pure full 186%define api.push-pull push 187%expect 0 188 189%union { 190 char *sval; 191}; 192%destructor { free ($$); } <sval> 193%printer { fprintf (yyo, "%s", $$); } <sval> 194 195%token <sval> RAW 196%token EOL 197 198%type <sval> text 199 200%% 201 202line 203 : text EOL { printf ("text: %s\n", $1); free ($1); YYACCEPT; }; 204 205text 206 : RAW { $$ = $1; } 207 | text RAW { $$ = string_concat ($1, $2); } 208 ; 209 210%% 211]AT_YYERROR_DEFINE[ 212 213static char * 214string_concat (char *a, char *b) 215{ 216 size_t la = strlen (a); 217 size_t lb = strlen (b); 218 char *res = YY_CAST (char *, malloc (la + lb + 1)); 219 strcpy (res, a); 220 strcpy (res + la, b); 221 free (a); 222 free (b); 223 return res; 224} 225 226static int 227push (yypstate *ps, yytoken_kind_t kind, const char *str) 228{ 229 YYSTYPE lval; 230 lval.sval = str ? strdup (str) : YY_NULLPTR; 231 switch (yypush_parse (ps, kind, &lval)) 232 { 233 case 0: 234 return 0; 235 case YYPUSH_MORE: 236 // parsing incomplete, but valid; parser not reset 237 return 0; 238 case 1: 239 // YYABORT or syntax invalid; parser is reset 240 fprintf (stderr, "invalid input, but no error was thrown\n"); 241 return 1; 242 case 2: 243 // memory exhaustion; parser is reset 244 fprintf (stderr, "memory exhaustion during yypush_parse\n"); 245 return 1; 246 } 247 return 1; 248} 249 250int 251main (void) 252{ 253 yydebug = !!getenv ("YYDEBUG"); 254 yypstate *ps = yypstate_new (); 255 256#define PUSH(Kind, Val) \ 257 do { \ 258 if (push (ps, Kind, Val)) \ 259 return 1; \ 260 } while (0) 261 262 PUSH (RAW, "te"); 263 PUSH (RAW, "xt"); 264 PUSH (EOL, YY_NULLPTR); 265 266 PUSH (RAW, "te"); 267 PUSH (RAW, "xt"); 268 PUSH (EOL, YY_NULLPTR); 269 270 yypstate_delete (ps); 271 272 return 0; 273} 274]]) 275 276AT_FULL_COMPILE([input]) 277AT_CHECK([./input], 0, 278[[text: text 279text: text 280]]) 281 282AT_BISON_OPTION_POPDEFS 283AT_CLEANUP 284