87 lines
2.4 KiB
Python
87 lines
2.4 KiB
Python
import re
|
|
from typing import Any
|
|
|
|
from .bootstrap import EBNFBootstrapParser
|
|
from .buffering import Buffer
|
|
from .grammars import PRAGMA_RE
|
|
from .infos import ParserConfig
|
|
from .parser_semantics import EBNFGrammarSemantics
|
|
from .semantics import ASTSemantics
|
|
|
|
|
|
class EBNFBuffer(Buffer):
|
|
def __init__(
|
|
self,
|
|
text,
|
|
/,
|
|
filename=None,
|
|
config: ParserConfig | None = None,
|
|
**settings: Any,
|
|
):
|
|
config = ParserConfig.new(
|
|
config=config, owner=self, filename=filename, **settings,
|
|
)
|
|
super().__init__(text, config=config)
|
|
|
|
def process_block(self, name, lines, index, **kwargs):
|
|
i = 0
|
|
while i < len(lines):
|
|
line = lines[i]
|
|
if re.match(PRAGMA_RE, line):
|
|
directive, arg = line.split('#', 1)[1], ''
|
|
if '::' in directive:
|
|
directive, arg = directive.split('::', 1)
|
|
directive, arg = directive.strip(), arg.strip()
|
|
i = self.pragma(name, directive, arg, lines, index, i)
|
|
else:
|
|
i += 1
|
|
return lines, index
|
|
|
|
def pragma(self, source, name, arg, lines, index, i):
|
|
# we only recognize the 'include' pragama
|
|
if name == 'include':
|
|
filename = arg.strip('\'"')
|
|
return self.include_file(source, filename, lines, index, i, i + 1)
|
|
else:
|
|
return i + 1 # will be treated as a directive by the parser
|
|
|
|
|
|
class EBNFParser(EBNFBootstrapParser):
|
|
def __init__(
|
|
self,
|
|
name: str | None = None,
|
|
config: ParserConfig | None = None,
|
|
semantics=None,
|
|
**settings: Any,
|
|
):
|
|
if semantics is None:
|
|
semantics = ASTSemantics()
|
|
config = ParserConfig.new(
|
|
config=config,
|
|
name=name,
|
|
semantics=semantics,
|
|
tokenizercls=EBNFBuffer,
|
|
**settings,
|
|
)
|
|
super().__init__(config)
|
|
|
|
|
|
class GrammarGenerator(EBNFBootstrapParser):
|
|
def __init__(
|
|
self,
|
|
name: str | None = None,
|
|
config: ParserConfig | None = None,
|
|
semantics=None,
|
|
**settings: Any,
|
|
):
|
|
if semantics is None:
|
|
semantics = EBNFGrammarSemantics(name)
|
|
config = ParserConfig.new(
|
|
config=config,
|
|
name=name,
|
|
semantics=semantics,
|
|
tokenizercls=EBNFBuffer,
|
|
**settings,
|
|
)
|
|
super().__init__(config)
|