Skip to content

Enhancement/refactor grammar encoding#99

Merged
Saibo-creator merged 11 commits into
epfl-dlab:mainfrom
nathanrchn:enhancement/refactor-grammar-encoding
Oct 22, 2024
Merged

Enhancement/refactor grammar encoding#99
Saibo-creator merged 11 commits into
epfl-dlab:mainfrom
nathanrchn:enhancement/refactor-grammar-encoding

Conversation

@nathanrchn

@nathanrchn nathanrchn commented Sep 26, 2024

Copy link
Copy Markdown
Contributor

This PR refactors the parser logic by introducing multiple classes to represent different parts of the grammar:

  1. GrammarElement: An abstract class representing a single element. It has two subclasses:

    • TerminatedElement: Represents literals, ranges, and similar constructs.
    • ReferenceElement: Represents references, with a single attribute: reference_id.
  2. AlternativeElements: A class representing an alternative, containing a list of symbols that is itself a list of GrammarElementobjects. Thesymbolsare useful for repetition operators that apply not just on the previousGrammarElement` but on the entire previous symbol.

  3. GrammarRule: A class representing a rule, containing a list of AlternativeElements objects.

Each of these classes implements the Codable interface and provides an implementation of the serialize method:

def serialize(self) -> List[int]:
    # Implementation details

The serialize method generates a list of integers, maintaining consistency with the original grammar_encoding list and the rest of the codebase.

I am currently trying to add a graph method to the ParseState class to be able to create nice graphics to visualise the grammar.
Update: The graph method is now fully functional.

@nathanrchn

Copy link
Copy Markdown
Contributor Author

I tested my changes against the old parser to ensure full compatibility. To accomplish this, I compared the results of processing all EBNF files in the repository:

def test_refactor_parser(self):
        # get all the ebnf files in examples/grammars and subdirectories
        import os
        from transformers_cfg.old_parser import parse_ebnf as old_parse_ebnf

        files = []
        for root, _, filenames in os.walk("examples/grammars"):
            for filename in filenames:
                if filename.endswith(".ebnf"):
                    files.append(os.path.join(root, filename))

        for file in files:
            with open(file, "r") as f:
                src = f.read()
            
            old_state = old_parse_ebnf(src)
            new_state = parse_ebnf(src)
            self.assertListEqual(old_state.grammar_encoding, new_state.grammar_encoding, f"The grammar encoding of {file} is different")

Here the old_parser.py file is just the original parser.py file from the main branch.

Comment thread transformers_cfg/parser.py Outdated


@dataclass
class TerminatedElement(GrammarElement):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the the name TerminalElement would be more appropriate as terminal is the word used in grammar theory

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to see if I understand correctly, this TerminalElement is used to match a single char, isn't it ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TerminalElement are all the elements that are not References. So it's just list of ranges. For a single char, it will be a list with one range: [(ord(char), ord(char)].

Comment thread transformers_cfg/parser.py Outdated

@dataclass
class ReferenceElement(GrammarElement):
reference_id: int

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the name referee_id would be more explictly expressing that this is the symbol id that is referred to

return outbuf


class ParseState:

@Saibo-creator Saibo-creator Oct 3, 2024

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I start to realise that ParseState was really a bad name... How do you think CompiledGrammar?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking about it, I think the ParseState is a good name because it represents the current parse state when parsing the grammar. But at the end, we can indeed use CompiledGrammar.

@Saibo-creator

Copy link
Copy Markdown
Collaborator

I’ll need a bit more time to review this PR—I’ve kind of forgotten how the parser works 😅.

@Saibo-creator
Saibo-creator merged commit f1fc708 into epfl-dlab:main Oct 22, 2024
@nathanrchn
nathanrchn deleted the enhancement/refactor-grammar-encoding branch October 22, 2024 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants