History

kconfig: fix ambiguous grammar in terms of new lines

This commit decreases 8 shift/reduce conflicts. A certain amount of grammatical ambiguity comes from how to reduce excessive T_EOL tokens. Let's take a look at the example code below: 1 config A 2 bool "a" 3 4 depends on B 5 6 config B 7 def_bool y The line 3 is melt into "config_option_list", but the line 5 can be either a part of "config_option_list" or "common_stmt" by itself. Currently, the lexer converts '\n' to T_EOL verbatim. In Kconfig, a new line works as a statement terminator, but new lines in empty lines are not critical since empty lines (or lines that contain only whitespaces/comments) are just no-op. If the lexer simply discards no-op lines, the parser will not be bothered by excessive T_EOL tokens. Of course, this means we are shifting the complexity from the parser to the lexer, but it is much easier than tackling on shift/reduce conflicts. I introduced the second stage lexer to tweak the behavior. Discard T_EOL if the previous token is T_EOL or T_HELPTEXT. Two T_EOL tokens in a row is meaningless. T_HELPTEXT is a special token that is reduced without T_EOL.

Masahiro Yamada committed 7 years ago

Commit cc66bca1 parent 21c5ecf2 files · +24 −15Browse files

Unified · Split

2 files
  1. scripts/kconfig/zconf.l +21 −0
  2. scripts/kconfig/zconf.y +3 −15
scripts/kconfig/zconf.l+21−0
@@ -16,6 +16,8 @@ · 15 unmodified lines
16 16
17#include "lkc.h"17#include "lkc.h"
18 18
19#define YY_DECL static int yylex1(void)
20
19#define START_STRSIZE 1621#define START_STRSIZE 16
20 22
21static struct {23static struct {
@@ -23,6 +25,7 @@ static struct { · 1 unmodified line
23 int lineno;25 int lineno;
24} current_pos;26} current_pos;
25 27
28static int prev_token = T_EOL;
26static char *text;29static char *text;
27static int text_size, text_asize;30static int text_size, text_asize;
28 31
@@ -268,6 +271,24 @@ n [A-Za-z0-9_-] · 239 unmodified lines
268}271}
269 272
270%%273%%
274
275/* second stage lexer */
276int yylex(void)
277{
278 int token;
279
280repeat:
281 token = yylex1();
282
283 /* Do not pass unneeded T_EOL to the parser. */
284 if ((prev_token == T_EOL || prev_token == T_HELPTEXT) && token == T_EOL)
285 goto repeat;
286
287 prev_token = token;
288
289 return token;
290}
291
271static char *expand_token(const char *in, size_t n)292static char *expand_token(const char *in, size_t n)
272{293{
273 char *out;294 char *out;
scripts/kconfig/zconf.y+3−15
@@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE]; · 30 unmodified lines
31static struct menu *current_menu, *current_entry;31static struct menu *current_menu, *current_entry;
32 32
33%}33%}
34%expect 2934%expect 21
35 35
36%union36%union
37{37{
@@ -111,9 +111,7 @@ static struct menu *current_menu, *current_entry; · 73 unmodified lines
111%}111%}
112 112
113%%113%%
114input: nl start | start;114input: mainmenu_stmt stmt_list | stmt_list;
115
116start: mainmenu_stmt stmt_list | stmt_list;
117 115
118/* mainmenu entry */116/* mainmenu entry */
119 117
@@ -141,8 +139,7 @@ option_name: · 21 unmodified lines
141;139;
142 140
143common_stmt:141common_stmt:
144 T_EOL142 if_stmt
145 | if_stmt
146 | comment_stmt143 | comment_stmt
147 | config_stmt144 | config_stmt
148 | menuconfig_stmt145 | menuconfig_stmt
@@ -193,7 +190,6 @@ config_option_list: · 44 unmodified lines
193 | config_option_list depends190 | config_option_list depends
194 | config_option_list help191 | config_option_list help
195 | config_option_list option_error192 | config_option_list option_error
196 | config_option_list T_EOL
197;193;
198 194
199config_option: T_TYPE prompt_stmt_opt T_EOL195config_option: T_TYPE prompt_stmt_opt T_EOL
@@ -293,7 +289,6 @@ choice_option_list: · 93 unmodified lines
293 | choice_option_list choice_option289 | choice_option_list choice_option
294 | choice_option_list depends290 | choice_option_list depends
295 | choice_option_list help291 | choice_option_list help
296 | choice_option_list T_EOL
297 | choice_option_list option_error292 | choice_option_list option_error
298;293;
299 294
@@ -443,7 +438,6 @@ help: help_start T_HELPTEXT · 143 unmodified lines
443depends_list:438depends_list:
444 /* empty */439 /* empty */
445 | depends_list depends440 | depends_list depends
446 | depends_list T_EOL
447 | depends_list option_error441 | depends_list option_error
448;442;
449 443
@@ -458,7 +452,6 @@ depends: T_DEPENDS T_ON expr T_EOL · 8 unmodified lines
458visibility_list:452visibility_list:
459 /* empty */453 /* empty */
460 | visibility_list visible454 | visibility_list visible
461 | visibility_list T_EOL
462;455;
463 456
464visible: T_VISIBLE if_expr T_EOL457visible: T_VISIBLE if_expr T_EOL
@@ -484,11 +477,6 @@ end: T_ENDMENU T_EOL { $$ = $1; } · 19 unmodified lines
484 | T_ENDIF T_EOL { $$ = $1; }477 | T_ENDIF T_EOL { $$ = $1; }
485;478;
486 479
487nl:
488 T_EOL
489 | nl T_EOL
490;
491
492if_expr: /* empty */ { $$ = NULL; }480if_expr: /* empty */ { $$ = NULL; }
493 | T_IF expr { $$ = $2; }481 | T_IF expr { $$ = $2; }
494;482;