Hello,
I am creating a compiler using Python but I keep getting this strange error from my compiler (NOT python) the reason why it’s strange is because the way I formatted it shouldn’t give me an error
Anyways here’s the results:
Input: “@O 45 V ABC”;
Expected Output (Something like this): “OUTPUT: VAR ABC”
Actual Output: “[Illegal Character]: ‘V’ is not allowed”
Here’s the code:
shell.py (The script I’m running):
#===================================
#[SSP] BASIC PROGRAMMING LANGUAGE
#[PROJECT] START DATE: 12/11/2022
#Samm
#===================================
import ssp_basic
while True:
text = input('SSP BASIC: ')
if(text == "EXIT"):
break
result, error = ssp_basic.run(text)
print(text)
if(error):
print(error)
else:
print(result)
ssp_basic.py:
#===================================
#[SSP] BASIC PROGRAMMING LANGUAGE
#[PROJECT] START DATE: 12/11/2022
#Samm
#===================================
DIGITS = '0123456789'
class Error:
def __init__(self, error_name, details):
self.error_name = error_name
self.details = details
def as_string(self):
result = f'[{self.error_name}]: {self.details}'
return result
def __repr__(self):
return self.as_string()
class IllegalCharError(Error):
def __init__(self, details):
super().__init__('Illegal Character', details)
TT_DEFINE = 'DEFINE'
TT_INPUT = 'INPUT'
TT_OUTPUT = 'OUTPUT'
TT_VAR_SET = 'SETVAR'
TT_ARR_SET = 'SETARR'
TT_VAR_GET = 'GETVAR'
TT_ARR_GET = 'GETARR'
TT_IF = 'IF'
TT_ELSE = 'ELSE'
TT_WHILE = 'WHILE'
TT_INT = 'INT'
TT_FLOAT = 'FLOAT'
TT_BINARY = 'BINARY'
TT_HEX = 'HEX'
TT_STR = 'STR'
TT_CHAR = 'CHAR'
TT_PLUS = 'PLUS'
TT_MINUS = 'MINUS'
TT_MUL = 'MUL'
TT_DIV = 'DIV'
TT_LPAREN = 'LPAREN'
TT_RPAREN = 'RPAREN'
TT_COLON = 'COLON'
TT_SEMI_COLON = 'SEMICOLON'
#TT_COMMENT = 'COMMENT'
class Token:
def __init__(self, type_, values={None}):
self.type = type_
self.values = values
def __repr__(self):
if(self.values != None):
return f'{self.type}: {self.values}'
return f'{self.type}'
class Lexer:
def __init__(self, text):
self.text = text
self.pos = -1
self.current_char = None
self.build_platform = 0
self.vars = {None}
self.advance()
def advance(self):
self.pos += 1
self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
def advance_multiple(self, advances):
self.pos += advances
self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
def make_tokens(self):
tokens = []
while(self.current_char != None):
if(self.current_char in ' \t'):
self.advance()
elif(self.current_char in DIGITS):
tokens.append(self.make_number)
self.advance()
elif(self.current_char == "#"):
tokens.append(self.make_def)
self.advance()
elif(self.current_char == "@"):
self.advance()
if(self.current_char == 'I'):
tokens.append(self.make_input)
self.advance()
elif(self.current_char == 'O'):
tokens.append(self.make_output)
self.advance()
else:
char = self.current_char
self.advance()
return [], IllegalCharError("'" + char + "' is not allowed after IO (AKA '@')")
elif(self.current_char == '!'): #Set variable or array
self.advance()
if(self.current_char == 'S'):
if(self.current_char == 'V'):
self.make_set_variable()
elif(self.current_char == 'A'):
self.make_set_array()
else:
char = self.current_char
self.advance()
return [], IllegalCharError("'" + char + "' is not allowed after VARIABLE TYPE (AKA '!')\nTypes Allowed: V - Variable, A - Array")
elif(self.current_char == 'G'):
if(self.current_char == 'V'):
self.make_get_variable()
elif(self.current_char == 'A'):
self.make_get_array()
else:
char = self.current_char
self.advance()
return [], IllegalCharError("'" + char + "' is not allowed after VARIABLE TYPE (AKA '!')\nTypes Allowed: V - Variable, A - Array")
else:
return [], IllegalCharError("'" + char + "' is not allowed after VARIABLE TYPE (AKA '!')\nTypes Allowed: S - Set, G - Get")
elif(self.current_char == 'B'):
tokens.append(self.make_bin_num)
self.advance()
elif(self.current_char == 'H'):
tokens.append(self.make_hex_num)
self.advance()
elif(self.current_char == 'S'):
tokens.append(self.make_str)
self.advance()
elif(self.current_char == 'C'):
self.advance_multiple(2)
tokens.append(Token(TT_CHAR, self.current_char))
self.advance()
elif(self.current_char == '+'):
tokens.append(Token(TT_PLUS))
self.advance()
elif(self.current_char == '-'):
tokens.append(Token(TT_MINUS))
self.advance()
elif(self.current_char == '*'):
tokens.append(Token(TT_MUL))
self.advance()
elif(self.current_char == '/'):
tokens.append(Token(TT_DIV))
self.advance()
elif(self.current_char == '('):
tokens.append(Token(TT_LPAREN))
self.advance()
elif(self.current_char == ')'):
tokens.append(Token(TT_RPAREN))
self.advance()
elif(self.current_char == '/'):
self.advance()
if(self.current_char == '/'):
while(self.current_char != '\n'):
self.advance()
self.advance()
else:
char = self.current_char
self.advance()
return [], IllegalCharError("'" + char + "' is not allowed")
return tokens, None
def make_number(self):
num_str = ''
dot_count = 0
while(self.current_char != None and self.current_char in DIGITS + '.'):
if(self.current_char == '.'):
if(dot_count == 1):
break
dot_count += 1
num_str += '.'
else:
num_str += self.current_char
self.advance()
if(dot_count == 0):
return Token(TT_INT, int(num_str))
else:
return Token(TT_FLOAT, float(num_str))
def make_input(self):
input_src_num_str = ''
self.advance()
while(self.current_char != None and self.current_char in DIGITS):
input_src_num_str += self.current_char
self.advance()
return Token(TT_INPUT, int(input_src_num_str))
def make_output(self):
output_src_num_str = ''
self.advance()
while(self.current_char != None and self.current_char.isspace() == True):
self.advance()
while(self.current_char != None and self.current_char.isspace() == False and self.current_char in DIGITS):
output_src_num_str += self.current_char
self.advance()
while(self.current_char != None and self.current_char != ';'):
if(self.current_char == 'V'):
self.advance_multiple(2)
output_var_num_str = ''
while(self.current_char != None and self.current_char != ';'):
output_var_num_str += self.current_char
self.advance()
return Token(TT_OUTPUT, int({output_src_num_str, 'VAR', output_var_num_str}))
elif(self.current_char == 'N'):
self.advance_multiple(2)
output_data_num_str = ''
while(self.current_char != None and self.current_char != ';'):
if(self.current_char in DIGITS):
output_data_num_str += self.current_char
self.advance()
else:
return [], IllegalCharError("'" + self.current_char + "' is not allowed, Must be a INTEGER or terminater (';')")
return Token(TT_OUTPUT, int({output_src_num_str, 'NUM', int(output_data_num_str)}))
self.advance()
return [], IllegalCharError("'" + self.current_char + "' is not allowed when outputing at that stage")
def make_def(self):
def_str = ''
self.advance()
while(self.current_char != None and self.current_char != '\n'):
def_str += self.current_char
self.advance()
if('BUILD_PLATFORM' in def_str):
if('01' in def_str):
self.build_platform = 1 #Arm Microcontroller (GNU)
elif('02' in def_str):
self.build_platform = 2
class NumberNode:
def __init__(self, tok):
self.tok = tok
def __repr__(self):
return f'{self.tok}'
class BinOpNode:
def __init__(self, left_node, op_tok, right_node):
self.left_node = left_node
self.op_tok = op_tok
self.right_node = right_node
def __repr__(self):
return f'({self.left_node}, {self.op_tok}, {self.right_node})'
class Parser:
def __init__(self, tokens):
self.tokens = tokens
self.tok_index = 1
self.advance()
def advance(self):
self.tok_index += 1
if(self.token_index < len(self.tokens)):
self.current_tok = self.tokens[self.tok_index]
return self.current_tok
def factor(self):
tok = self.current_tok
if(tok.type in (TT_INT, TT_FLOAT)):
self.advance()
return NumberNode(tok)
def term(self):
left = self.factor()
while(self.current_tok in (TT_MUL, TT_DIV)):
op_tok = self.current_tok
self.advance()
right = self.factor()
left = BinOpNode(left, op_tok, right)
return left
def expr(self):
pass
def run(text):
lexer = Lexer(text)
tokens, error = lexer.make_tokens()
return tokens, error
Anyways if you think you might know how to fix this please tell me your idea
Thanks in advance!
-Samm