• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from pygments.lexer import RegexLexer, bygroups, include
2from pygments.token import Comment, Generic, Keyword, Name, Operator, Punctuation, Text
3
4from sphinx.highlighting import lexers
5
6
7class PEGLexer(RegexLexer):
8    """Pygments Lexer for PEG grammar (.gram) files
9
10    This lexer strips the following elements from the grammar:
11
12        - Meta-tags
13        - Variable assignments
14        - Actions
15        - Lookaheads
16        - Rule types
17        - Rule options
18        - Rules named `invalid_*` or `incorrect_*`
19    """
20
21    name = "PEG"
22    aliases = ["peg"]
23    filenames = ["*.gram"]
24    _name = r"([^\W\d]\w*)"
25    _text_ws = r"(\s*)"
26
27    tokens = {
28        "ws": [(r"\n", Text), (r"\s+", Text), (r"#.*$", Comment.Singleline),],
29        "lookaheads": [
30            (r"(?<=\|\s)(&\w+\s?)", bygroups(None)),
31            (r"(?<=\|\s)(&'.+'\s?)", bygroups(None)),
32            (r'(?<=\|\s)(&".+"\s?)', bygroups(None)),
33            (r"(?<=\|\s)(&\(.+\)\s?)", bygroups(None)),
34        ],
35        "metas": [
36            (r"(@\w+ '''(.|\n)+?''')", bygroups(None)),
37            (r"^(@.*)$", bygroups(None)),
38        ],
39        "actions": [(r"{(.|\n)+?}", bygroups(None)),],
40        "strings": [
41            (r"'\w+?'", Keyword),
42            (r'"\w+?"', Keyword),
43            (r"'\W+?'", Text),
44            (r'"\W+?"', Text),
45        ],
46        "variables": [(_name + _text_ws + "(=)", bygroups(None, None, None),),],
47        "invalids": [
48            (r"^(\s+\|\s+invalid_\w+\s*\n)", bygroups(None)),
49            (r"^(\s+\|\s+incorrect_\w+\s*\n)", bygroups(None)),
50            (r"^(#.*invalid syntax.*(?:.|\n)*)", bygroups(None),),
51        ],
52        "root": [
53            include("invalids"),
54            include("ws"),
55            include("lookaheads"),
56            include("metas"),
57            include("actions"),
58            include("strings"),
59            include("variables"),
60            (r"\b(?!(NULL|EXTRA))([A-Z_]+)\b\s*(?!\()", Text,),
61            (
62                r"^\s*" + _name + r"\s*" + r"(\[.*\])?" + r"\s*" + r"(\(.+\))?" + r"\s*(:)",
63                bygroups(Name.Function, None, None, Punctuation),
64            ),
65            (_name, Name.Function),
66            (r"[\||\.|\+|\*|\?]", Operator),
67            (r"{|}|\(|\)|\[|\]", Punctuation),
68            (r".", Text),
69        ],
70    }
71
72
73def setup(app):
74    lexers["peg"] = PEGLexer()
75    return {"version": "1.0", "parallel_read_safe": True}
76