1 /**
2
3 MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
4
5 @file parser.y
6
7 @brief Use a cleaned copy of the parser grammar to allow "fuzz" testing with
8 combinations of every line type to find combinations that can't be parsed.
9 NOTE: This does not mean that each of these combinations is properly parsed,
10 simply that it does not cause the parser to fail. Use the test suite to ensure
11 that input text is properly being parsed.
12
13
14 @author Fletcher T. Penney
15 @bug
16
17 **/
18
19 /*
20
21 Copyright © 2016 - 2017 Fletcher T. Penney.
22
23
24 The `MultiMarkdown 6` project is released under the MIT License..
25
26 GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
27
28 https://github.com/fletcher/MultiMarkdown-4/
29
30 MMD 4 is released under both the MIT License and GPL.
31
32
33 CuTest is released under the zlib/libpng license. See CuTest.c for the text
34 of the license.
35
36
37 ## The MIT License ##
38
39 Permission is hereby granted, free of charge, to any person obtaining a copy
40 of this software and associated documentation files (the "Software"), to deal
41 in the Software without restriction, including without limitation the rights
42 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43 copies of the Software, and to permit persons to whom the Software is
44 furnished to do so, subject to the following conditions:
45
46 The above copyright notice and this permission notice shall be included in
47 all copies or substantial portions of the Software.
48
49 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55 THE SOFTWARE.
56
57 */
58
59
60
61 //
62 // Language grammar here
63 //
64
65 %token_type { int }
66
67
68 // Manually copy fallbacks from `parser.y` here
69
70 %fallback LINE_HR LINE_SETEXT_1 LINE_SETEXT_2.
71
72 //%fallback LINE_PLAIN LINE_TABLE_SEPARATOR.
73
74 %fallback LINE_CONTINUATION LINE_INDENTED_TAB LINE_INDENTED_SPACE LINE_TABLE LINE_TABLE_SEPARATOR.
75
76 %fallback LINE_HTML LINE_ATX_1 LINE_ATX_2 LINE_ATX_3 LINE_ATX_4 LINE_ATX_5 LINE_ATX_6 LINE_BLOCKQUOTE
77 LINE_LIST_BULLETED LINE_LIST_ENUMERATED LINE_DEF_ABBREVIATION LINE_DEF_CITATION LINE_DEF_FOOTNOTE
78 LINE_DEF_GLOSSARY LINE_DEF_LINK LINE_FENCE_BACKTICK LINE_FENCE_BACKTICK_START.
79
80
81 // Copy clean grammar via `lemon -g parser.y` here
82
83 doc ::= blocks.
84 blocks ::= blocks block.
85 blocks ::= block.
86 block ::= LINE_ATX_1.
87 block ::= LINE_ATX_2.
88 block ::= LINE_ATX_3.
89 block ::= LINE_ATX_4.
90 block ::= LINE_ATX_5.
91 block ::= LINE_ATX_6.
92 block ::= LINE_HR.
93 block ::= LINE_TOC.
94 block ::= blockquote.
95 block ::= def_abbreviation.
96 block ::= def_citation.
97 block ::= def_footnote.
98 block ::= def_glossary.
99 block ::= def_link.
100 block ::= definition_block.
101 block ::= empty.
102 block ::= fenced_block.
103 block ::= html_block.
104 block ::= indented_code.
105 block ::= list_bullet.
106 block ::= list_enum.
107 block ::= meta_block.
108 block ::= para.
109 block ::= setext_1.
110 block ::= setext_2.
111 block ::= table.
112 chunk ::= chunk chunk_line.
113 nested_chunks ::= nested_chunks nested_chunk.
114 nested_chunk ::= empty indented_line chunk.
115 nested_chunk ::= empty indented_line.
116 ext_chunk ::= chunk nested_chunks.
117 opt_ext_chunk ::= chunk nested_chunks.
118 blockquote ::= blockquote quote_line.
119 def_citation ::= LINE_DEF_CITATION tail.
120 def_footnote ::= LINE_DEF_FOOTNOTE tail.
121 def_glossary ::= LINE_DEF_GLOSSARY tail.
122 def_link ::= LINE_DEF_LINK chunk.
123 def_abbreviation ::= LINE_DEF_ABBREVIATION chunk.
124 definition_block ::= para defs.
125 defs ::= defs def.
126 def ::= LINE_DEFINITION tail.
127 def ::= LINE_DEFINITION.
128 empty ::= empty LINE_EMPTY.
129 fenced_block ::= fenced_3 LINE_FENCE_BACKTICK_3.
130 fenced_block ::= fenced_3 LINE_FENCE_BACKTICK_4.
131 fenced_block ::= fenced_3 LINE_FENCE_BACKTICK_5.
132 fenced_3 ::= fenced_3 fenced_line.
133 fenced_block ::= fenced_4 LINE_FENCE_BACKTICK_4.
134 fenced_block ::= fenced_4 LINE_FENCE_BACKTICK_5.
135 fenced_4 ::= fenced_4 fenced_line.
136 fenced_4 ::= fenced_4 LINE_FENCE_BACKTICK_3.
137 fenced_4 ::= fenced_4 LINE_FENCE_BACKTICK_START_3.
138 fenced_block ::= fenced_5 LINE_FENCE_BACKTICK_5.
139 fenced_5 ::= fenced_5 fenced_line.
140 fenced_5 ::= fenced_5 LINE_FENCE_BACKTICK_3.
141 fenced_5 ::= fenced_5 LINE_FENCE_BACKTICK_START_3.
142 fenced_5 ::= fenced_5 LINE_FENCE_BACKTICK_4.
143 fenced_5 ::= fenced_5 LINE_FENCE_BACKTICK_START_4.
144 html_block ::= html_block html_line.
145 indented_code ::= indented_code indented_line.
146 indented_code ::= indented_code LINE_EMPTY.
147 list_bullet ::= list_bullet item_bullet.
148 item_bullet ::= LINE_LIST_BULLETED ext_chunk.
149 item_bullet ::= LINE_LIST_BULLETED chunk.
150 item_bullet ::= LINE_LIST_BULLETED nested_chunks.
151 item_bullet ::= LINE_LIST_BULLETED.
152 list_enum ::= list_enum item_enum.
153 item_enum ::= LINE_LIST_ENUMERATED ext_chunk.
154 item_enum ::= LINE_LIST_ENUMERATED chunk.
155 item_enum ::= LINE_LIST_ENUMERATED nested_chunks.
156 item_enum ::= LINE_LIST_ENUMERATED.
157 meta_block ::= meta_block meta_line.
158 para ::= LINE_PLAIN chunk.
159 setext_1 ::= para LINE_SETEXT_1.
160 setext_2 ::= para LINE_SETEXT_2.
161 table ::= table_header table_body.
162 table_header ::= header_rows LINE_TABLE_SEPARATOR.
163 header_rows ::= header_rows LINE_TABLE.
164 table_body ::= table_body table_section.
165 table_section ::= all_rows LINE_EMPTY.
166 table_section ::= all_rows.
167 all_rows ::= all_rows row.
168 para ::= all_rows.
169 chunk ::= chunk_line.
170 chunk_line ::= LINE_CONTINUATION.
171 nested_chunks ::= nested_chunk.
172 nested_chunk ::= empty.
173 indented_line ::= LINE_INDENTED_TAB.
174 indented_line ::= LINE_INDENTED_SPACE.
175 opt_ext_chunk ::= chunk.
176 tail ::= opt_ext_chunk.
177 tail ::= nested_chunks.
178 blockquote ::= LINE_BLOCKQUOTE.
179 quote_line ::= LINE_BLOCKQUOTE.
180 quote_line ::= LINE_CONTINUATION.
181 def_citation ::= LINE_DEF_CITATION.
182 def_footnote ::= LINE_DEF_FOOTNOTE.
183 def_glossary ::= LINE_DEF_GLOSSARY.
184 def_link ::= LINE_DEF_LINK.
185 def_abbreviation ::= LINE_DEF_ABBREVIATION.
186 defs ::= def.
187 empty ::= LINE_EMPTY.
188 fenced_block ::= fenced_3.
189 fenced_3 ::= LINE_FENCE_BACKTICK_3.
190 fenced_3 ::= LINE_FENCE_BACKTICK_START_3.
191 fenced_block ::= fenced_4.
192 fenced_4 ::= LINE_FENCE_BACKTICK_4.
193 fenced_4 ::= LINE_FENCE_BACKTICK_START_4.
194 fenced_block ::= fenced_5.
195 fenced_5 ::= LINE_FENCE_BACKTICK_5.
196 fenced_5 ::= LINE_FENCE_BACKTICK_START_5.
197 fenced_line ::= LINE_CONTINUATION.
198 fenced_line ::= LINE_EMPTY.
199 fenced_line ::= LINE_SETEXT_1.
200 fenced_line ::= LINE_SETEXT_2.
201 html_block ::= LINE_HTML.
202 html_line ::= LINE_CONTINUATION.
203 html_line ::= LINE_HTML.
204 indented_code ::= indented_line.
205 list_bullet ::= item_bullet.
206 list_enum ::= item_enum.
207 meta_block ::= LINE_META.
208 meta_line ::= LINE_META.
209 meta_line ::= LINE_CONTINUATION.
210 para ::= LINE_PLAIN.
211 table ::= table_header.
212 header_rows ::= LINE_TABLE.
213 table_body ::= table_section.
214 all_rows ::= row.
215 row ::= header_rows.
216 row ::= LINE_TABLE_SEPARATOR.
217 para ::= defs.
218
219
220 //
221 // Additional Configuration
222 //
223
224 %include {
225 #include <assert.h>
226 #include <stdio.h>
227 #include <stdlib.h>
228 #include "parser_test.h"
229
230 // Basic parser function declarations
231 void * ParseAlloc();
232 void Parse();
233 void ParseFree();
234 void ParseTrace();
235
236 #define kMaxToken 36
237
238 int i,j,k,l,m, n;
239
main(int argc,char ** argv)240 int main(int argc, char** argv) {
241
242 void* pParser = ParseAlloc (malloc); // Create a parser (for lemon)
243
244 #ifndef NDEBUG
245 ParseTrace(stderr, "parser >>");
246 #endif
247
248
249 fprintf(stderr, "Single line tests\n");
250
251 i = 0;
252 j = 0;
253 k = 0;
254 l = 0;
255 m = 0;
256 n = 0;
257
258 for (i = 1; i <= kMaxToken; ++i)
259 {
260 // LINE_CONTINUATION can't be the first line
261 if (i == LINE_CONTINUATION)
262 break;
263
264 Parse(pParser, i, NULL);
265
266 Parse(pParser, 0, NULL);
267 }
268
269 fprintf(stderr, "\nDouble line tests\n");
270
271 i = 0;
272 j = 0;
273 k = 0;
274 l = 0;
275 m = 0;
276
277 for (i = 1; i <= kMaxToken; ++i)
278 {
279 // LINE_CONTINUATION can't be the first line
280 if (i == LINE_CONTINUATION)
281 break;
282
283 for (j = 1; j <= kMaxToken; ++j) {
284
285 Parse(pParser, i, NULL);
286 Parse(pParser, j, NULL);
287
288 Parse(pParser, 0, NULL);
289 }
290 }
291
292 fprintf(stderr, "\nTriple line tests\n");
293
294 i = 0;
295 j = 0;
296 k = 0;
297 l = 0;
298 m = 0;
299
300 for (i = 1; i <= kMaxToken; ++i)
301 {
302 // LINE_CONTINUATION can't be the first line
303 if (i == LINE_CONTINUATION)
304 break;
305
306 for (j = 1; j <= kMaxToken; ++j) {
307
308 for (k = 1; k <= kMaxToken; ++k) {
309
310 Parse(pParser, i, NULL);
311 Parse(pParser, j, NULL);
312 Parse(pParser, k, NULL);
313
314 Parse(pParser, 0, NULL);
315 }
316 }
317 }
318
319 // return(0);
320
321 fprintf(stderr, "\nQuad line tests\n");
322
323 i = 0;
324 j = 0;
325 k = 0;
326 l = 0;
327 m = 0;
328
329 for (i = 1; i <= kMaxToken; ++i)
330 {
331 // LINE_CONTINUATION can't be the first line
332 if (i == LINE_CONTINUATION)
333 break;
334
335 for (j = 1; j <= kMaxToken; ++j) {
336
337 for (k = 1; k <= kMaxToken; ++k) {
338
339 for (l = 1; l <= kMaxToken; ++l) {
340
341 Parse(pParser, i, NULL);
342 Parse(pParser, j, NULL);
343 Parse(pParser, k, NULL);
344 Parse(pParser, l, NULL);
345
346 Parse(pParser, 0, NULL);
347 }
348 }
349 }
350 }
351
352 // return(0);
353
354 fprintf(stderr, "\nFive line tests\n");
355
356 i = 0;
357 j = 0;
358 k = 0;
359 l = 0;
360 m = 0;
361
362 for (i = 1; i <= kMaxToken; ++i)
363 {
364 // LINE_CONTINUATION can't be the first line
365 if (i == LINE_CONTINUATION)
366 break;
367
368 for (j = 1; j <= kMaxToken; ++j) {
369
370 for (k = 1; k <= kMaxToken; ++k) {
371
372 for (l = 1; l <= kMaxToken; ++l) {
373
374 for (m = 1; m <= kMaxToken; ++m) {
375
376 Parse(pParser, i, NULL);
377 Parse(pParser, j, NULL);
378 Parse(pParser, k, NULL);
379 Parse(pParser, l, NULL);
380 Parse(pParser, m, NULL);
381
382 Parse(pParser, 0, NULL);
383 }
384 }
385 }
386 }
387 }
388
389 return(0);
390
391 // Six cycles takes quite a while
392
393 fprintf(stderr, "\nSix line tests\n");
394
395 i = 0;
396 j = 0;
397 k = 0;
398 l = 0;
399 m = 0;
400 n = 0;
401
402 for (i = 1; i <= kMaxToken; ++i)
403 {
404 // LINE_CONTINUATION can't be the first line
405 if (i == LINE_CONTINUATION)
406 break;
407
408 fprintf(stderr, "%d\n", i);
409
410 for (j = 1; j <= kMaxToken; ++j) {
411
412 for (k = 1; k <= kMaxToken; ++k) {
413
414 for (l = 1; l <= kMaxToken; ++l) {
415
416 for (m = 1; m <= kMaxToken; ++m) {
417
418 for (n = 1; n <= kMaxToken; ++n) {
419 Parse(pParser, i, NULL);
420 Parse(pParser, j, NULL);
421 Parse(pParser, k, NULL);
422 Parse(pParser, l, NULL);
423 Parse(pParser, m, NULL);
424 Parse(pParser, n, NULL);
425
426 Parse(pParser, 0, NULL);
427 }
428 }
429 }
430 }
431 }
432 }
433 }
434
435 }
436
437
438 // Improved error messages for debugging:
439 // http://stackoverflow.com/questions/11705737/expected-token-using-lemon-parser-generator
440
441 %syntax_error {
442 #ifndef NDEBUG
443 fprintf(stderr,"Parser syntax error.\n");
444 int n = sizeof(yyTokenName) / sizeof(yyTokenName[0]);
445 for (i = 0; i < n; ++i) {
446 int a = yy_find_shift_action(yypParser, (YYCODETYPE)i);
447 if (a < YYNSTATE + YYNRULE) {
448 fprintf(stderr,"expected token: %s\n", yyTokenName[i]);
449 }
450 }
451 #endif
452 }
453
454 %parse_failure {
455 fprintf(stderr, "%d:%d:%d:%d:%d:%d Parser failed to successfully parse.\n", i, j, k, l, m, n);
456 }
457
458