diff --git a/CHANGES.current b/CHANGES.current index 5796308df..6bc4f9fcd 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,12 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.2.0 (in progress) =========================== +2023-06-07: olly + #2630 Fix parsing of <= and >= in templated lambda. + + Skipping between matching delimiters is now done at the token level + rather than the character level. + 2023-06-02: mmomtchev [Javascript] #2622 Fix support for %typemap(default) and improve support for default arguments in general. diff --git a/Examples/test-suite/cpp20_lambda_template.i b/Examples/test-suite/cpp20_lambda_template.i index 5672bd1b7..61b59dfff 100644 --- a/Examples/test-suite/cpp20_lambda_template.i +++ b/Examples/test-suite/cpp20_lambda_template.i @@ -9,4 +9,8 @@ %inline %{ #include auto templated_lambda = [](std::vector t){}; + +// Regression test for parsing bug fixed in SWIG 4.2.0 (#2630) +auto y = []=2> { return 1; }; +auto z = [] { return 1; }; %} diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c index 63d38ec62..086be1836 100644 --- a/Source/Swig/scanner.c +++ b/Source/Swig/scanner.c @@ -1554,126 +1554,55 @@ void Scanner_skip_line(Scanner *s) { * ----------------------------------------------------------------------------- */ int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) { - char c; - int num_levels = 1; - int state = 0; - String *locator = 0; - Clear(s->text); - Setfile(s->text, Getfile(s->str)); - Setline(s->text, s->line); + int old_line = s->line; + long position = Tell(s->str); - Putc((char)startchar, s->text); - while (num_levels > 0) { - if ((c = nextchar(s)) == 0) { - Delete(locator); - return -1; - } - switch (state) { - case 0: - if (c == startchar) - num_levels++; - else if (c == endchar) - num_levels--; - else if (c == '/') - state = 10; - else if (c == '\"') - state = 20; - else if (c == '\'') - state = 30; + int num_levels = 1; + int starttok, endtok; + switch (endchar) { + case '}': + starttok = SWIG_TOKEN_LBRACE; + endtok = SWIG_TOKEN_RBRACE; break; - case 10: - if (c == '/') - state = 11; - else if (c == '*') - state = 12; - else if (c == startchar) { - state = 0; - num_levels++; - } - else - state = 0; + case ')': + starttok = SWIG_TOKEN_LPAREN; + endtok = SWIG_TOKEN_RPAREN; break; - case 11: - if (c == '\n') - state = 0; - else - state = 11; + case ']': + starttok = SWIG_TOKEN_LBRACKET; + endtok = SWIG_TOKEN_RBRACKET; break; - case 12: /* first character inside C comment */ - if (c == '*') - state = 14; - else if (c == '@') - state = 40; - else - state = 13; - break; - case 13: - if (c == '*') - state = 14; - break; - case 14: /* possible end of C comment */ - if (c == '*') - state = 14; - else if (c == '/') - state = 0; - else - state = 13; - break; - case 20: - if (c == '\"') - state = 0; - else if (c == '\\') - state = 21; - break; - case 21: - state = 20; - break; - case 30: - if (c == '\'') - state = 0; - else if (c == '\\') - state = 31; - break; - case 31: - state = 30; - break; - /* 40-45 SWIG locator checks - a C comment with contents starting: @SWIG */ - case 40: - state = (c == 'S') ? 41 : (c == '*') ? 14 : 13; - break; - case 41: - state = (c == 'W') ? 42 : (c == '*') ? 14 : 13; - break; - case 42: - state = (c == 'I') ? 43 : (c == '*') ? 14 : 13; - break; - case 43: - state = (c == 'G') ? 44 : (c == '*') ? 14 : 13; - if (c == 'G') { - Delete(locator); - locator = NewString("/*@SWIG"); - } - break; - case 44: - if (c == '*') - state = 45; - Putc(c, locator); - break; - case 45: /* end of SWIG locator in C comment */ - if (c == '/') { - state = 0; - Putc(c, locator); - Scanner_locator(s, locator); - } else { - /* malformed locator */ - state = (c == '*') ? 14 : 13; - } + case '>': + starttok = SWIG_TOKEN_LESSTHAN; + endtok = SWIG_TOKEN_GREATERTHAN; break; default: - break; + assert(0); + } + + while (1) { + int tok = Scanner_token(s); + if (tok == starttok) { + num_levels++; + } else if (tok == endtok) { + if (--num_levels == 0) break; + } else if (tok == SWIG_TOKEN_COMMENT) { + char *loc = Char(s->text); + if (strncmp(loc, "/*@SWIG", 7) == 0 && loc[Len(s->text)-3] == '@') { + Scanner_locator(s, s->text); + } + } else if (tok == 0) { + return -1; } } - Delete(locator); + + Delete(s->text); + s->text = NewStringWithSize(Char(s->str) + position - 1, + Tell(s->str) - position + 1); + Char(s->text)[0] = startchar; + Setfile(s->text, Getfile(s->str)); + Setline(s->text, old_line); + return 0; } @@ -1684,105 +1613,66 @@ int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) { * ----------------------------------------------------------------------------- */ String *Scanner_get_raw_text_balanced(Scanner *s, int startchar, int endchar) { - String *result = 0; - char c; + String *result = NULL; int old_line = s->line; String *old_text = Copy(s->text); long position = Tell(s->str); int num_levels = 1; - int state = 0; - Clear(s->text); - Setfile(s->text, Getfile(s->str)); - Setline(s->text, s->line); - Putc((char)startchar, s->text); - while (num_levels > 0) { - if ((c = nextchar(s)) == 0) { - Clear(s->text); - Append(s->text, old_text); - Delete(old_text); - s->line = old_line; - return 0; - } - switch (state) { - case 0: - if (c == startchar) - num_levels++; - else if (c == endchar) - num_levels--; - else if (c == '/') - state = 10; - else if (c == '\"') - state = 20; - else if (c == '\'') - state = 30; + int starttok, endtok; + switch (endchar) { + case '}': + starttok = SWIG_TOKEN_LBRACE; + endtok = SWIG_TOKEN_RBRACE; break; - case 10: - if (c == '/') - state = 11; - else if (c == '*') - state = 12; - else if (c == startchar) { - state = 0; - num_levels++; - } - else - state = 0; + case ')': + starttok = SWIG_TOKEN_LPAREN; + endtok = SWIG_TOKEN_RPAREN; break; - case 11: - if (c == '\n') - state = 0; - else - state = 11; + case ']': + starttok = SWIG_TOKEN_LBRACKET; + endtok = SWIG_TOKEN_RBRACKET; break; - case 12: /* first character inside C comment */ - if (c == '*') - state = 14; - else - state = 13; - break; - case 13: - if (c == '*') - state = 14; - break; - case 14: /* possible end of C comment */ - if (c == '*') - state = 14; - else if (c == '/') - state = 0; - else - state = 13; - break; - case 20: - if (c == '\"') - state = 0; - else if (c == '\\') - state = 21; - break; - case 21: - state = 20; - break; - case 30: - if (c == '\'') - state = 0; - else if (c == '\\') - state = 31; - break; - case 31: - state = 30; + case '>': + starttok = SWIG_TOKEN_LESSTHAN; + endtok = SWIG_TOKEN_GREATERTHAN; break; default: + assert(0); + } + + while (1) { + int tok = Scanner_token(s); + if (tok == starttok) { + num_levels++; + } else if (tok == endtok) { + if (--num_levels == 0) { + result = NewStringWithSize(Char(s->str) + position - 1, + Tell(s->str) - position + 1); + Char(result)[0] = startchar; + Setfile(result, Getfile(s->str)); + Setline(result, old_line); + break; + } + } else if (tok == SWIG_TOKEN_COMMENT) { + char *loc = Char(s->text); + if (strncmp(loc, "/*@SWIG", 7) == 0 && loc[Len(s->text)-3] == '@') { + Scanner_locator(s, s->text); + } + } else if (tok == 0) { break; } } + + /* Reset the scanner state. */ Seek(s->str, position, SEEK_SET); - result = Copy(s->text); - Clear(s->text); - Append(s->text, old_text); - Delete(old_text); + Delete(s->text); + s->text = old_text; s->line = old_line; + return result; } + /* ----------------------------------------------------------------------------- * Scanner_isoperator() *