diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2018-12-11 06:00:49 -0500 |
---|---|---|
committer | Masahiro Yamada <yamada.masahiro@socionext.com> | 2018-12-12 10:18:54 -0500 |
commit | cc66bca775eeb81ef24456338bcd97e2e780c236 (patch) | |
tree | 00309c147f287d6706e31a08b211ad4697997533 /scripts/kconfig | |
parent | 21c5ecf60472be9f1b5bfe0b94870bef93db4202 (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.l | 21 | ||||
-rw-r--r-- | scripts/kconfig/zconf.y | 18 |
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 | ||
21 | static struct { | 23 | static struct { |
@@ -23,6 +25,7 @@ static struct { | |||
23 | int lineno; | 25 | int lineno; |
24 | } current_pos; | 26 | } current_pos; |
25 | 27 | ||
28 | static int prev_token = T_EOL; | ||
26 | static char *text; | 29 | static char *text; |
27 | static int text_size, text_asize; | 30 | static 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 */ | ||
276 | int yylex(void) | ||
277 | { | ||
278 | int token; | ||
279 | |||
280 | repeat: | ||
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 | |||
271 | static char *expand_token(const char *in, size_t n) | 292 | static 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]; | |||
31 | static struct menu *current_menu, *current_entry; | 31 | static 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 | %% |
114 | input: nl start | start; | 114 | input: mainmenu_stmt stmt_list | stmt_list; |
115 | |||
116 | start: 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 | ||
143 | common_stmt: | 141 | common_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 | ||
199 | config_option: T_TYPE prompt_stmt_opt T_EOL | 195 | config_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 | |||
443 | depends_list: | 438 | depends_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 | |||
458 | visibility_list: | 452 | visibility_list: |
459 | /* empty */ | 453 | /* empty */ |
460 | | visibility_list visible | 454 | | visibility_list visible |
461 | | visibility_list T_EOL | ||
462 | ; | 455 | ; |
463 | 456 | ||
464 | visible: T_VISIBLE if_expr T_EOL | 457 | visible: 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 | ||
487 | nl: | ||
488 | T_EOL | ||
489 | | nl T_EOL | ||
490 | ; | ||
491 | |||
492 | if_expr: /* empty */ { $$ = NULL; } | 480 | if_expr: /* empty */ { $$ = NULL; } |
493 | | T_IF expr { $$ = $2; } | 481 | | T_IF expr { $$ = $2; } |
494 | ; | 482 | ; |