path: root/scripts/kconfig/zconf.l
diff options
authorMasahiro Yamada <yamada.masahiro@socionext.com>2018-12-11 20:00:49 +0900
committerMasahiro Yamada <yamada.masahiro@socionext.com>2018-12-13 00:18:54 +0900
commitcc66bca775eeb81ef24456338bcd97e2e780c236 (patch)
tree00309c147f287d6706e31a08b211ad4697997533 /scripts/kconfig/zconf.l
parentkconfig: refactor pattern matching in STRING state (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/zconf.l')
1 files changed, 21 insertions, 0 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 @@
#include "lkc.h"
+#define YY_DECL static int yylex1(void)
#define START_STRSIZE 16
static struct {
@@ -23,6 +25,7 @@ static struct {
int lineno;
} current_pos;
+static int prev_token = T_EOL;
static char *text;
static int text_size, text_asize;
@@ -268,6 +271,24 @@ n [A-Za-z0-9_-]
+/* second stage lexer */
+int yylex(void)
+ int token;
+ token = yylex1();
+ /* Do not pass unneeded T_EOL to the parser. */
+ if ((prev_token == T_EOL || prev_token == T_HELPTEXT) && token == T_EOL)
+ goto repeat;
+ prev_token = token;
+ return token;
static char *expand_token(const char *in, size_t n)
char *out;