From dc2ae5078cb0e265381cafe860f0c64ee1cdafbd Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Sun, 23 Nov 2025 21:59:12 +0100 Subject: [PATCH] Berry Force left bracket without spaces for calls (#24154) --- lib/libesp32/berry/src/be_lexer.c | 10 ++++++++-- lib/libesp32/berry/src/be_lexer.h | 7 ++++--- lib/libesp32/berry/src/be_parser.c | 20 +++++++++++++------- lib/libesp32/berry/tools/coc/str_build.py | 2 +- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/lib/libesp32/berry/src/be_lexer.c b/lib/libesp32/berry/src/be_lexer.c index 36afaa6c1..8be1b5372 100644 --- a/lib/libesp32/berry/src/be_lexer.c +++ b/lib/libesp32/berry/src/be_lexer.c @@ -36,7 +36,7 @@ static const char* const kwords_tab[] = { "^=", "<<=", ">>=", "+", "-", "*", "/", "%", "<", "<=", "==", "!=", ">", ">=", "&", "|", "^", "<<", ">>", "..", "&&", "||", "!", "~", - "(", ")", "[", "]", "{", "}", ".", ",", ";", + "(", "(", ")", "[", "]", "{", "}", ".", ",", ";", ":", "?", "->", "if", "elif", "else", "while", "for", "def", "end", "class", "break", "continue", "return", "true", "false", "nil", "var", "do", @@ -686,6 +686,7 @@ static int skip_delimiter(blexer *lexer) { c = lgetc(lexer); delimeter_present = 1; } + lexer->had_whitespace = delimeter_present; return delimeter_present; } @@ -791,12 +792,15 @@ static btokentype lexer_next(blexer *lexer) switch (lgetc(lexer)) { case '\r': case '\n': /* newline */ skip_newline(lexer); + lexer->had_whitespace = 1; break; case ' ': case '\t': case '\f': case '\v': /* spaces */ next(lexer); + lexer->had_whitespace = 1; break; case '#': /* comment */ skip_comment(lexer); + lexer->had_whitespace = 1; break; case EOS: return TokenEOS; /* end of source stream */ /* operator */ @@ -805,7 +809,7 @@ static btokentype lexer_next(blexer *lexer) case '*': return scan_assign(lexer, OptMulAssign, OptMul); case '/': return scan_assign(lexer, OptDivAssign, OptDiv); case '%': return scan_assign(lexer, OptModAssign, OptMod); - case '(': next(lexer); return OptLBK; + case '(': next(lexer); return lexer->had_whitespace ? OptSpaceLBK : OptCallLBK; case ')': next(lexer); return OptRBK; case '[': next(lexer); return OptLSB; case ']': next(lexer); return OptRSB; @@ -865,6 +869,7 @@ void be_lexer_init(blexer *lexer, bvm *vm, lexer->reader.readf = reader; lexer->reader.data = data; lexer->reader.len = 0; + lexer->had_whitespace = 1; /* start with whitespace state */ lexerbuf_init(lexer); keyword_registe(vm); lexer->strtab = be_map_new(vm); @@ -892,6 +897,7 @@ int be_lexer_scan_next(blexer *lexer) return 0; } lexer->lastline = lexer->linenumber; + lexer->had_whitespace = 0; /* reset whitespace flag before scanning */ type = lexer_next(lexer); clear_buf(lexer); if (type != TokenNone) { diff --git a/lib/libesp32/berry/src/be_lexer.h b/lib/libesp32/berry/src/be_lexer.h index fdbcc1d4f..4549a0460 100644 --- a/lib/libesp32/berry/src/be_lexer.h +++ b/lib/libesp32/berry/src/be_lexer.h @@ -54,7 +54,8 @@ typedef enum { OptNot, /* operator, ! */ OptFlip, /* operator, ~ */ /* postfix operator or bracket */ - OptLBK, /* operator, ( bracket */ + OptSpaceLBK, /* operator, ( bracket (with space/newline before) */ + OptCallLBK, /* operator, ( bracket (call - no space before) */ OptRBK, /* operator, ) bracket */ OptLSB, /* operator, [ square bracket */ OptRSB, /* operator, ] square bracket */ @@ -67,6 +68,7 @@ typedef enum { OptColon, /* operator, : */ OptQuestion, /* operator, ? */ OptArrow, /* operator, -> */ + OptWalrus, /* operator, := */ /* keyword */ KeyIf, /* keyword if */ KeyElif, /* keyword elif */ @@ -90,8 +92,6 @@ typedef enum { KeyExcept, /* keyword except */ KeyRaise, /* keyword raise */ KeyStatic, /* keyword static */ - /* Walrus operator */ - OptWalrus, /* operator, := */ } btokentype; struct blexerreader { @@ -126,6 +126,7 @@ typedef struct blexer { struct blexerreader reader; bmap *strtab; bvm *vm; + int had_whitespace; /* track if whitespace/newline preceded current token */ } blexer; void be_lexer_init(blexer *lexer, bvm *vm, diff --git a/lib/libesp32/berry/src/be_parser.c b/lib/libesp32/berry/src/be_parser.c index 96144483b..f5f70111e 100644 --- a/lib/libesp32/berry/src/be_parser.c +++ b/lib/libesp32/berry/src/be_parser.c @@ -595,7 +595,12 @@ static void func_varlist(bparser *parser) /* '(' [ ID {',' ID}] ')' or */ /* '(' '*' ID ')' or */ /* '(' [ ID {',' ID}] ',' '*' ID ')' */ - match_token(parser, OptLBK); /* skip '(' */ + btokentype type_lbk = next_type(parser); + if ((type_lbk == OptSpaceLBK) || (type_lbk == OptCallLBK)) { + match_token(parser, type_lbk); /* skip '(' */ + } else { + match_token(parser, OptCallLBK); /* raise error */ + } if (next_type(parser) == OptMul) { func_vararg(parser); } else if (match_id(parser, str) != NULL) { @@ -837,8 +842,8 @@ static void member_expr(bparser *parser, bexpdesc *e) init_exp(&key, ETSTRING, 0); key.v.s = str; be_code_member(parser->finfo, e, &key); - } else if (next_type(parser) == OptLBK) { - scan_next_token(parser); /* skip '(' */ + } else if (next_type(parser) == OptCallLBK) { + scan_next_token(parser); /* skip '(' - must be no space before */ bexpdesc key; expr(parser, &key); check_var(parser, &key); @@ -897,7 +902,8 @@ static void simple_expr(bparser *parser, bexpdesc *e) static void primary_expr(bparser *parser, bexpdesc *e) { switch (next_type(parser)) { - case OptLBK: /* '(' expr ')' */ + case OptSpaceLBK: /* '(' expr ')' - grouping parentheses only */ + case OptCallLBK: /* '(' expr ')' - following a symbol */ scan_next_token(parser); /* skip '(' */ expr(parser, e); check_var(parser, e); @@ -926,7 +932,7 @@ static void suffix_expr(bparser *parser, bexpdesc *e) primary_expr(parser, e); for (;;) { switch (next_type(parser)) { - case OptLBK: /* '(' function call */ + case OptCallLBK: /* '(' function call - no space before */ call_expr(parser, e); break; case OptDot: /* '.' member */ @@ -1355,7 +1361,7 @@ static void continue_stmt(bparser *parser) static bbool isoverloadable(btokentype type) { return (type >= OptAdd && type <= OptConnect) /* overloaded binary operator */ - || type == OptFlip || type == OptLBK; /* '~' and '()' operator */ + || type == OptFlip || type == OptSpaceLBK; /* '~' and '()' operator */ } static bstring* func_name(bparser* parser, bexpdesc* e, int ismethod) @@ -1376,7 +1382,7 @@ static bstring* func_name(bparser* parser, bexpdesc* e, int ismethod) return parser_newstr(parser, "-*"); } /* '()' call operator */ - if (type == OptLBK && next_type(parser) == OptRBK) { + if ((type == OptSpaceLBK) && next_type(parser) == OptRBK) { scan_next_token(parser); /* skip ')' */ return parser_newstr(parser, "()"); } diff --git a/lib/libesp32/berry/tools/coc/str_build.py b/lib/libesp32/berry/tools/coc/str_build.py index b8380bf57..7b00f6f35 100644 --- a/lib/libesp32/berry/tools/coc/str_build.py +++ b/lib/libesp32/berry/tools/coc/str_build.py @@ -62,7 +62,7 @@ class str_build: return size def keywords(self): - opif = 50 + opif = 52 tab = { "if": opif, "elif": opif + 1 , "else": opif + 2 , "while": opif + 3 ,