Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support binding token literals in rules #322

Open
cstrahan-blueshift opened this issue Oct 29, 2022 · 1 comment
Open

Support binding token literals in rules #322

cstrahan-blueshift opened this issue Oct 29, 2022 · 1 comment
Labels
feature Something not supported that perhaps should be requires-breaking-change

Comments

@cstrahan-blueshift
Copy link

The tokens I'm using in my grammar include info like text range, line, column, etc. It would be nice if I could match some of these tokens via the literal syntax and bind the resulting token to a variable for use within the rule's action expression.

Something like:

rule foo() -> u32
    = t:"blah" { t.line }

but when I try something like the above I get "cannot find value `t` in this scope".

I can work around this in a couple ways right now:

// I can use a rule like this:
rule nt() -> Token<'input> = ##next_token()

// using the undocumented ##member() syntax, with a suitable implementation on my impl Parser type:

impl<'input> TokenSlice<'input> {
    pub fn next_token(&self, pos: usize) -> RuleResult<Token<'input>> {
        match self.tokens.get(pos) {
            Some(t) => RuleResult::Matched(pos, *t),
            _ => RuleResult::Failed,
        }
    }
}

// and now I can do like so:
rule foo() -> u32
    = t:nt() "blah" { t.line }

(the above is what I'm using for now)

or

// I could create rules for each token kind:
rule BLAH() -> Token<'input>
    = token:[Token{ kind: TokenKind::Blah, .. }] { token }

rule foo() -> u32
    = t:BLAH() { t.line }

// But that gets tedious as I add new tokens, and I'd rather use the "blah" literal syntax instead of BLAH()
@kevinmehall
Copy link
Owner

Another option is to use rule arguments:

rule tok(expected_kind: TokenKind) -> Token<'input>
    = token:[Token{ kind, .. } if kind == expected_kind] { token }

rule foo() -> u32
    = t:tok(TokenKind::Blah) { t.line }

But sure, I think it would make sense to add an associated type to the ParseLiteral trait and use it in the return type of parse_str_literal. I'd accept a PR for that for version 0.9 (since it would be a breaking change for anyone who's implemented that trait).

@kevinmehall kevinmehall added feature Something not supported that perhaps should be requires-breaking-change labels Oct 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Something not supported that perhaps should be requires-breaking-change
Projects
None yet
Development

No branches or pull requests

2 participants