81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
# Copyright (c) PARRRATE T&V 2021. All rights reserved.
|
|
|
|
from io import BytesIO
|
|
|
|
from bu4.parsing.abstractparser import AbstractParser
|
|
from bu4.parsing.codes import *
|
|
from bu4.parsing.constructs.linked import Parsed
|
|
from bu4.parsing.constructs.llambda import PLambda
|
|
from bu4.parsing.constructs.lname import PName
|
|
from bu4.parsing.constructs.lnull import PNull
|
|
from bu4.parsing.states.psafter import PSAfter
|
|
from bu4.parsing.states.pscall import pscall
|
|
from bu4.parsing.states.psfinal import PSFinal
|
|
from bu4.parsing.states.psread import PSRead
|
|
from bu4.parsing.targets.pschain import PSChain
|
|
from bu4.parsing.targets.psendswith import PSEndsWith
|
|
from bu4.parsing.targets.pslambda import PSLambda
|
|
|
|
__all__ = ('Parser',)
|
|
|
|
|
|
class Parser(AbstractParser):
|
|
def __init__(self, s: bytes):
|
|
self.__s = BytesIO(s)
|
|
|
|
def read(self) -> int:
|
|
bytes_ = self.__s.read(1)
|
|
return bytes_[0] if bytes_ else 0
|
|
|
|
def parse_name(self) -> bytes:
|
|
s = BytesIO()
|
|
while True:
|
|
c = self.read()
|
|
if not c:
|
|
return s.getvalue()
|
|
s.write(bytes([c]))
|
|
|
|
def _state_read(self, state: PSAfter):
|
|
c = self.read()
|
|
if c == CODE_NULL:
|
|
state.state = PSFinal(PNull())
|
|
elif c == CODE_CALL:
|
|
state.state = pscall
|
|
elif c == CODE_MAKE:
|
|
state.state = (lambda name: PSAfter(
|
|
PSRead(),
|
|
PSLambda(
|
|
lambda value: PSFinal(PLambda(name, value))
|
|
)
|
|
))(self.parse_name())
|
|
elif c == CODE_NAME:
|
|
state.state = PSFinal(PName(self.parse_name()))
|
|
elif c == CODE_SKIP:
|
|
pass
|
|
elif c == CODE_QUOT:
|
|
state.target = PSChain(PSEndsWith(self, CODE_QUOT, "quot expected"), state.target)
|
|
elif c == CODE_QOPN:
|
|
state.target = PSChain(PSEndsWith(self, CODE_QCLS, "qcls expected"), state.target)
|
|
else:
|
|
raise ValueError(f"unknown control: {hex(c)}")
|
|
return state
|
|
|
|
def _state_next(self, state: PSAfter):
|
|
if isinstance(state.state, PSAfter):
|
|
state.state, state.target = state.state.state, PSChain(state.state.target, state.target)
|
|
elif isinstance(state.state, PSFinal):
|
|
state = state.target.given(state.state.parsed)
|
|
elif isinstance(state.state, PSRead):
|
|
state = self._state_read(state)
|
|
return state
|
|
|
|
def parse(self) -> Parsed:
|
|
state = PSAfter(PSRead(), PSLambda(lambda parsed: PSFinal(parsed)))
|
|
while True:
|
|
if isinstance(state, PSFinal):
|
|
return state.parsed
|
|
elif isinstance(state, PSAfter):
|
|
state = self._state_next(state)
|
|
else:
|
|
raise TypeError
|