Fix parsing of <= and >= in templated lambda

Skipping between matching delimiters is now done at the token level
rather than the character level.

Partly addresses #2630
This commit is contained in:
Olly Betts 2023-06-07 11:37:45 +12:00
parent 94ba29410c
commit 40033f8498
3 changed files with 94 additions and 194 deletions

View File

@ -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) 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 2023-06-02: mmomtchev
[Javascript] #2622 Fix support for %typemap(default) and improve [Javascript] #2622 Fix support for %typemap(default) and improve
support for default arguments in general. support for default arguments in general.

View File

@ -9,4 +9,8 @@
%inline %{ %inline %{
#include <vector> #include <vector>
auto templated_lambda = []<typename T>(std::vector<T> t){}; auto templated_lambda = []<typename T>(std::vector<T> t){};
// Regression test for parsing bug fixed in SWIG 4.2.0 (#2630)
auto y = []<bool X = 1>=2> { return 1; };
auto z = []<bool X = 1<=2> { return 1; };
%} %}

View File

@ -1554,126 +1554,55 @@ void Scanner_skip_line(Scanner *s) {
* ----------------------------------------------------------------------------- */ * ----------------------------------------------------------------------------- */
int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) { int Scanner_skip_balanced(Scanner *s, int startchar, int endchar) {
char c; int old_line = s->line;
int num_levels = 1; long position = Tell(s->str);
int state = 0;
String *locator = 0;
Clear(s->text);
Setfile(s->text, Getfile(s->str));
Setline(s->text, s->line);
Putc((char)startchar, s->text); int num_levels = 1;
while (num_levels > 0) { int starttok, endtok;
if ((c = nextchar(s)) == 0) { switch (endchar) {
Delete(locator); case '}':
return -1; starttok = SWIG_TOKEN_LBRACE;
} endtok = SWIG_TOKEN_RBRACE;
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;
break; break;
case 10: case ')':
if (c == '/') starttok = SWIG_TOKEN_LPAREN;
state = 11; endtok = SWIG_TOKEN_RPAREN;
else if (c == '*')
state = 12;
else if (c == startchar) {
state = 0;
num_levels++;
}
else
state = 0;
break; break;
case 11: case ']':
if (c == '\n') starttok = SWIG_TOKEN_LBRACKET;
state = 0; endtok = SWIG_TOKEN_RBRACKET;
else
state = 11;
break; break;
case 12: /* first character inside C comment */ case '>':
if (c == '*') starttok = SWIG_TOKEN_LESSTHAN;
state = 14; endtok = SWIG_TOKEN_GREATERTHAN;
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;
}
break; break;
default: 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; 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 *Scanner_get_raw_text_balanced(Scanner *s, int startchar, int endchar) {
String *result = 0; String *result = NULL;
char c;
int old_line = s->line; int old_line = s->line;
String *old_text = Copy(s->text); String *old_text = Copy(s->text);
long position = Tell(s->str); long position = Tell(s->str);
int num_levels = 1; int num_levels = 1;
int state = 0; int starttok, endtok;
Clear(s->text); switch (endchar) {
Setfile(s->text, Getfile(s->str)); case '}':
Setline(s->text, s->line); starttok = SWIG_TOKEN_LBRACE;
Putc((char)startchar, s->text); endtok = SWIG_TOKEN_RBRACE;
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;
break; break;
case 10: case ')':
if (c == '/') starttok = SWIG_TOKEN_LPAREN;
state = 11; endtok = SWIG_TOKEN_RPAREN;
else if (c == '*')
state = 12;
else if (c == startchar) {
state = 0;
num_levels++;
}
else
state = 0;
break; break;
case 11: case ']':
if (c == '\n') starttok = SWIG_TOKEN_LBRACKET;
state = 0; endtok = SWIG_TOKEN_RBRACKET;
else
state = 11;
break; break;
case 12: /* first character inside C comment */ case '>':
if (c == '*') starttok = SWIG_TOKEN_LESSTHAN;
state = 14; endtok = SWIG_TOKEN_GREATERTHAN;
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; break;
default: 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; break;
} }
} }
/* Reset the scanner state. */
Seek(s->str, position, SEEK_SET); Seek(s->str, position, SEEK_SET);
result = Copy(s->text); Delete(s->text);
Clear(s->text); s->text = old_text;
Append(s->text, old_text);
Delete(old_text);
s->line = old_line; s->line = old_line;
return result; return result;
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Scanner_isoperator() * Scanner_isoperator()
* *