Eliah-Lakhin / lady-deirdre

Compiler front-end foundation technology.
http://lady-deirdre.lakhin.com/
360 stars 11 forks source link

Proc macro `Node` panic: duplicate covered token #19

Closed jerome-trc closed 5 days ago

jerome-trc commented 1 week ago
!! LADY DEIRDRE INTERNAL ERROR
!!
!! This is a bug.
!! If you see this message, please open an Issue: https://github.com/Eliah-Lakhin/lady-deirdre/issues
!!
!! Message: Duplicate covered token.
!! File: /home/jerome/.cargo/git/checkouts/lady-deirdre-32d6389957ff7fde/fb02983/work/crates/derive/src/node/rule.rs
!! Line: 315
!! Column: 29

I can confirm this occurs on v2.0.1, bdb70e22 and fb029833. Minimal reproduction:

use lady_deirdre::lexis::Token as LexisToken;

#[derive(LexisToken, Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum T {
    Eoi = 0,
    Mismatch = 1,
    #[rule(i("true"))]
    #[priority(5)]
    LitTrue,
}

#[derive(lady_deirdre::syntax::Node)]
#[token(Token)]
pub enum S {
    #[root]
    #[rule((top: A | B)*)]
    Root {
        #[node]
        node: NodeRef,
        #[parent]
        parent: NodeRef,
        #[child]
        top: Vec<NodeRef>,
    },
    #[rule($LitTrue)]
    A {
        #[node]
        node: NodeRef,
        #[parent]
        parent: NodeRef,
    },
    #[rule($LitTrue)]
    B {
        #[node]
        node: NodeRef,
        #[parent]
        parent: NodeRef,
    },
}
jerome-trc commented 1 week ago

For context, I was attempting to define a grammar for a language which does not declare any keywords to its lexer in the formal sense. Instead, its lexer only tokenises identifiers, and the parser then checks the strings of these identifiers to determine if they match the keywords to assemble syntax elements.

I was trying to replicate this behaviour in Lady Deirdre by making each syntax node use #[rule($Identifier)] as its left-most set, and then defining custom parsers for each which manually check for chains of identifiers matching the keywords.

Eliah-Lakhin commented 1 week ago

Bug confirmed. Thank you for reporting!

A note regarding your approach. I think matching on the generic tokens in the parser's context is fine, but you don't need a parsing rule for each of these Keyword-nodes. Here is an example: https://gist.github.com/Eliah-Lakhin/4c543cdf7415c1c2b98c88e353beb87f

In the snippet from the description, normally the macro should yield a grammar error message because A and B have overlapping leftmost sets. But for some obscure reason, it throws an assertion error that I'm currently investigating.

Eliah-Lakhin commented 1 week ago

Ok, I think I found the root cause and fixed it. Now the macro yields the correct error message:

error: Rule "B" with "$LitTrue" token in the leftmost position conflicts with rule "A" that contains the same token match in its leftmost position.
  --> crates/playground/src/lib.rs:23:26
   |
23 |         #[rule((top: A | B)*)]
   |                          ^

The fix is in the issue-19-proc-macro-node-panic-duplicate-covered-token branch.