diff options
| author | Xavier Claessens <xavier.claessens@collabora.com> | 2023-11-01 09:18:49 -0400 |
|---|---|---|
| committer | Xavier Claessens <xclaesse@gmail.com> | 2025-05-31 10:07:06 -0400 |
| commit | 474d77d005512f37710a84f1e809e0878cc22713 (patch) | |
| tree | 87110e2ea002af5c439fbd7675716855b767dd12 /mesonbuild/cargo | |
| parent | f3adf71b85960da3ff22914cd1a5ce885d3b6a67 (diff) | |
| download | meson-474d77d005512f37710a84f1e809e0878cc22713.tar.gz | |
cargo: Fix cfg() parsing
Add cfg token to be able to parse the top level cfg() function.
Fix parser which was creating a new iterator when recursing which caused
the caller function's iterator to not have advanced when recursing
function returns.
Diffstat (limited to 'mesonbuild/cargo')
| -rw-r--r-- | mesonbuild/cargo/cfg.py | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/mesonbuild/cargo/cfg.py b/mesonbuild/cargo/cfg.py index 0d49527cc..3586a2a54 100644 --- a/mesonbuild/cargo/cfg.py +++ b/mesonbuild/cargo/cfg.py @@ -4,6 +4,7 @@ """Rust CFG parser. Rust uses its `cfg()` format in cargo. +https://doc.rust-lang.org/reference/conditional-compilation.html This may have the following functions: - all() @@ -33,7 +34,7 @@ from ..mesonlib import MesonBugException if T.TYPE_CHECKING: _T = T.TypeVar('_T') _LEX_TOKEN = T.Tuple['TokenType', T.Optional[str]] - _LEX_STREAM = T.Iterable[_LEX_TOKEN] + _LEX_STREAM = T.Iterator[_LEX_TOKEN] _LEX_STREAM_AH = T.Iterator[T.Tuple[_LEX_TOKEN, T.Optional[_LEX_TOKEN]]] @@ -48,6 +49,7 @@ class TokenType(enum.Enum): NOT = enum.auto() COMMA = enum.auto() EQUAL = enum.auto() + CFG = enum.auto() def lexer(raw: str) -> _LEX_STREAM: @@ -56,45 +58,41 @@ def lexer(raw: str) -> _LEX_STREAM: :param raw: The raw cfg() expression :return: An iterable of tokens """ - buffer: T.List[str] = [] + start: int = 0 is_string: bool = False - for s in raw: - if s.isspace() or s in {')', '(', ',', '='} or (s == '"' and buffer): - val = ''.join(buffer) - buffer.clear() - if is_string: + for i, s in enumerate(raw): + if s.isspace() or s in {')', '(', ',', '=', '"'}: + val = raw[start:i] + start = i + 1 + if s == '"' and is_string: yield (TokenType.STRING, val) + is_string = False + continue elif val == 'any': yield (TokenType.ANY, None) elif val == 'all': yield (TokenType.ALL, None) elif val == 'not': yield (TokenType.NOT, None) + elif val == 'cfg': + yield (TokenType.CFG, None) elif val: yield (TokenType.IDENTIFIER, val) if s == '(': yield (TokenType.LPAREN, None) - continue elif s == ')': yield (TokenType.RPAREN, None) - continue elif s == ',': yield (TokenType.COMMA, None) - continue elif s == '=': yield (TokenType.EQUAL, None) - continue - elif s.isspace(): - continue - - if s == '"': - is_string = not is_string - else: - buffer.append(s) - if buffer: + elif s == '"': + is_string = True + val = raw[start:] + if val: # This should always be an identifier - yield (TokenType.IDENTIFIER, ''.join(buffer)) + yield (TokenType.IDENTIFIER, val) def lookahead(iter: T.Iterator[_T]) -> T.Iterator[T.Tuple[_T, T.Optional[_T]]]: @@ -175,41 +173,40 @@ def _parse(ast: _LEX_STREAM_AH) -> IR: else: ntoken, _ = (None, None) - stream: T.List[_LEX_TOKEN] if token is TokenType.IDENTIFIER: + assert value + id_ = Identifier(value) if ntoken is TokenType.EQUAL: - return Equal(Identifier(value), _parse(ast)) - if token is TokenType.STRING: - return String(value) - if token is TokenType.EQUAL: - # In this case the previous caller already has handled the equal - return _parse(ast) - if token in {TokenType.ANY, TokenType.ALL}: + next(ast) + (token, value), _ = next(ast) + assert token is TokenType.STRING + assert value is not None + return Equal(id_, String(value)) + return id_ + elif token in {TokenType.ANY, TokenType.ALL}: type_ = All if token is TokenType.ALL else Any - assert ntoken is TokenType.LPAREN - next(ast) # advance the iterator to get rid of the LPAREN - stream = [] args: T.List[IR] = [] - while token is not TokenType.RPAREN: + (token, value), n_stream = next(ast) + assert token is TokenType.LPAREN + if n_stream and n_stream[0] == TokenType.RPAREN: + return type_(args) + while True: + args.append(_parse(ast)) (token, value), _ = next(ast) - if token is TokenType.COMMA: - args.append(_parse(lookahead(iter(stream)))) - stream.clear() - else: - stream.append((token, value)) - if stream: - args.append(_parse(lookahead(iter(stream)))) + if token is TokenType.RPAREN: + break + assert token is TokenType.COMMA return type_(args) - if token is TokenType.NOT: - next(ast) # advance the iterator to get rid of the LPAREN - stream = [] - # Mypy can't figure out that token is overridden inside the while loop - while token is not TokenType.RPAREN: # type: ignore - (token, value), _ = next(ast) - stream.append((token, value)) - return Not(_parse(lookahead(iter(stream)))) - - raise MesonBugException(f'Unhandled Cargo token: {token}') + elif token in {TokenType.NOT, TokenType.CFG}: + is_not = token is TokenType.NOT + (token, value), _ = next(ast) + assert token is TokenType.LPAREN + arg = _parse(ast) + (token, value), _ = next(ast) + assert token is TokenType.RPAREN + return Not(arg) if is_not else arg + else: + raise MesonBugException(f'Unhandled Cargo token:{token} {value}') def parse(ast: _LEX_STREAM) -> IR: @@ -218,7 +215,7 @@ def parse(ast: _LEX_STREAM) -> IR: :param ast: An iterable of Tokens :return: An mparser Node to be used as a conditional """ - ast_i: _LEX_STREAM_AH = lookahead(iter(ast)) + ast_i: _LEX_STREAM_AH = lookahead(ast) return _parse(ast_i) @@ -256,6 +253,8 @@ def _(ir: Not, build: builder.Builder) -> mparser.BaseNode: @ir_to_meson.register def _(ir: Any, build: builder.Builder) -> mparser.BaseNode: + if not ir.args: + return build.bool(False) args = iter(reversed(ir.args)) last = next(args) cur = build.or_(ir_to_meson(next(args), build), ir_to_meson(last, build)) @@ -266,6 +265,8 @@ def _(ir: Any, build: builder.Builder) -> mparser.BaseNode: @ir_to_meson.register def _(ir: All, build: builder.Builder) -> mparser.BaseNode: + if not ir.args: + return build.bool(True) args = iter(reversed(ir.args)) last = next(args) cur = build.and_(ir_to_meson(next(args), build), ir_to_meson(last, build)) |
