]> begriffs open source - ai-review/blob - critic/yacc.md
frama-c
[ai-review] / critic / yacc.md
1 # Lex & Yacc Critic Framework (Levine, Brown & Mason)
2
3 This framework guides the Critic role when evaluating Lex and Yacc (or Flex and Bison) lexical analyzers and parsers from the perspective of John R. Levine, Doug Brown, and Tony Mason, authors of "Lex & Yacc." This critic focuses on lexer and parser design best practices, grammar correctness, performance optimization, and the fundamental principles that ensure reliable, maintainable, and efficient language processing tools.
4
5 ## Lex & Yacc Evaluation Areas
6
7 ### 1. Lexical Analysis Design (Lex/Flex)
8 **What to Look For:**
9 - Proper regular expression patterns that are unambiguous and efficient
10 - Correct token definitions with appropriate precedence ordering
11 - Proper handling of whitespace, comments, and string literals
12 - Appropriate use of start conditions for context-sensitive lexing
13 - Efficient pattern matching that avoids backtracking
14
15 **Common Problems:**
16 - Ambiguous regular expressions that create lexer conflicts
17 - Inefficient patterns that cause excessive backtracking
18 - Missing or incorrect handling of edge cases (EOF, newlines, escapes)
19 - Poor token precedence leading to incorrect tokenization
20 - Overly complex regular expressions that should be handled in the parser
21
22 **Evaluation Questions:**
23 - Are regular expression patterns unambiguous and well-ordered?
24 - Does the lexer handle all edge cases correctly (EOF, escapes, quotes)?
25 - Are start conditions used appropriately for context-sensitive lexing?
26 - Is the token set complete and properly designed for the grammar?
27 - Are patterns efficient and avoid unnecessary backtracking?
28
29 ### 2. Grammar Design and Structure (Yacc/Bison)
30 **What to Look For:**
31 - Unambiguous grammar rules with proper precedence declarations
32 - Appropriate left/right associativity for operators
33 - Proper handling of operator precedence hierarchies
34 - Correct use of semantic actions and value passing
35 - Well-structured grammar that reflects language semantics
36
37 **Common Problems:**
38 - Shift/reduce and reduce/reduce conflicts due to ambiguous grammar
39 - Missing or incorrect precedence declarations
40 - Improper associativity specifications
41 - Grammar rules that don't reflect intended language structure
42 - Semantic actions that access incorrect grammar symbol values
43
44 **Evaluation Questions:**
45 - Is the grammar unambiguous with all conflicts properly resolved?
46 - Are precedence and associativity declarations correct and complete?
47 - Do grammar rules accurately reflect the intended language structure?
48 - Are semantic actions correctly accessing grammar symbol values?
49 - Is the grammar organized in a logical and maintainable way?
50
51 ### 3. Conflict Resolution and Ambiguity
52 **What to Look For:**
53 - Proper use of `%left`, `%right`, and `%nonassoc` declarations
54 - Appropriate `%prec` directives for resolving specific conflicts
55 - Well-designed grammar rules that minimize conflicts
56 - Correct resolution of dangling-else and similar ambiguities
57 - Proper understanding of when conflicts are acceptable
58
59 **Common Problems:**
60 - Unresolved shift/reduce conflicts that cause incorrect parsing
61 - Reduce/reduce conflicts indicating grammar design problems
62 - Inappropriate use of precedence to force conflict resolution
63 - Missing precedence declarations for operators
64 - Grammar design that creates unnecessary ambiguity
65
66 **Evaluation Questions:**
67 - Are all shift/reduce and reduce/reduce conflicts properly resolved?
68 - Are precedence declarations used correctly and minimally?
69 - Does the conflict resolution match the intended language semantics?
70 - Are grammar rules designed to minimize necessary conflict resolution?
71 - Is the parser deterministic for all valid input?
72
73 ### 4. Semantic Actions and Value Management
74 **What to Look For:**
75 - Correct use of `$$` and `$n` for accessing grammar symbol values
76 - Proper memory management for dynamically allocated semantic values
77 - Appropriate semantic action placement within grammar rules
78 - Correct typing and casting of semantic values
79 - Proper error recovery that maintains semantic consistency
80
81 **Common Problems:**
82 - Incorrect access to grammar symbol values using wrong `$n` indices
83 - Memory leaks from improperly managed semantic values
84 - Semantic actions that modify parser state inappropriately
85 - Type mismatches in semantic value assignments
86 - Missing cleanup in error recovery paths
87
88 **Evaluation Questions:**
89 - Are semantic actions correctly accessing grammar symbol values?
90 - Is memory management for semantic values handled properly?
91 - Do semantic actions maintain appropriate separation from parsing logic?
92 - Are semantic value types consistent throughout the grammar?
93 - Does error recovery properly clean up semantic values?
94
95 ### 5. Error Handling and Recovery
96 **What to Look For:**
97 - Appropriate use of the `error` token for error recovery
98 - Well-placed error recovery points that maintain parse state
99 - Meaningful error messages that help users locate problems
100 - Proper cleanup of semantic values during error recovery
101 - Recovery strategies that allow continued parsing after errors
102
103 **Common Problems:**
104 - Missing or poorly placed error recovery rules
105 - Error recovery that leaves the parser in an inconsistent state
106 - Generic error messages that don't help users understand problems
107 - Memory leaks during error recovery
108 - Error recovery that prevents detection of subsequent errors
109
110 **Evaluation Questions:**
111 - Are error recovery points placed appropriately throughout the grammar?
112 - Do error messages provide useful information for debugging?
113 - Does error recovery maintain parser and semantic consistency?
114 - Are semantic values properly cleaned up during error recovery?
115 - Can the parser continue effectively after error recovery?
116
117 ### 6. Integration and Interface Design
118 **What to Look For:**
119 - Clean interface between lexer and parser (yylex/yyparse)
120 - Proper handling of lexer/parser interaction and state
121 - Appropriate use of global variables and communication mechanisms
122 - Correct integration with the target application
123 - Proper handling of multiple parsing sessions or reentrant parsing
124
125 **Common Problems:**
126 - Tight coupling between lexer and parser that reduces modularity
127 - Global state that prevents reentrant or thread-safe operation
128 - Poor interface design that makes integration difficult
129 - Missing or incorrect initialization and cleanup routines
130 - Hardcoded assumptions about the target application
131
132 **Evaluation Questions:**
133 - Is the interface between lexer and parser clean and well-defined?
134 - Can the parser be used in different contexts without modification?
135 - Are global variables minimized and properly managed?
136 - Is the parser suitable for the intended integration scenario?
137 - Does the design support reentrant or thread-safe operation if needed?
138
139 ### 7. Performance and Optimization
140 **What to Look For:**
141 - Efficient regular expressions that minimize lexer state size
142 - Grammar design that produces efficient parsing tables
143 - Appropriate use of Flex/Bison optimization options
144 - Minimal semantic action overhead
145 - Efficient memory management for large inputs
146
147 **Common Problems:**
148 - Inefficient regular expressions that create large lexer tables
149 - Grammar design that produces inefficient parsing tables
150 - Unnecessary semantic actions that slow down parsing
151 - Poor memory management that affects performance with large inputs
152 - Missing optimization opportunities in lexer/parser configuration
153
154 **Evaluation Questions:**
155 - Are regular expressions designed for optimal lexer performance?
156 - Does the grammar produce efficient parsing tables?
157 - Are semantic actions optimized to minimize parsing overhead?
158 - Is memory usage appropriate for the expected input size?
159 - Are available optimization options used effectively?
160
161 ## Lex & Yacc Specific Criticism Process
162
163 ### Step 1: Lexical Analysis Review
164 1. **Check Pattern Design**: Are regular expressions unambiguous and efficient?
165 2. **Evaluate Token Definitions**: Is the token set complete and well-designed?
166 3. **Assess Edge Case Handling**: Are EOF, escapes, and quotes handled correctly?
167 4. **Review Start Conditions**: Are context-sensitive features used appropriately?
168
169 ### Step 2: Grammar Structure Analysis
170 1. **Check Grammar Ambiguity**: Are there unresolved conflicts in the grammar?
171 2. **Evaluate Precedence Rules**: Are operator precedence and associativity correct?
172 3. **Assess Rule Organization**: Is the grammar logically structured and maintainable?
173 4. **Review Language Mapping**: Do grammar rules reflect intended language semantics?
174
175 ### Step 3: Conflict Resolution Assessment
176 1. **Audit Shift/Reduce Conflicts**: Are all conflicts properly resolved or acceptable?
177 2. **Check Reduce/Reduce Conflicts**: Do these indicate grammar design problems?
178 3. **Evaluate Precedence Usage**: Are precedence declarations used correctly?
179 4. **Assess Ambiguity Resolution**: Does conflict resolution match language intent?
180
181 ### Step 4: Semantic Action Evaluation
182 1. **Check Value Access**: Are `$$` and `$n` used correctly throughout?
183 2. **Evaluate Memory Management**: Are semantic values managed properly?
184 3. **Assess Action Placement**: Are semantic actions placed appropriately?
185 4. **Review Type Consistency**: Are semantic value types used consistently?
186
187 ### Step 5: Error Handling Review
188 1. **Check Error Recovery**: Are error recovery points well-placed and effective?
189 2. **Evaluate Error Messages**: Do error messages provide useful information?
190 3. **Assess Cleanup**: Are semantic values cleaned up during error recovery?
191 4. **Review Recovery Strategy**: Can parsing continue effectively after errors?
192
193 ## Lex & Yacc Specific Criticism Guidelines
194
195 ### Focus on Grammar Design Best Practices
196 **Good Criticism:**
197 - "This grammar rule creates an unnecessary shift/reduce conflict that should be resolved with precedence"
198 - "The regular expression pattern is ambiguous and will match incorrectly in edge cases"
199 - "This semantic action accesses `$3` but the rule only has two symbols"
200 - "The error recovery point is too coarse and won't help users locate the actual error"
201
202 **Poor Criticism:**
203 - "This doesn't look right"
204 - "This seems inefficient"
205 - "I don't like this approach"
206
207 ### Emphasize Deterministic Parsing
208 **Good Criticism:**
209 - "This grammar produces reduce/reduce conflicts that make parsing non-deterministic"
210 - "The precedence declarations don't cover all operators in the precedence hierarchy"
211 - "This regular expression will cause backtracking that affects lexer performance"
212 - "The grammar ambiguity for the dangling-else problem needs explicit resolution"
213
214 **Poor Criticism:**
215 - "This won't work correctly"
216 - "This is not deterministic"
217 - "This might cause problems"
218
219 ### Emphasize Proper Tool Usage
220 **Good Criticism:**
221 - "Use `%left` to declare left-associative operators instead of restructuring the grammar"
222 - "The `error` token should be used for recovery instead of trying to parse all invalid input"
223 - "Start conditions should handle this context-sensitive lexing instead of parser hacks"
224 - "Use `%prec` to resolve this specific conflict instead of changing the grammar structure"
225
226 **Poor Criticism:**
227 - "This tool usage is wrong"
228 - "You should use different features"
229 - "This approach is bad"
230
231 ### Consider Language Processing Quality
232 **Good Criticism:**
233 - "The error recovery doesn't maintain semantic consistency after encountering syntax errors"
234 - "This lexer pattern doesn't handle string escape sequences correctly"
235 - "The semantic actions don't properly construct the abstract syntax tree"
236 - "The grammar doesn't correctly handle operator associativity for this language"
237
238 **Poor Criticism:**
239 - "This has bugs"
240 - "This is unreliable"
241 - "This parser is bad"
242
243 ## Lex & Yacc Specific Problem Categories
244
245 ### Lexical Analysis Problems
246 - **Pattern Ambiguity**: Regular expressions that match ambiguously
247 - **Inefficient Patterns**: Regular expressions that cause performance issues
248 - **Edge Case Failures**: Missing handling of EOF, escapes, or special characters
249 - **Context Insensitivity**: Not using start conditions where needed
250
251 ### Grammar Design Problems
252 - **Shift/Reduce Conflicts**: Ambiguous grammar requiring precedence resolution
253 - **Reduce/Reduce Conflicts**: Grammar design problems causing multiple reductions
254 - **Missing Precedence**: Operator precedence not properly declared
255 - **Poor Structure**: Grammar rules that don't reflect language semantics
256
257 ### Semantic Action Problems
258 - **Incorrect Value Access**: Wrong use of `$$` and `$n` in semantic actions
259 - **Memory Management**: Improper handling of dynamically allocated values
260 - **Type Inconsistency**: Semantic value types not used consistently
261 - **Parser Interference**: Semantic actions that improperly affect parser state
262
263 ### Error Handling Problems
264 - **Poor Recovery**: Missing or ineffective error recovery points
265 - **Inconsistent State**: Error recovery that leaves parser in bad state
266 - **Unclear Messages**: Error messages that don't help users debug
267 - **Resource Leaks**: Missing cleanup during error recovery
268
269 ### Integration Problems
270 - **Tight Coupling**: Lexer and parser too tightly integrated
271 - **Global State**: Excessive use of global variables preventing reuse
272 - **Poor Interface**: Difficult integration with target applications
273 - **Non-Reentrant**: Design that prevents multiple parsing sessions
274
275 ### Performance Problems
276 - **Lexer Inefficiency**: Regular expressions that create large state tables
277 - **Parser Inefficiency**: Grammar that produces inefficient parsing tables
278 - **Action Overhead**: Unnecessary semantic actions that slow parsing
279 - **Memory Issues**: Poor memory management for large inputs
280
281 ## Lex & Yacc Specific Criticism Templates
282
283 ### For Lexical Analysis Issues
284 ```
285 Lexical Issue: [Specific lexer problem]
286 Problem: [How this violates lexical analysis best practices]
287 Impact: [Tokenization errors, performance issues, or maintainability problems]
288 Evidence: [Specific regular expression patterns and tokenization examples]
289 Priority: [Critical/High/Medium/Low]
290 ```
291
292 ### For Grammar Design Issues
293 ```
294 Grammar Issue: [Specific grammar problem]
295 Problem: [What makes this grammar design problematic]
296 Impact: [Parsing errors, conflicts, or semantic issues]
297 Evidence: [Specific grammar rules and conflict examples]
298 Priority: [Critical/High/Medium/Low]
299 ```
300
301 ### For Conflict Resolution Issues
302 ```
303 Conflict Issue: [Specific parsing conflict]
304 Problem: [Why this conflict occurs and how it affects parsing]
305 Impact: [Non-deterministic parsing or incorrect language recognition]
306 Evidence: [Specific conflicts reported by parser generator]
307 Priority: [Critical/High/Medium/Low]
308 ```
309
310 ### For Semantic Action Issues
311 ```
312 Semantic Action Issue: [Specific semantic action problem]
313 Problem: [What makes this semantic action incorrect or inefficient]
314 Impact: [Incorrect semantic values or memory management issues]
315 Evidence: [Specific semantic action code and value handling]
316 Priority: [High/Medium/Low]
317 ```
318
319 ## Lex & Yacc Specific Criticism Best Practices
320
321 ### Do's
322 - **Follow Tool Conventions**: Always follow established Lex and Yacc patterns
323 - **Design for Determinism**: Create unambiguous grammars and lexers
324 - **Use Proper Precedence**: Declare precedence and associativity correctly
325 - **Handle All Cases**: Consider edge cases and error conditions
326 - **Optimize Patterns**: Design efficient regular expressions and grammar rules
327 - **Separate Concerns**: Keep lexical and syntactic analysis properly separated
328 - **Plan for Integration**: Design clean interfaces for target applications
329
330 ### Don'ts
331 - **Ignore Conflicts**: Don't accept unresolved parser conflicts
332 - **Overcomplicate Patterns**: Don't use overly complex regular expressions
333 - **Mix Responsibilities**: Don't handle syntax in the lexer or lexing in the parser
334 - **Assume Perfect Input**: Don't ignore error handling and recovery
335 - **Hardcode Assumptions**: Don't make inflexible assumptions about usage
336 - **Neglect Performance**: Don't ignore lexer and parser efficiency
337 - **Skip Documentation**: Don't leave grammar and lexer patterns undocumented
338
339 ## Lex & Yacc Specific Criticism Checklist
340
341 ### Lexical Analysis Assessment
342 - [ ] Are regular expression patterns unambiguous and well-ordered?
343 - [ ] Does the lexer handle all edge cases correctly (EOF, escapes, quotes)?
344 - [ ] Are start conditions used appropriately for context-sensitive lexing?
345 - [ ] Is the token set complete and properly designed for the grammar?
346 - [ ] Are patterns efficient and avoid unnecessary backtracking?
347
348 ### Grammar Design Assessment
349 - [ ] Is the grammar unambiguous with all conflicts properly resolved?
350 - [ ] Are precedence and associativity declarations correct and complete?
351 - [ ] Do grammar rules accurately reflect the intended language structure?
352 - [ ] Are semantic actions correctly accessing grammar symbol values?
353 - [ ] Is the grammar organized in a logical and maintainable way?
354
355 ### Conflict Resolution Assessment
356 - [ ] Are all shift/reduce and reduce/reduce conflicts properly resolved?
357 - [ ] Are precedence declarations used correctly and minimally?
358 - [ ] Does the conflict resolution match the intended language semantics?
359 - [ ] Are grammar rules designed to minimize necessary conflict resolution?
360 - [ ] Is the parser deterministic for all valid input?
361
362 ### Semantic Action Assessment
363 - [ ] Are semantic actions correctly accessing grammar symbol values?
364 - [ ] Is memory management for semantic values handled properly?
365 - [ ] Do semantic actions maintain appropriate separation from parsing logic?
366 - [ ] Are semantic value types consistent throughout the grammar?
367 - [ ] Does error recovery properly clean up semantic values?
368
369 ### Error Handling Assessment
370 - [ ] Are error recovery points placed appropriately throughout the grammar?
371 - [ ] Do error messages provide useful information for debugging?
372 - [ ] Does error recovery maintain parser and semantic consistency?
373 - [ ] Are semantic values properly cleaned up during error recovery?
374 - [ ] Can the parser continue effectively after error recovery?
375
376 ### Integration Assessment
377 - [ ] Is the interface between lexer and parser clean and well-defined?
378 - [ ] Can the parser be used in different contexts without modification?
379 - [ ] Are global variables minimized and properly managed?
380 - [ ] Is the parser suitable for the intended integration scenario?
381 - [ ] Does the design support reentrant or thread-safe operation if needed?
382
383 ### Performance Assessment
384 - [ ] Are regular expressions designed for optimal lexer performance?
385 - [ ] Does the grammar produce efficient parsing tables?
386 - [ ] Are semantic actions optimized to minimize parsing overhead?
387 - [ ] Is memory usage appropriate for the expected input size?
388 - [ ] Are available optimization options used effectively?
389
390 ## Lex & Yacc Specific Evaluation Questions
391
392 ### For Any Lex & Yacc Project
393 1. **Does this lexer/parser correctly recognize the intended language?**
394 2. **Are all grammar conflicts properly resolved or acceptable?**
395 3. **Is the lexical analysis design efficient and unambiguous?**
396 4. **Are semantic actions correctly implemented and efficient?**
397 5. **Is error handling comprehensive and user-friendly?**
398 6. **Is the parser suitable for integration with the target application?**
399 7. **Does the design scale appropriately for expected input sizes?**
400 8. **Are the lexer and parser properly modularized?**
401 9. **Is the grammar well-documented and maintainable?**
402 10. **Does the implementation follow Lex & Yacc best practices?**
403
404 ### For Language Implementation Projects
405 1. **Does the grammar accurately reflect the language specification?**
406 2. **Are all language constructs properly handled in the lexer and parser?**
407 3. **Is operator precedence and associativity correctly implemented?**
408 4. **Are language-specific features (comments, strings, etc.) handled correctly?**
409 5. **Does the semantic analysis properly construct language representations?**
410
411 ### For Domain-Specific Language Projects
412 1. **Is the grammar designed for the intended domain users?**
413 2. **Are error messages meaningful for domain experts rather than parser experts?**
414 3. **Does the lexer handle domain-specific notation and conventions?**
415 4. **Is the parser extensible for future domain requirements?**
416 5. **Are performance characteristics appropriate for typical domain inputs?**
417
418 ## Lex & Yacc Tool Principles Applied
419
420 ### "Separation of Concerns"
421 - Lexical analysis should handle tokenization, not syntax
422 - Parser should handle syntax, not character-level processing
423 - Semantic actions should build representations, not parse
424 - Error recovery should be separate from normal parsing logic
425
426 ### "Deterministic Recognition"
427 - Grammars should be unambiguous and produce deterministic parsers
428 - Regular expressions should match unambiguously
429 - Conflict resolution should be explicit and correct
430 - Parser behavior should be predictable for all valid inputs
431
432 ### "Efficient Implementation"
433 - Regular expressions should be designed for optimal state machines
434 - Grammar should produce efficient parsing tables
435 - Semantic actions should minimize overhead during parsing
436 - Memory management should be appropriate for input characteristics
437
438 ### "Proper Tool Usage"
439 - Use precedence declarations instead of grammar restructuring
440 - Use start conditions for context-sensitive lexing
441 - Use error token for recovery instead of trying to parse all input
442 - Use tool features as intended rather than working around them
443
444 ### "Clean Integration"
445 - Lexer and parser should have clean, well-defined interfaces
446 - Global state should be minimized to allow reuse
447 - Integration with target applications should be straightforward
448 - Design should support different usage scenarios
449
450 ### "Comprehensive Error Handling"
451 - Error recovery should be placed at appropriate grammar points
452 - Error messages should help users locate and understand problems
453 - Recovery should maintain parser and semantic consistency
454 - Cleanup should prevent resource leaks during error conditions
455
456 ## Lex & Yacc API Evaluation Criteria
457
458 ### Lex/Flex Functions and Features
459 - **Pattern Matching**: Proper regular expression design and ordering
460 - **Start Conditions**: Appropriate use of `%s` and `%x` for context sensitivity
461 - **Actions**: Correct token return and semantic value assignment
462 - **Input Handling**: Proper use of `input()`, `unput()`, and `yytext`
463
464 ### Yacc/Bison Functions and Features
465 - **Grammar Rules**: Proper BNF rule structure and organization
466 - **Precedence Declarations**: Correct use of `%left`, `%right`, `%nonassoc`
467 - **Semantic Actions**: Proper use of `$$` and `$n` for value management
468 - **Error Handling**: Appropriate use of `error` token and recovery strategies
469
470 ### Integration Functions
471 - **yylex()**: Proper lexer function interface and token return
472 - **yyparse()**: Correct parser function usage and return values
473 - **yyerror()**: Appropriate error reporting function implementation
474 - **yylval**: Correct semantic value communication between lexer and parser
475
476 ### Memory Management Functions
477 - **malloc/free**: Proper dynamic memory allocation in semantic actions
478 - **String Handling**: Correct string duplication and cleanup
479 - **AST Management**: Appropriate abstract syntax tree construction and cleanup
480 - **Error Cleanup**: Proper resource cleanup during error recovery
481
482 ### Optimization Features
483 - **Flex Options**: Appropriate use of performance and compatibility options
484 - **Bison Options**: Correct use of parser generation and optimization flags
485 - **Table Compression**: Proper use of space/time optimization tradeoffs
486 - **Reentrant Parsing**: Appropriate use of reentrant parser features when needed