summaryrefslogtreecommitdiffstats
path: root/scripts/kconfig
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.masahiro@socionext.com>2018-12-11 06:00:49 -0500
committerMasahiro Yamada <yamada.masahiro@socionext.com>2018-12-12 10:18:54 -0500
commitcc66bca775eeb81ef24456338bcd97e2e780c236 (patch)
tree00309c147f287d6706e31a08b211ad4697997533 /scripts/kconfig
parent21c5ecf60472be9f1b5bfe0b94870bef93db4202 (diff)
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. Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Diffstat (limited to 'scripts/kconfig')
-rw-r--r--scripts/kconfig/zconf.l21
-rw-r--r--scripts/kconfig/zconf.y18
2 files changed, 24 insertions, 15 deletions
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l
index b7bc164fdf00..847ba4248092 100644
--- a/scripts/kconfig/zconf.l
+++ b/scripts/kconfig/zconf.l
@@ -16,6 +16,8 @@
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 16 21#define START_STRSIZE 16
20 22
21static struct { 23static struct {
@@ -23,6 +25,7 @@ static struct {
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_-]
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;
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index c28f1a8f721d..02bfc62ba92c 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE];
31static struct menu *current_menu, *current_entry; 31static struct menu *current_menu, *current_entry;
32 32
33%} 33%}
34%expect 29 34%expect 21
35 35
36%union 36%union
37{ 37{
@@ -111,9 +111,7 @@ static struct menu *current_menu, *current_entry;
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:
141; 139;
142 140
143common_stmt: 141common_stmt:
144 T_EOL 142 if_stmt
145 | if_stmt
146 | comment_stmt 143 | comment_stmt
147 | config_stmt 144 | config_stmt
148 | menuconfig_stmt 145 | menuconfig_stmt
@@ -193,7 +190,6 @@ config_option_list:
193 | config_option_list depends 190 | config_option_list depends
194 | config_option_list help 191 | config_option_list help
195 | config_option_list option_error 192 | config_option_list option_error
196 | config_option_list T_EOL
197; 193;
198 194
199config_option: T_TYPE prompt_stmt_opt T_EOL 195config_option: T_TYPE prompt_stmt_opt T_EOL
@@ -293,7 +289,6 @@ choice_option_list:
293 | choice_option_list choice_option 289 | choice_option_list choice_option
294 | choice_option_list depends 290 | choice_option_list depends
295 | choice_option_list help 291 | choice_option_list help
296 | choice_option_list T_EOL
297 | choice_option_list option_error 292 | choice_option_list option_error
298; 293;
299 294
@@ -443,7 +438,6 @@ help: help_start T_HELPTEXT
443depends_list: 438depends_list:
444 /* empty */ 439 /* empty */
445 | depends_list depends 440 | depends_list depends
446 | depends_list T_EOL
447 | depends_list option_error 441 | depends_list option_error
448; 442;
449 443
@@ -458,7 +452,6 @@ depends: T_DEPENDS T_ON expr T_EOL
458visibility_list: 452visibility_list:
459 /* empty */ 453 /* empty */
460 | visibility_list visible 454 | visibility_list visible
461 | visibility_list T_EOL
462; 455;
463 456
464visible: T_VISIBLE if_expr T_EOL 457visible: T_VISIBLE if_expr T_EOL
@@ -484,11 +477,6 @@ end: T_ENDMENU T_EOL { $$ = $1; }
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;