Fixes to lexer and syntactical analyzer
This commit is contained in:
parent
6ede3a4c5e
commit
c2051ffce4
|
@ -0,0 +1,18 @@
|
||||||
|
// Kyler Olsen
|
||||||
|
// Source Code Test 1
|
||||||
|
// Syntax Test
|
||||||
|
# Dummy Directive
|
||||||
|
|
||||||
|
fn test_func(arg1: int, arg2: unsigned = 10) -> fixed {
|
||||||
|
let var1: float;
|
||||||
|
var1 = (arg1 + arg2) / arg1;
|
||||||
|
var1 = var1 + test_func(arg2, arg1) + 15;
|
||||||
|
test_func = var1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> int {
|
||||||
|
let var1: int = 1;
|
||||||
|
let var2: unsigned = 1;
|
||||||
|
main = 0;
|
||||||
|
test_func(arg1=var1, arg2=var2);
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Kyler Olsen
|
||||||
|
// Source Code Test 2
|
||||||
|
// Syntax Test
|
||||||
|
# Dummy Directive
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
static points: @Point = 0,
|
||||||
|
static count: int = 0,
|
||||||
|
x: int = 0,
|
||||||
|
y: int = 0,
|
||||||
|
z: int,
|
||||||
|
random: @int
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Colors { RED, GREEN, BLUE = 7 }
|
||||||
|
|
||||||
|
fn test_func(arg1: int, arg2: unsigned = 10) -> fixed {
|
||||||
|
let var1: float;
|
||||||
|
var1 = (arg1 + arg2) / arg1;
|
||||||
|
var1 = var1 + test_func(arg2, arg1) + 15;
|
||||||
|
test_func = var1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_func2() -> Point {
|
||||||
|
test++;
|
||||||
|
test--;
|
||||||
|
--test;
|
||||||
|
++test;
|
||||||
|
-test;
|
||||||
|
!test;
|
||||||
|
$test;
|
||||||
|
~test;
|
||||||
|
@test;
|
||||||
|
|
||||||
|
test >> test;
|
||||||
|
test << test;
|
||||||
|
test ^ test;
|
||||||
|
test | test;
|
||||||
|
test & test;
|
||||||
|
test % test;
|
||||||
|
test / test;
|
||||||
|
test * test;
|
||||||
|
test - test;
|
||||||
|
test + test;
|
||||||
|
test >= test;
|
||||||
|
test > test;
|
||||||
|
test <= test;
|
||||||
|
test < test;
|
||||||
|
test != test;
|
||||||
|
test == test;
|
||||||
|
test ^^ test;
|
||||||
|
test || test;
|
||||||
|
test && test;
|
||||||
|
test >>= test;
|
||||||
|
test <<= test;
|
||||||
|
test ^= test;
|
||||||
|
test |= test;
|
||||||
|
test &= test;
|
||||||
|
test %= test;
|
||||||
|
test /= test;
|
||||||
|
test *= test;
|
||||||
|
test -= test;
|
||||||
|
test += test;
|
||||||
|
test = test;
|
||||||
|
|
||||||
|
test ? test : test;
|
||||||
|
|
||||||
|
test = None;
|
||||||
|
test = False;
|
||||||
|
test = True;
|
||||||
|
test = 1234;
|
||||||
|
test = 0xff1;
|
||||||
|
test = .156;
|
||||||
|
test = 15e5;
|
||||||
|
test = 0o1526;
|
||||||
|
test = 0b1010;
|
||||||
|
test = '5';
|
||||||
|
test = 'g';
|
||||||
|
test = '\n';
|
||||||
|
test = '\'';
|
||||||
|
test = '\\';
|
||||||
|
test = '"';
|
||||||
|
test = "Hello World!";
|
||||||
|
test = "This is \"cool\"!";
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> int {
|
||||||
|
let var1: int = 1;
|
||||||
|
let var2: unsigned = 1;
|
||||||
|
main = 0;
|
||||||
|
test_func(arg1=var1, arg2=var2);
|
||||||
|
test_func2();
|
||||||
|
}
|
|
@ -21,6 +21,12 @@ class FileInfo:
|
||||||
self._col = col
|
self._col = col
|
||||||
self._length = length
|
self._length = length
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return (
|
||||||
|
f"{type(self).__name__}"
|
||||||
|
f"('{self._filename}',{self._line},{self._col},{self._length})"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CompilerError(Exception):
|
class CompilerError(Exception):
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ _Num_Continue_Next = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Punctuation_Any = "@$+-*/%~&|^<>=!?{}[]().->,;:"
|
_Punctuation_Any = "@$+-*/%~&|^<>=!?{[(}]).->,;:"
|
||||||
|
|
||||||
_Punctuation = (
|
_Punctuation = (
|
||||||
"++", "--", "@", "$", "+", "-",
|
"++", "--", "@", "$", "+", "-",
|
||||||
|
@ -143,6 +143,9 @@ class Token:
|
||||||
self._value = value
|
self._value = value
|
||||||
self._file_info = file_info
|
self._file_info = file_info
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"Type: {self._type}, Value: {self.value}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> str: return self._value
|
def value(self) -> str: return self._value
|
||||||
|
|
||||||
|
@ -183,6 +186,7 @@ def lexer(file: str, filename: str) -> Sequence[Token]:
|
||||||
tokens.append(Identifier(current, fi))
|
tokens.append(Identifier(current, fi))
|
||||||
elif token_type is _InterTokenType.NumberLiteral:
|
elif token_type is _InterTokenType.NumberLiteral:
|
||||||
tokens.append(NumberLiteral(current, fi))
|
tokens.append(NumberLiteral(current, fi))
|
||||||
|
number_type = _NumberLiteralType.Number
|
||||||
elif token_type is _InterTokenType.Punctuation:
|
elif token_type is _InterTokenType.Punctuation:
|
||||||
if current not in _Punctuation:
|
if current not in _Punctuation:
|
||||||
raise LexerError("Invalid Punctuation", fi)
|
raise LexerError("Invalid Punctuation", fi)
|
||||||
|
@ -209,20 +213,34 @@ def lexer(file: str, filename: str) -> Sequence[Token]:
|
||||||
tokens.append(Keyword(current, fi))
|
tokens.append(Keyword(current, fi))
|
||||||
else:
|
else:
|
||||||
tokens.append(Identifier(current, fi))
|
tokens.append(Identifier(current, fi))
|
||||||
token_type = _InterTokenType.Generic
|
token_type = _InterTokenType.Generic
|
||||||
elif token_type is _InterTokenType.NumberLiteral:
|
elif token_type is _InterTokenType.NumberLiteral:
|
||||||
if len(current) == 2 and char in _Num_Second[number_type]:
|
if (
|
||||||
|
len(current) == 1 and
|
||||||
|
number_type in _Num_Second and
|
||||||
|
char in _Num_Second[number_type]
|
||||||
|
):
|
||||||
current += char
|
current += char
|
||||||
if char in _Num_Second_Next[number_type]:
|
if (
|
||||||
|
number_type in _Num_Second_Next and
|
||||||
|
char in _Num_Second_Next[number_type]
|
||||||
|
):
|
||||||
number_type = _Num_Second_Next[number_type][char]
|
number_type = _Num_Second_Next[number_type][char]
|
||||||
elif char in _Num_Continue:
|
elif (
|
||||||
|
number_type in _Num_Continue and
|
||||||
|
char in _Num_Continue[number_type]
|
||||||
|
):
|
||||||
current += char
|
current += char
|
||||||
if char in _Num_Continue_Next[number_type]:
|
if (
|
||||||
|
number_type in _Num_Continue_Next and
|
||||||
|
char in _Num_Continue_Next[number_type]
|
||||||
|
):
|
||||||
number_type = _Num_Continue_Next[number_type][char]
|
number_type = _Num_Continue_Next[number_type][char]
|
||||||
else:
|
else:
|
||||||
fi = FileInfo(
|
fi = FileInfo(
|
||||||
filename, current_line, current_col, len(current))
|
filename, current_line, current_col, len(current))
|
||||||
tokens.append(NumberLiteral(current, fi))
|
tokens.append(NumberLiteral(current, fi))
|
||||||
|
number_type = _NumberLiteralType.Number
|
||||||
token_type = _InterTokenType.Generic
|
token_type = _InterTokenType.Generic
|
||||||
elif token_type is _InterTokenType.CharLiteral:
|
elif token_type is _InterTokenType.CharLiteral:
|
||||||
if escaped:
|
if escaped:
|
||||||
|
@ -234,12 +252,11 @@ def lexer(file: str, filename: str) -> Sequence[Token]:
|
||||||
fi = FileInfo(
|
fi = FileInfo(
|
||||||
filename, current_line, current_col, len(current))
|
filename, current_line, current_col, len(current))
|
||||||
if (
|
if (
|
||||||
current[1] != '\\' and
|
(current[1] != '\\' and len(current) > 3) or
|
||||||
len(current) == 3 or
|
len(current) > 4
|
||||||
len(current) > 3
|
|
||||||
):
|
):
|
||||||
raise LexerError("Character Literal Too Long", fi)
|
raise LexerError("Character Literal Too Long", fi)
|
||||||
tokens.append(StringLiteral(current, fi))
|
tokens.append(CharLiteral(current, fi))
|
||||||
token_type = _InterTokenType.Generic
|
token_type = _InterTokenType.Generic
|
||||||
continue
|
continue
|
||||||
current += char
|
current += char
|
||||||
|
@ -257,7 +274,7 @@ def lexer(file: str, filename: str) -> Sequence[Token]:
|
||||||
continue
|
continue
|
||||||
current += char
|
current += char
|
||||||
elif token_type is _InterTokenType.Punctuation:
|
elif token_type is _InterTokenType.Punctuation:
|
||||||
if char in _Punctuation_Any:
|
if char in _Punctuation_Any and current + char in _Punctuation:
|
||||||
current += char
|
current += char
|
||||||
else:
|
else:
|
||||||
fi = FileInfo(
|
fi = FileInfo(
|
||||||
|
@ -265,7 +282,7 @@ def lexer(file: str, filename: str) -> Sequence[Token]:
|
||||||
if current not in _Punctuation:
|
if current not in _Punctuation:
|
||||||
raise LexerError("Invalid Punctuation", fi)
|
raise LexerError("Invalid Punctuation", fi)
|
||||||
tokens.append(Punctuation(current, fi))
|
tokens.append(Punctuation(current, fi))
|
||||||
token_type = _InterTokenType.Generic
|
token_type = _InterTokenType.Generic
|
||||||
|
|
||||||
if token_type is _InterTokenType.Generic:
|
if token_type is _InterTokenType.Generic:
|
||||||
current = char
|
current = char
|
||||||
|
@ -297,4 +314,26 @@ def lexer(file: str, filename: str) -> Sequence[Token]:
|
||||||
elif char in _Punctuation_Any:
|
elif char in _Punctuation_Any:
|
||||||
token_type = _InterTokenType.Punctuation
|
token_type = _InterTokenType.Punctuation
|
||||||
|
|
||||||
|
fi = FileInfo(filename, current_line, current_col, len(current))
|
||||||
|
if token_type in _NewLineErrorTokens:
|
||||||
|
raise LexerError("Unexpected Newline", fi)
|
||||||
|
if token_type in _NewLineTerminatedTokens:
|
||||||
|
if token_type is _InterTokenType.Directive:
|
||||||
|
tokens.append(Directive(current, fi))
|
||||||
|
elif token_type is _InterTokenType.Word:
|
||||||
|
if len(current) > 15:
|
||||||
|
raise LexerError("Identifier Too Long", fi)
|
||||||
|
if current in _Keywords:
|
||||||
|
tokens.append(Keyword(current, fi))
|
||||||
|
else:
|
||||||
|
tokens.append(Identifier(current, fi))
|
||||||
|
elif token_type is _InterTokenType.NumberLiteral:
|
||||||
|
tokens.append(NumberLiteral(current, fi))
|
||||||
|
number_type = _NumberLiteralType.Number
|
||||||
|
elif token_type is _InterTokenType.Punctuation:
|
||||||
|
if current not in _Punctuation:
|
||||||
|
raise LexerError("Invalid Punctuation", fi)
|
||||||
|
tokens.append(Punctuation(current, fi))
|
||||||
|
token_type = _InterTokenType.Generic
|
||||||
|
|
||||||
return tokens
|
return tokens
|
||||||
|
|
|
@ -4,10 +4,29 @@
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
from .lexer import lexer
|
||||||
|
from .syntactical_analyzer import syntactical_analyzer
|
||||||
|
|
||||||
def compile(args: argparse.Namespace):
|
def compile(args: argparse.Namespace):
|
||||||
pass
|
tokens = lexer(args.input_file.read(), args.input_file.name)
|
||||||
|
|
||||||
|
if args.token_file:
|
||||||
|
for token in tokens:
|
||||||
|
args.token_file.write(str(token) + "\n")
|
||||||
|
|
||||||
|
syntax = syntactical_analyzer(tokens)
|
||||||
|
|
||||||
|
if args.syntax_file:
|
||||||
|
args.syntax_file.write(syntax.tree_str())
|
||||||
|
|
||||||
def parser(parser: argparse.ArgumentParser):
|
def parser(parser: argparse.ArgumentParser):
|
||||||
|
parser.add_argument(
|
||||||
|
'input_file', type=argparse.FileType('r', encoding='utf-8'))
|
||||||
|
# parser.add_argument('-o', '--output_file', type=argparse.FileType('wb'))
|
||||||
|
parser.add_argument(
|
||||||
|
'-t', '--token_file', type=argparse.FileType('w', encoding='utf-8'))
|
||||||
|
parser.add_argument(
|
||||||
|
'-x', '--syntax_file', type=argparse.FileType('w', encoding='utf-8'))
|
||||||
parser.set_defaults(func=compile)
|
parser.set_defaults(func=compile)
|
||||||
|
|
||||||
def main(argv: Sequence[str] | None = None):
|
def main(argv: Sequence[str] | None = None):
|
||||||
|
|
|
@ -4,10 +4,16 @@
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
|
||||||
from .compiler_types import CompilerError
|
from .compiler_types import CompilerError# , FileInfo
|
||||||
from . import lexer
|
from . import lexer
|
||||||
|
|
||||||
|
|
||||||
|
# _file_info: FileInfo
|
||||||
|
|
||||||
|
# file_info: FileInfo,
|
||||||
|
|
||||||
|
# self._file_info = file_info
|
||||||
|
|
||||||
class UnexpectedEndOfTokenStream(CompilerError): pass
|
class UnexpectedEndOfTokenStream(CompilerError): pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,7 +105,7 @@ class UnexpectedToken(_UnexpectedTokenBase):
|
||||||
s = ""
|
s = ""
|
||||||
for i in expected[:-1]:
|
for i in expected[:-1]:
|
||||||
s += i + "', '"
|
s += i + "', '"
|
||||||
s = s[:-1] + "or '" + i
|
s = s[:-1] + "or '" + expected[-1]
|
||||||
expected = s
|
expected = s
|
||||||
found = found or type(token).__name__
|
found = found or type(token).__name__
|
||||||
super().__init__(token, expected, found)
|
super().__init__(token, expected, found)
|
||||||
|
@ -124,7 +130,7 @@ class UnexpectedPunctuation(_UnexpectedTokenBase):
|
||||||
type NestableCodeBlock = ForBlock | WhileBlock | DoBlock | IfBlock
|
type NestableCodeBlock = ForBlock | WhileBlock | DoBlock | IfBlock
|
||||||
|
|
||||||
type Literal = (
|
type Literal = (
|
||||||
BuildInConst |
|
BuiltInConst |
|
||||||
NumberLiteral |
|
NumberLiteral |
|
||||||
CharLiteral |
|
CharLiteral |
|
||||||
StringLiteral
|
StringLiteral
|
||||||
|
@ -141,25 +147,38 @@ type Expression = (
|
||||||
|
|
||||||
type Statement = Expression | LetStatement | LoopStatements | NestableCodeBlock
|
type Statement = Expression | LetStatement | LoopStatements | NestableCodeBlock
|
||||||
|
|
||||||
type DataType = DefaultDataType | Identifier
|
type DataType = BuiltInDataType | Identifier
|
||||||
|
|
||||||
|
type UnaryOperator = PostfixUnaryOperator | PrefixUnaryOperator
|
||||||
|
|
||||||
|
|
||||||
class BuildInConst(Enum):
|
class BuiltInConst(Enum):
|
||||||
ConstTrue = "True"
|
ConstTrue = "True"
|
||||||
ConstFalse = "False"
|
ConstFalse = "False"
|
||||||
ConstNone = "None"
|
ConstNone = "None"
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Built-In Constant: {self.value}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class LoopStatements(Enum):
|
class LoopStatements(Enum):
|
||||||
ContinueStatement = "continue"
|
ContinueStatement = "continue"
|
||||||
BreakStatement = "break"
|
BreakStatement = "break"
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} {self.value.upper()}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
class UnaryOperator(Enum):
|
|
||||||
PostfixIncrement = "++"
|
class PostfixUnaryOperator(Enum):
|
||||||
PostfixDecrement = "--"
|
Increment = "++"
|
||||||
PrefixIncrement = "++"
|
Decrement = "--"
|
||||||
PrefixDecrement = "--"
|
|
||||||
|
|
||||||
|
class PrefixUnaryOperator(Enum):
|
||||||
|
Increment = "++"
|
||||||
|
Decrement = "--"
|
||||||
Negate = "-"
|
Negate = "-"
|
||||||
BitwiseNOT = "~"
|
BitwiseNOT = "~"
|
||||||
BooleanNOT = "!"
|
BooleanNOT = "!"
|
||||||
|
@ -204,7 +223,7 @@ class TernaryOperator(Enum):
|
||||||
TernaryConditional = "?"
|
TernaryConditional = "?"
|
||||||
|
|
||||||
|
|
||||||
class DefaultDataType(Enum):
|
class BuiltInDataType(Enum):
|
||||||
unsigned = "unsigned"
|
unsigned = "unsigned"
|
||||||
int = "int"
|
int = "int"
|
||||||
fixed = "fixed"
|
fixed = "fixed"
|
||||||
|
@ -214,15 +233,15 @@ class DefaultDataType(Enum):
|
||||||
_Operator_Precedence: tuple[
|
_Operator_Precedence: tuple[
|
||||||
UnaryOperator | BinaryOperator | TernaryOperator, ...
|
UnaryOperator | BinaryOperator | TernaryOperator, ...
|
||||||
] = (
|
] = (
|
||||||
UnaryOperator.AddressOf,
|
PrefixUnaryOperator.AddressOf,
|
||||||
UnaryOperator.Dereference,
|
PrefixUnaryOperator.Dereference,
|
||||||
UnaryOperator.BitwiseNOT,
|
PrefixUnaryOperator.BitwiseNOT,
|
||||||
UnaryOperator.PostfixDecrement,
|
PostfixUnaryOperator.Decrement,
|
||||||
UnaryOperator.PostfixIncrement,
|
PostfixUnaryOperator.Increment,
|
||||||
UnaryOperator.PrefixDecrement,
|
PrefixUnaryOperator.Decrement,
|
||||||
UnaryOperator.PrefixIncrement,
|
PrefixUnaryOperator.Increment,
|
||||||
UnaryOperator.Negate,
|
PrefixUnaryOperator.Negate,
|
||||||
UnaryOperator.BooleanNOT,
|
PrefixUnaryOperator.BooleanNOT,
|
||||||
BinaryOperator.RightShift,
|
BinaryOperator.RightShift,
|
||||||
BinaryOperator.LeftShift,
|
BinaryOperator.LeftShift,
|
||||||
BinaryOperator.BitwiseXOR,
|
BinaryOperator.BitwiseXOR,
|
||||||
|
@ -267,6 +286,12 @@ class Identifier:
|
||||||
):
|
):
|
||||||
self._content = content
|
self._content = content
|
||||||
|
|
||||||
|
def __str__(self) -> str: return self._content
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Identifier: {self._content}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class StringLiteral:
|
class StringLiteral:
|
||||||
|
|
||||||
|
@ -278,6 +303,12 @@ class StringLiteral:
|
||||||
):
|
):
|
||||||
self._content = content
|
self._content = content
|
||||||
|
|
||||||
|
def __str__(self) -> str: return self._content
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} String Literal: {self._content}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class CharLiteral:
|
class CharLiteral:
|
||||||
|
|
||||||
|
@ -289,6 +320,12 @@ class CharLiteral:
|
||||||
):
|
):
|
||||||
self._content = content
|
self._content = content
|
||||||
|
|
||||||
|
def __str__(self) -> str: return self._content
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Character Literal: {self._content}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class NumberLiteral:
|
class NumberLiteral:
|
||||||
|
|
||||||
|
@ -300,6 +337,12 @@ class NumberLiteral:
|
||||||
):
|
):
|
||||||
self._content = content
|
self._content = content
|
||||||
|
|
||||||
|
def __str__(self) -> str: return self._content
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Number Literal: {self._content}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class ArraySubscription:
|
class ArraySubscription:
|
||||||
|
|
||||||
|
@ -314,6 +357,11 @@ class ArraySubscription:
|
||||||
self._identifier = identifier
|
self._identifier = identifier
|
||||||
self._index = index
|
self._index = index
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Array Subscription: {self._identifier}\n"
|
||||||
|
s += f"{pre_cont}└─ Index: {self._index}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class FunctionArgument:
|
class FunctionArgument:
|
||||||
|
|
||||||
|
@ -322,12 +370,18 @@ class FunctionArgument:
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
identifier: Identifier,
|
identifier: Identifier | None,
|
||||||
value: Expression,
|
value: Expression,
|
||||||
):
|
):
|
||||||
self._identifier = identifier
|
self._identifier = identifier
|
||||||
self._value = value
|
self._value = value
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Function Argument\n"
|
||||||
|
if self._identifier: s += f"{pre_cont}├─ Name: {self._identifier}\n"
|
||||||
|
s += f"{pre_cont}└─ Value: {self._value}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class FunctionCall:
|
class FunctionCall:
|
||||||
|
|
||||||
|
@ -342,23 +396,41 @@ class FunctionCall:
|
||||||
self._identifier = identifier
|
self._identifier = identifier
|
||||||
self._args = args
|
self._args = args
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Function Call: {self._identifier}\n"
|
||||||
|
if self._args:
|
||||||
|
for arg in self._args[:-1]:
|
||||||
|
s += arg.tree_str(pre_cont + "├─", pre_cont + "│ ")
|
||||||
|
s += self._args[-1].tree_str(pre_cont + "└─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class TernaryExpression:
|
class TernaryExpression:
|
||||||
|
|
||||||
|
_operator: TernaryOperator
|
||||||
_operand1: Expression
|
_operand1: Expression
|
||||||
_operand2: Expression
|
_operand2: Expression
|
||||||
_operand3: Expression
|
_operand3: Expression
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
operator: TernaryOperator,
|
||||||
operand1: Expression,
|
operand1: Expression,
|
||||||
operand2: Expression,
|
operand2: Expression,
|
||||||
operand3: Expression,
|
operand3: Expression,
|
||||||
):
|
):
|
||||||
|
self._operator = operator
|
||||||
self._operand1 = operand1
|
self._operand1 = operand1
|
||||||
self._operand2 = operand2
|
self._operand2 = operand2
|
||||||
self._operand3 = operand3
|
self._operand3 = operand3
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Ternary Expression: {self._operator}\n"
|
||||||
|
s += self._operand1.tree_str(pre_cont + "├─", pre_cont + "│ ")
|
||||||
|
s += self._operand2.tree_str(pre_cont + "├─", pre_cont + "│ ")
|
||||||
|
s += self._operand3.tree_str(pre_cont + "└─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class BinaryExpression:
|
class BinaryExpression:
|
||||||
|
|
||||||
|
@ -376,6 +448,12 @@ class BinaryExpression:
|
||||||
self._operand1 = operand1
|
self._operand1 = operand1
|
||||||
self._operand2 = operand2
|
self._operand2 = operand2
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Binary Expression: {self._operator}\n"
|
||||||
|
s += self._operand1.tree_str(pre_cont + "├─", pre_cont + "│ ")
|
||||||
|
s += self._operand2.tree_str(pre_cont + "└─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class UnaryExpression:
|
class UnaryExpression:
|
||||||
|
|
||||||
|
@ -390,6 +468,11 @@ class UnaryExpression:
|
||||||
self._operator = operator
|
self._operator = operator
|
||||||
self._operand = operand
|
self._operand = operand
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Unary Expression: {self._operator}\n"
|
||||||
|
s += self._operand.tree_str(pre_cont + "└─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class LetStatement:
|
class LetStatement:
|
||||||
|
|
||||||
|
@ -413,6 +496,17 @@ class LetStatement:
|
||||||
self._static = static
|
self._static = static
|
||||||
self._assignment = assignment
|
self._assignment = assignment
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Let Statement: {self._identifier}\n"
|
||||||
|
s += pre_cont
|
||||||
|
s += '├─ Type: ' if self._assignment else '└─ Type: '
|
||||||
|
if self._static: s+= "static "
|
||||||
|
if self._pointer: s+= "@"
|
||||||
|
s += f"{self._type}\n"
|
||||||
|
if self._assignment is not None:
|
||||||
|
s += f"{pre_cont}└─ Default Value: {self._assignment}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class ElseBlock:
|
class ElseBlock:
|
||||||
|
|
||||||
|
@ -424,6 +518,15 @@ class ElseBlock:
|
||||||
):
|
):
|
||||||
self._code = code[:]
|
self._code = code[:]
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Else Block\n"
|
||||||
|
if self._code:
|
||||||
|
s += f"{pre_cont}└─ Code\n"
|
||||||
|
for code in self._code[:-1]:
|
||||||
|
s += code.tree_str(pre_cont + " ├─", pre_cont + " │ ")
|
||||||
|
s += self._code[-1].tree_str(pre_cont + " └─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class ForPreDef:
|
class ForPreDef:
|
||||||
|
|
||||||
|
@ -444,6 +547,14 @@ class ForPreDef:
|
||||||
self._pointer = pointer
|
self._pointer = pointer
|
||||||
self._assignment = assignment
|
self._assignment = assignment
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} For Loop Pre-Definition: {self._identifier}\n"
|
||||||
|
s += f"{pre_cont}├─ Type: "
|
||||||
|
if self._pointer: s+= "@"
|
||||||
|
s += f"{self._type}\n"
|
||||||
|
s += f"{pre_cont}└─ Value: {self._assignment}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class ForBlock:
|
class ForBlock:
|
||||||
|
|
||||||
|
@ -467,6 +578,37 @@ class ForBlock:
|
||||||
self._post_statement = post_statement
|
self._post_statement = post_statement
|
||||||
self._else = else_block
|
self._else = else_block
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} If Statement\n"
|
||||||
|
if self._code or self._else is not None:
|
||||||
|
cond_pre = f"{pre_cont}├─"
|
||||||
|
cond_pre_cont = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
cond_pre = f"{pre_cont}└─"
|
||||||
|
cond_pre_cont = f"{pre_cont} "
|
||||||
|
s += f"{cond_pre} Pre-Statement\n"
|
||||||
|
s += self._pre_statement.tree_str(
|
||||||
|
cond_pre_cont + "└─", cond_pre_cont + " ")
|
||||||
|
s += f"{cond_pre} Condition\n"
|
||||||
|
s += self._condition.tree_str(
|
||||||
|
cond_pre_cont + "└─", cond_pre_cont + " ")
|
||||||
|
s += f"{cond_pre} Post-Statement\n"
|
||||||
|
s += self._post_statement.tree_str(
|
||||||
|
cond_pre_cont + "└─", cond_pre_cont + " ")
|
||||||
|
if self._code:
|
||||||
|
if self._else is not None:
|
||||||
|
s += f"{pre_cont}├─ Code\n"
|
||||||
|
code_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Code\n"
|
||||||
|
code_pre = f"{pre_cont} "
|
||||||
|
for code in self._code[:-1]:
|
||||||
|
s += code.tree_str(code_pre + "├─", code_pre + "│ ")
|
||||||
|
s += self._code[-1].tree_str(code_pre + "└─", code_pre + " ")
|
||||||
|
if self._else is not None:
|
||||||
|
s += self._else.tree_str(pre_cont + "└─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class WhileBlock:
|
class WhileBlock:
|
||||||
|
|
||||||
|
@ -484,6 +626,29 @@ class WhileBlock:
|
||||||
self._code = code[:]
|
self._code = code[:]
|
||||||
self._else = else_block
|
self._else = else_block
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} While Loop\n"
|
||||||
|
if self._code or self._else is not None:
|
||||||
|
s += f"{pre_cont}├─ Condition\n"
|
||||||
|
cond_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Condition\n"
|
||||||
|
cond_pre = f"{pre_cont} "
|
||||||
|
s += self._condition.tree_str(cond_pre + "└─", cond_pre + " ")
|
||||||
|
if self._code:
|
||||||
|
if self._else is not None:
|
||||||
|
s += f"{pre_cont}├─ Code\n"
|
||||||
|
code_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Code\n"
|
||||||
|
code_pre = f"{pre_cont} "
|
||||||
|
for code in self._code[:-1]:
|
||||||
|
s += code.tree_str(code_pre + "├─", code_pre + "│ ")
|
||||||
|
s += self._code[-1].tree_str(code_pre + "└─", code_pre + " ")
|
||||||
|
if self._else is not None:
|
||||||
|
s += self._else.tree_str(pre_cont + "└─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class DoBlock:
|
class DoBlock:
|
||||||
|
|
||||||
|
@ -507,6 +672,41 @@ class DoBlock:
|
||||||
self._second_code = None
|
self._second_code = None
|
||||||
self._else = else_block
|
self._else = else_block
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Do Loop\n"
|
||||||
|
if self._first_code:
|
||||||
|
if self._second_code or self._else is not None:
|
||||||
|
s += f"{pre_cont}├─ First Code\n"
|
||||||
|
code_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ First Code\n"
|
||||||
|
code_pre = f"{pre_cont} "
|
||||||
|
for code in self._first_code[:-1]:
|
||||||
|
s += code.tree_str(code_pre + "├─", code_pre + "│ ")
|
||||||
|
s += self._first_code[-1].tree_str(
|
||||||
|
code_pre + "└─", code_pre + " ")
|
||||||
|
if self._second_code or self._else is not None:
|
||||||
|
s += f"{pre_cont}├─ Condition\n"
|
||||||
|
cond_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Condition\n"
|
||||||
|
cond_pre = f"{pre_cont} "
|
||||||
|
s += self._condition.tree_str(cond_pre + "└─", cond_pre + " ")
|
||||||
|
if self._second_code:
|
||||||
|
if self._else is not None:
|
||||||
|
s += f"{pre_cont}├─ Second Code\n"
|
||||||
|
code_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Second Code\n"
|
||||||
|
code_pre = f"{pre_cont} "
|
||||||
|
for code in self._second_code[:-1]:
|
||||||
|
s += code.tree_str(code_pre + "├─", code_pre + "│ ")
|
||||||
|
s += self._second_code[-1].tree_str(
|
||||||
|
code_pre + "└─", code_pre + " ")
|
||||||
|
if self._else is not None:
|
||||||
|
s += self._else.tree_str(pre_cont + "└─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class IfBlock:
|
class IfBlock:
|
||||||
|
|
||||||
|
@ -524,6 +724,29 @@ class IfBlock:
|
||||||
self._code = code[:]
|
self._code = code[:]
|
||||||
self._else = else_block
|
self._else = else_block
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} If Statement\n"
|
||||||
|
if self._code or self._else is not None:
|
||||||
|
s += f"{pre_cont}├─ Condition\n"
|
||||||
|
cond_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Condition\n"
|
||||||
|
cond_pre = f"{pre_cont} "
|
||||||
|
s += self._condition.tree_str(cond_pre + "└─", cond_pre + " ")
|
||||||
|
if self._code:
|
||||||
|
if self._else is not None:
|
||||||
|
s += f"{pre_cont}├─ Code\n"
|
||||||
|
code_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Code\n"
|
||||||
|
code_pre = f"{pre_cont} "
|
||||||
|
for code in self._code[:-1]:
|
||||||
|
s += code.tree_str(code_pre + "├─", code_pre + "│ ")
|
||||||
|
s += self._code[-1].tree_str(code_pre + "└─", code_pre + " ")
|
||||||
|
if self._else is not None:
|
||||||
|
s += self._else.tree_str(pre_cont + "└─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class FunctionParameter:
|
class FunctionParameter:
|
||||||
|
|
||||||
|
@ -544,13 +767,23 @@ class FunctionParameter:
|
||||||
self._pointer = pointer
|
self._pointer = pointer
|
||||||
self._default = default
|
self._default = default
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Function Parameter: {self._identifier}\n"
|
||||||
|
s += pre_cont
|
||||||
|
s += '├─ Type: ' if self._default else '└─ Type: '
|
||||||
|
if self._pointer: s+= "@"
|
||||||
|
s += f"{self._type}\n"
|
||||||
|
if self._default:
|
||||||
|
s += f"{pre_cont}└─ Default Value: {self._default}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class FunctionBlock:
|
class FunctionBlock:
|
||||||
|
|
||||||
_identifier: Identifier
|
_identifier: Identifier
|
||||||
_params: list[FunctionParameter]
|
_params: list[FunctionParameter]
|
||||||
_return_type_pointer: bool
|
_return_type_pointer: bool
|
||||||
_return_type: DataType
|
_return_type: DataType | None
|
||||||
_code: list[Statement]
|
_code: list[Statement]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -558,7 +791,7 @@ class FunctionBlock:
|
||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
params: list[FunctionParameter],
|
params: list[FunctionParameter],
|
||||||
return_type_pointer: bool,
|
return_type_pointer: bool,
|
||||||
return_type: DataType,
|
return_type: DataType | None,
|
||||||
code: list[Statement],
|
code: list[Statement],
|
||||||
):
|
):
|
||||||
self._identifier = identifier
|
self._identifier = identifier
|
||||||
|
@ -567,6 +800,32 @@ class FunctionBlock:
|
||||||
self._return_type = return_type
|
self._return_type = return_type
|
||||||
self._code = code[:]
|
self._code = code[:]
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Function: {self._identifier}\n"
|
||||||
|
if self._params:
|
||||||
|
if self._code or self._return_type is not None:
|
||||||
|
s += f"{pre_cont}├─ Parameters\n"
|
||||||
|
params_pre = f"{pre_cont}│ "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Parameters\n"
|
||||||
|
params_pre = f"{pre_cont} "
|
||||||
|
for param in self._params[:-1]:
|
||||||
|
s += param.tree_str(params_pre + "├─", params_pre + "│ ")
|
||||||
|
s += self._params[-1].tree_str(params_pre + "└─", params_pre + " ")
|
||||||
|
if self._return_type is not None:
|
||||||
|
if self._code:
|
||||||
|
s += f"{pre_cont}├─ Return Type: "
|
||||||
|
else:
|
||||||
|
s += f"{pre_cont}└─ Return Type: "
|
||||||
|
if self._return_type_pointer: s+= "@"
|
||||||
|
s += f"{self._return_type}\n"
|
||||||
|
if self._code:
|
||||||
|
s += f"{pre_cont}└─ Code\n"
|
||||||
|
for code in self._code[:-1]:
|
||||||
|
s += code.tree_str(pre_cont + " ├─", pre_cont + " │ ")
|
||||||
|
s += self._code[-1].tree_str(pre_cont + " └─", pre_cont + " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class EnumMember:
|
class EnumMember:
|
||||||
|
|
||||||
|
@ -581,6 +840,12 @@ class EnumMember:
|
||||||
self._identifier = identifier
|
self._identifier = identifier
|
||||||
self._value = value
|
self._value = value
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Enum Member: {self._identifier}\n"
|
||||||
|
if self._value is not None:
|
||||||
|
s += f"{pre_cont}└─ Value: {self._value}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class EnumBlock:
|
class EnumBlock:
|
||||||
|
|
||||||
|
@ -595,6 +860,14 @@ class EnumBlock:
|
||||||
self._identifier = identifier
|
self._identifier = identifier
|
||||||
self._members = members[:]
|
self._members = members[:]
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Enum: {self._identifier}\n"
|
||||||
|
if self._members:
|
||||||
|
for member in self._members[:-1]:
|
||||||
|
s += member.tree_str(pre_cont + "├─", pre_cont + "│ ")
|
||||||
|
s += self._members[-1].tree_str(pre_cont + "└─", pre_cont + "│ ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class StructureMember:
|
class StructureMember:
|
||||||
|
|
||||||
|
@ -618,6 +891,17 @@ class StructureMember:
|
||||||
self._static = static
|
self._static = static
|
||||||
self._default = default
|
self._default = default
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Struct Member: {self._identifier}\n"
|
||||||
|
s += pre_cont
|
||||||
|
s += '├─ Type: ' if self._default else '└─ Type: '
|
||||||
|
if self._static: s+= "static "
|
||||||
|
if self._pointer: s+= "@"
|
||||||
|
s += f"{self._type}\n"
|
||||||
|
if self._default is not None:
|
||||||
|
s += f"{pre_cont}└─ Default Value: {self._default}\n"
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class StructBlock:
|
class StructBlock:
|
||||||
|
|
||||||
|
@ -632,6 +916,14 @@ class StructBlock:
|
||||||
self._identifier = identifier
|
self._identifier = identifier
|
||||||
self._members = members[:]
|
self._members = members[:]
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
s: str = f"{pre} Struct: {self._identifier}\n"
|
||||||
|
if self._members:
|
||||||
|
for member in self._members[:-1]:
|
||||||
|
s += member.tree_str(pre_cont + "├─", pre_cont + "│ ")
|
||||||
|
s += self._members[-1].tree_str(pre_cont + "└─", pre_cont + "│ ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
class Directive:
|
class Directive:
|
||||||
|
|
||||||
|
@ -643,6 +935,9 @@ class Directive:
|
||||||
):
|
):
|
||||||
self._content = content
|
self._content = content
|
||||||
|
|
||||||
|
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
|
||||||
|
return f"{pre} Directive: {self._content}\n"
|
||||||
|
|
||||||
|
|
||||||
class File:
|
class File:
|
||||||
|
|
||||||
|
@ -654,6 +949,14 @@ class File:
|
||||||
):
|
):
|
||||||
self._children = children[:]
|
self._children = children[:]
|
||||||
|
|
||||||
|
def tree_str(self) -> str:
|
||||||
|
s: str = "File\n"
|
||||||
|
if self._children:
|
||||||
|
for child in self._children[:-1]:
|
||||||
|
s += child.tree_str("├─", "│ ")
|
||||||
|
s += self._children[-1].tree_str("└─", " ")
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
def _assert_token(
|
def _assert_token(
|
||||||
exception: type[_ExpectedTokenBase],
|
exception: type[_ExpectedTokenBase],
|
||||||
|
@ -693,8 +996,8 @@ def _assert_token_literal(
|
||||||
type(token).__name__,
|
type(token).__name__,
|
||||||
)
|
)
|
||||||
if isinstance(token, lexer.Keyword):
|
if isinstance(token, lexer.Keyword):
|
||||||
if token.value not in BuildInConst:
|
if token.value not in BuiltInConst:
|
||||||
raise UnexpectedKeyword(token, [i.value for i in DefaultDataType])
|
raise UnexpectedKeyword(token, [i.value for i in BuiltInDataType])
|
||||||
|
|
||||||
def _literal_map(literal: (
|
def _literal_map(literal: (
|
||||||
lexer.Keyword |
|
lexer.Keyword |
|
||||||
|
@ -703,7 +1006,45 @@ def _literal_map(literal: (
|
||||||
lexer.StringLiteral
|
lexer.StringLiteral
|
||||||
)) -> Literal:
|
)) -> Literal:
|
||||||
if isinstance(literal, lexer.Keyword):
|
if isinstance(literal, lexer.Keyword):
|
||||||
return BuildInConst(literal.value)
|
return BuiltInConst(literal.value)
|
||||||
|
elif isinstance(literal, lexer.NumberLiteral):
|
||||||
|
return NumberLiteral(literal.value)
|
||||||
|
elif isinstance(literal, lexer.CharLiteral):
|
||||||
|
return CharLiteral(literal.value)
|
||||||
|
elif isinstance(literal, lexer.StringLiteral):
|
||||||
|
return StringLiteral(literal.value)
|
||||||
|
|
||||||
|
def _assert_token_value(
|
||||||
|
token: lexer.Token,
|
||||||
|
):
|
||||||
|
token_types = (
|
||||||
|
lexer.Identifier,
|
||||||
|
lexer.Keyword,
|
||||||
|
lexer.NumberLiteral,
|
||||||
|
lexer.CharLiteral,
|
||||||
|
lexer.StringLiteral,
|
||||||
|
)
|
||||||
|
if not isinstance(token, token_types):
|
||||||
|
raise ExpectedLiteral(
|
||||||
|
token,
|
||||||
|
[i.__name__ for i in token_types], # type: ignore
|
||||||
|
type(token).__name__,
|
||||||
|
)
|
||||||
|
if isinstance(token, lexer.Keyword):
|
||||||
|
if token.value not in BuiltInConst:
|
||||||
|
raise UnexpectedKeyword(token, [i.value for i in BuiltInDataType])
|
||||||
|
|
||||||
|
def _value_map(literal: (
|
||||||
|
lexer.Identifier |
|
||||||
|
lexer.Keyword |
|
||||||
|
lexer.NumberLiteral |
|
||||||
|
lexer.CharLiteral |
|
||||||
|
lexer.StringLiteral
|
||||||
|
)) -> Literal | Identifier:
|
||||||
|
if isinstance(literal, lexer.Identifier):
|
||||||
|
return Identifier(literal.value)
|
||||||
|
elif isinstance(literal, lexer.Keyword):
|
||||||
|
return BuiltInConst(literal.value)
|
||||||
elif isinstance(literal, lexer.NumberLiteral):
|
elif isinstance(literal, lexer.NumberLiteral):
|
||||||
return NumberLiteral(literal.value)
|
return NumberLiteral(literal.value)
|
||||||
elif isinstance(literal, lexer.CharLiteral):
|
elif isinstance(literal, lexer.CharLiteral):
|
||||||
|
@ -734,11 +1075,11 @@ def _get_nested_group(
|
||||||
|
|
||||||
def _get_to_symbol(
|
def _get_to_symbol(
|
||||||
tokens: list[lexer.Token],
|
tokens: list[lexer.Token],
|
||||||
symbol: str = ';',
|
symbols: str | Sequence[str] = ';',
|
||||||
) -> list[lexer.Token]:
|
) -> list[lexer.Token]:
|
||||||
expr_len = -1
|
expr_len = -1
|
||||||
for i in range(len(tokens)):
|
for i in range(len(tokens)):
|
||||||
if tokens[i].value == symbol:
|
if tokens[i].value in symbols:
|
||||||
expr_len = i
|
expr_len = i
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
@ -819,7 +1160,9 @@ def _function_sa(tokens: list[lexer.Token]) -> FunctionBlock:
|
||||||
params: list[FunctionParameter] = []
|
params: list[FunctionParameter] = []
|
||||||
while token.value != ')':
|
while token.value != ')':
|
||||||
token = tokens.pop(0)
|
token = tokens.pop(0)
|
||||||
if isinstance(token, lexer.Identifier):
|
if isinstance(token, lexer.Punctuation):
|
||||||
|
_assert_token(ExpectedPunctuation, token, ')')
|
||||||
|
elif isinstance(token, lexer.Identifier):
|
||||||
member_id = Identifier(token.value)
|
member_id = Identifier(token.value)
|
||||||
token = tokens.pop(0)
|
token = tokens.pop(0)
|
||||||
_assert_token(ExpectedPunctuation, token, ':')
|
_assert_token(ExpectedPunctuation, token, ':')
|
||||||
|
@ -840,11 +1183,12 @@ def _function_sa(tokens: list[lexer.Token]) -> FunctionBlock:
|
||||||
params.append(
|
params.append(
|
||||||
FunctionParameter(member_id, data_type, pointer, literal))
|
FunctionParameter(member_id, data_type, pointer, literal))
|
||||||
else:
|
else:
|
||||||
raise UnexpectedToken(token, ["Keyword", "Identifier"])
|
raise UnexpectedToken(
|
||||||
|
token, ["Keyword", "Identifier", "Punctuation"])
|
||||||
token = tokens.pop(0)
|
token = tokens.pop(0)
|
||||||
_assert_token(ExpectedPunctuation, token, '->')
|
_assert_token(ExpectedPunctuation, token, '->')
|
||||||
pointer, return_type = _data_type_sa(tokens)
|
pointer, return_type = _data_type_sa(tokens)
|
||||||
code = _code_block_sa(tokens)
|
code = _code_block_sa(_get_nested_group(tokens, ('{','}')))
|
||||||
return FunctionBlock(
|
return FunctionBlock(
|
||||||
Identifier(identifier.value),
|
Identifier(identifier.value),
|
||||||
params,
|
params,
|
||||||
|
@ -861,40 +1205,39 @@ def _data_type_sa(tokens: list[lexer.Token]) -> tuple[bool, DataType]:
|
||||||
lexer.Punctuation,
|
lexer.Punctuation,
|
||||||
))
|
))
|
||||||
if isinstance(token, lexer.Punctuation):
|
if isinstance(token, lexer.Punctuation):
|
||||||
_assert_token(ExpectedPunctuation, token, '*')
|
_assert_token(ExpectedPunctuation, token, '@')
|
||||||
pointer = True
|
pointer = True
|
||||||
token = tokens.pop(0)
|
token = tokens.pop(0)
|
||||||
_assert_token_mult(token, (lexer.Keyword, lexer.Identifier))
|
_assert_token_mult(token, (lexer.Keyword, lexer.Identifier))
|
||||||
else:
|
else:
|
||||||
pointer = False
|
pointer = False
|
||||||
if isinstance(token, lexer.Keyword):
|
if isinstance(token, lexer.Keyword):
|
||||||
if token.value not in DefaultDataType:
|
if token.value not in BuiltInDataType:
|
||||||
raise UnexpectedKeyword(
|
raise UnexpectedKeyword(
|
||||||
token,
|
token,
|
||||||
[i.value for i in DefaultDataType],
|
[i.value for i in BuiltInDataType],
|
||||||
)
|
)
|
||||||
return pointer, DefaultDataType(token.value)
|
return pointer, BuiltInDataType(token.value)
|
||||||
else:
|
else:
|
||||||
return pointer, Identifier(token.value)
|
return pointer, Identifier(token.value)
|
||||||
|
|
||||||
def _code_block_sa(
|
def _code_block_sa(tokens: list[lexer.Token]) -> list[Statement]:
|
||||||
tokens: list[lexer.Token],
|
|
||||||
encloses: tuple[str, str] = ('{','}'),
|
|
||||||
) -> list[Statement]:
|
|
||||||
token = tokens.pop(0)
|
|
||||||
_assert_token(ExpectedPunctuation, token, encloses[0])
|
|
||||||
code: list[Statement] = []
|
code: list[Statement] = []
|
||||||
while tokens[0].value != encloses[1]:
|
while tokens:
|
||||||
code.append(_statement_sa(tokens))
|
code.append(_statement_sa(tokens))
|
||||||
return code
|
return code
|
||||||
|
|
||||||
def _expression_sa(tokens: list[lexer.Token]) -> Expression:
|
def _expression_sa(tokens: list[lexer.Token]) -> Expression:
|
||||||
if tokens[0] == '(' and tokens[-1] == ')':
|
print([(type(i).__name__, i.value) for i in tokens])
|
||||||
|
if not tokens:
|
||||||
|
raise UnexpectedEndOfTokenStream(
|
||||||
|
"Unexpected Expression.", None) # type: ignore
|
||||||
|
if tokens[0].value == '(' and tokens[-1].value == ')':
|
||||||
return _expression_sa(tokens[1:-1])
|
return _expression_sa(tokens[1:-1])
|
||||||
elif len(tokens) == 1:
|
elif len(tokens) == 1:
|
||||||
token = tokens.pop(0)
|
token = tokens.pop(0)
|
||||||
_assert_token_literal(token)
|
_assert_token_value(token)
|
||||||
return _literal_map(token) # type: ignore
|
return _value_map(token) # type: ignore
|
||||||
|
|
||||||
max_operator: int = -1
|
max_operator: int = -1
|
||||||
max_operator_precedence: int = -1
|
max_operator_precedence: int = -1
|
||||||
|
@ -905,7 +1248,7 @@ def _expression_sa(tokens: list[lexer.Token]) -> Expression:
|
||||||
if nested == 0:
|
if nested == 0:
|
||||||
raise UnexpectedPunctuation(token, "(' before ')", token.value)
|
raise UnexpectedPunctuation(token, "(' before ')", token.value)
|
||||||
nested -= 1
|
nested -= 1
|
||||||
if nested == 0 and isinstance(token, lexer.Punctuation):
|
elif nested == 0 and isinstance(token, lexer.Punctuation):
|
||||||
for j, operator in reversed(list(enumerate(_Operator_Precedence))):
|
for j, operator in reversed(list(enumerate(_Operator_Precedence))):
|
||||||
if j <= max_operator_precedence:
|
if j <= max_operator_precedence:
|
||||||
break
|
break
|
||||||
|
@ -914,38 +1257,42 @@ def _expression_sa(tokens: list[lexer.Token]) -> Expression:
|
||||||
max_operator_precedence = j
|
max_operator_precedence = j
|
||||||
break
|
break
|
||||||
|
|
||||||
if tokens[max_operator].value in UnaryOperator:
|
if max_operator == -1:
|
||||||
if tokens[max_operator].value in (
|
function_identifier = tokens.pop(0)
|
||||||
UnaryOperator.PostfixDecrement,
|
_assert_token(ExpectedIdentifier, function_identifier)
|
||||||
UnaryOperator.PostfixIncrement,
|
token = tokens.pop(0)
|
||||||
) and max_operator == len(tokens) - 1:
|
_assert_token(ExpectedPunctuation, token, '(')
|
||||||
operators = {
|
function_args: list[FunctionArgument] = []
|
||||||
'--': UnaryOperator.PostfixDecrement,
|
while tokens:
|
||||||
'++': UnaryOperator.PostfixIncrement,
|
arg_tokens = _get_to_symbol(tokens, (',', ')'))
|
||||||
}
|
if arg_tokens:
|
||||||
return UnaryExpression(
|
if len(arg_tokens) > 1 and arg_tokens[1].value == '=':
|
||||||
operators[tokens[max_operator].value],
|
_assert_token(ExpectedIdentifier, arg_tokens[0])
|
||||||
_expression_sa(tokens[:max_operator]),
|
arg_identifier = Identifier(arg_tokens[0].value)
|
||||||
)
|
del arg_tokens[:2]
|
||||||
elif tokens[max_operator].value in (
|
else:
|
||||||
UnaryOperator.PrefixDecrement,
|
arg_identifier = None
|
||||||
UnaryOperator.PrefixIncrement,
|
function_args.append(FunctionArgument(
|
||||||
) and max_operator == 0:
|
arg_identifier, _expression_sa(arg_tokens)))
|
||||||
operators = {
|
return FunctionCall(
|
||||||
'--': UnaryOperator.PrefixDecrement,
|
Identifier(function_identifier.value), function_args)
|
||||||
'++': UnaryOperator.PrefixIncrement,
|
|
||||||
}
|
if (
|
||||||
return UnaryExpression(
|
tokens[max_operator].value in PostfixUnaryOperator and
|
||||||
operators[tokens[max_operator].value],
|
max_operator == len(tokens) - 1
|
||||||
_expression_sa(tokens[max_operator+1:]),
|
):
|
||||||
)
|
return UnaryExpression(
|
||||||
elif max_operator == 0:
|
PostfixUnaryOperator(tokens[max_operator].value),
|
||||||
return UnaryExpression(
|
_expression_sa(tokens[:max_operator]),
|
||||||
UnaryOperator(tokens[max_operator].value),
|
)
|
||||||
_expression_sa(tokens[max_operator+1:]),
|
elif (
|
||||||
)
|
tokens[max_operator].value in PrefixUnaryOperator and
|
||||||
else: raise CompilerError(
|
max_operator == 0
|
||||||
"Operator Precedence Error", tokens[max_operator].file_info)
|
):
|
||||||
|
return UnaryExpression(
|
||||||
|
PrefixUnaryOperator(tokens[max_operator].value),
|
||||||
|
_expression_sa(tokens[max_operator+1:]),
|
||||||
|
)
|
||||||
elif tokens[max_operator].value in BinaryOperator:
|
elif tokens[max_operator].value in BinaryOperator:
|
||||||
return BinaryExpression(
|
return BinaryExpression(
|
||||||
BinaryOperator(tokens[max_operator].value),
|
BinaryOperator(tokens[max_operator].value),
|
||||||
|
@ -957,7 +1304,12 @@ def _expression_sa(tokens: list[lexer.Token]) -> Expression:
|
||||||
del tokens[:max_operator]
|
del tokens[:max_operator]
|
||||||
true_expr = _expression_sa(_get_nested_group(tokens, ('?', ':')))
|
true_expr = _expression_sa(_get_nested_group(tokens, ('?', ':')))
|
||||||
false_expr = _expression_sa(tokens)
|
false_expr = _expression_sa(tokens)
|
||||||
return TernaryExpression(condition, true_expr, false_expr)
|
return TernaryExpression(
|
||||||
|
TernaryOperator.TernaryConditional,
|
||||||
|
condition,
|
||||||
|
true_expr,
|
||||||
|
false_expr,
|
||||||
|
)
|
||||||
else: raise CompilerError(
|
else: raise CompilerError(
|
||||||
"Expression Error", tokens[max_operator].file_info)
|
"Expression Error", tokens[max_operator].file_info)
|
||||||
|
|
||||||
|
@ -1071,7 +1423,7 @@ def _statement_sa(tokens: list[lexer.Token]) -> Statement:
|
||||||
else_block = None
|
else_block = None
|
||||||
return ForBlock(
|
return ForBlock(
|
||||||
pre_loop, condition, code, post_loop, else_block)
|
pre_loop, condition, code, post_loop, else_block)
|
||||||
case key if key not in BuildInConst:
|
case key if key not in BuiltInConst:
|
||||||
raise UnexpectedKeyword(token, [
|
raise UnexpectedKeyword(token, [
|
||||||
'static',
|
'static',
|
||||||
'let',
|
'let',
|
||||||
|
@ -1081,7 +1433,7 @@ def _statement_sa(tokens: list[lexer.Token]) -> Statement:
|
||||||
'do',
|
'do',
|
||||||
'while',
|
'while',
|
||||||
'for',
|
'for',
|
||||||
] + [i.value for i in BuildInConst])
|
] + [i.value for i in BuiltInConst])
|
||||||
expr_tokens: list[lexer.Token] = [token] + _get_to_symbol(tokens)
|
expr_tokens: list[lexer.Token] = [token] + _get_to_symbol(tokens)
|
||||||
return _expression_sa(expr_tokens)
|
return _expression_sa(expr_tokens)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue