Files
Custom-Operating-System/utils/compilers/ConnectionCompiler/Parser/parser.py

141 lines
4.2 KiB
Python

from Lexer.lexer import Lexer
from token import Token
from type_file import Type
from connection import Connection
class Parser:
def set_code_lines(self, code: [str]):
self.lexer = Lexer(code)
self.token = Token()
self.current_token_id = -1
self.read_tokens = 0
self.lexer_rich_the_end = 0
self.tokens = []
self.next_token()
def next_token(self):
self.current_token_id += 1
self.token = self.get_token_at(self.current_token_id)
def get_token_at(self, pos):
if pos >= self.read_tokens and not self.lexer_rich_the_end:
for i in range(pos - self.read_tokens + 1):
self.tokens.append(self.lexer.next_token())
self.read_tokens += 1
if self.tokens[-1].type == Type.Special.EOF:
self.lexer_rich_the_end = True
break
return self.tokens[min(pos, self.read_tokens - 1)]
def is_nth(self, type_of_token, n):
if isinstance(type_of_token, list):
for type_of_cur_token in type_of_token:
if self.get_token_at(self.current_token_id+n).type == type_of_cur_token:
return True
return False
return self.get_token_at(self.current_token_id+n).type == type_of_token
def is_next(self, type_of_token):
if isinstance(type_of_token, list):
for type_of_cur_token in type_of_token:
if self.token.type == type_of_cur_token:
return True
return False
return self.token.type == type_of_token
def must_next(self, type_of_token):
if not self.is_next(type_of_token):
print("{0} is not {1}".format(self.token, type_of_token))
exit(1)
def __init__(self):
pass
def eat_name(self):
self.must_next(Type.Reserved.Name)
self.next_token()
self.must_next(Type.Lang.Colon)
self.next_token()
self.must_next(Type.Word)
res = self.token.value
self.next_token()
return res
def eat_protected(self):
if (self.is_next(Type.Reserved.KeyProtected)):
self.next_token()
return True
return False
def eat_magic(self):
self.must_next(Type.Reserved.Magic)
self.next_token()
self.must_next(Type.Lang.Colon)
self.next_token()
self.must_next(Type.Number.Integer)
res = self.token.value
self.next_token()
return res
def eat_params(self):
params = []
self.must_next(Type.Lang.LeftBracket)
self.next_token()
while not self.is_next(Type.Lang.RightBracket):
self.must_next(Type.Word)
typ = self.token.value
self.next_token()
self.must_next(Type.Word)
nam = self.token.value
self.next_token()
params.append([typ, nam])
if self.is_next(Type.Lang.Comma):
self.must_next(Type.Lang.Comma)
self.next_token()
self.must_next(Type.Lang.RightBracket)
self.next_token()
return params
def eat_message(self, decoder):
self.must_next(Type.Word)
msgname = self.token.value
self.next_token()
decoder.add_message(msgname, self.eat_params())
return msgname
def eat_function(self, decoder):
ms1 = self.eat_message(decoder)
ms2 = None
if self.is_next(Type.Reserved.Return):
self.must_next(Type.Reserved.Return)
self.next_token()
ms2 = self.eat_message(decoder)
decoder.add_function(ms1, ms2)
def eat_decoder(self):
self.must_next(Type.Reserved.Begin)
self.next_token()
is_protected = self.eat_protected()
decoder = Connection(self.eat_name(), self.eat_magic(), is_protected)
while not self.is_next(Type.Reserved.End):
self.eat_function(decoder)
self.must_next(Type.Reserved.End)
self.next_token()
return decoder
def parse(self):
decoders = []
while self.is_next(Type.Reserved.Begin):
decoders.append(self.eat_decoder())
print("connc: {0} decoders parsed!".format(len(decoders)))
return decoders