More compiler fixes

This commit is contained in:
Kyler 2024-03-05 23:51:01 -07:00
parent c2051ffce4
commit e833d2e311
4 changed files with 220 additions and 49 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
docs/*.pdf docs/*.pdf
__pycache__ __pycache__
bin bin
.vscode

View File

@ -237,35 +237,36 @@ and a `literal`.
#### If Statement #### If Statement
An `if statement` begins with the `if` keyword, followed by its condition, an An `if statement` begins with the `if` keyword, followed by its condition, an
`expression` enclosed in parentheses (`(` and `)`), then a list enclosed in `expression` enclosed in parentheses (`(` and `)`), then a single `statement`
curly braces (`{` and `}`) of `statements`. It may then optionally be followed or a list enclosed in curly braces (`{` and `}`) of `statements`. It may then
by an `else block`. optionally be followed by an `else block`.
#### Do Loop #### Do Loop
A `do loop` begins with the `do` keyword, followed by a list enclosed in curly A `do loop` begins with the `do` keyword, followed by a single `statement` or a
braces (`{` and `}`) of `statements`. It is then followed with the `while` list enclosed in curly braces (`{` and `}`) of `statements`. It is then followed
keyword, then by its condition, an `expression` enclosed in parentheses with the `while` keyword, then by its condition, an `expression` enclosed in
(`(` and `)`). It may then optionally be followed by another list enclosed in parentheses (`(` and `)`). It may then optionally be followed by a single
curly braces (`{` and `}`) of `statements`. Finally the `do loop` may optionally `statement` or another list enclosed in curly braces (`{` and `}`) of
be followed by an `else block`. `statements`. Finally the `do loop` may optionally be followed by an
`else block`.
#### While Loop #### While Loop
A `while loop` begins with the `while` keyword, followed by its condition, an A `while loop` begins with the `while` keyword, followed by its condition, an
`expression` enclosed in parentheses (`(` and `)`), then a list enclosed in `expression` enclosed in parentheses (`(` and `)`), then a single `statement`
curly braces (`{` and `}`) of `statements`. It may then or a list enclosed in curly braces (`{` and `}`) of `statements`. It may then
optionally be followed by an `else block`. optionally be followed by an `else block`.
#### For Loop #### For Loop
A `for loop` begins with the `for` keyword, followed by three expressions A `for loop` begins with the `for` keyword, followed by three expressions
enclosed in parentheses (`(` and `)`), separated by semicolons (`;`). The first enclosed in parentheses (`(` and `)`), separated by semicolons (`;`). The
expression is a *pre-loop expression*, the second is its condition which is a first expression is a *pre-loop expression*, the second is its condition which
normal `expression`, and the last is its post-loop expression which is another is a normal `expression`, and the last is its post-loop expression which is
normal `expression`. It is ended with a list enclosed in curly braces another normal `expression`. It is ended with a single `statement` or a list
(`{` and `}`) of `statements`. It may then optionally be enclosed in curly braces (`{` and `}`) of `statements`. It may then optionally
followed by an `else block`. be followed by an `else block`.
##### Pre-Loop Expression ##### Pre-Loop Expression
@ -275,8 +276,8 @@ then an equal sign (`=`) followed by an `expression`.
#### Else Block #### Else Block
An `else block` begins with the `else` keyword, followed by a list enclosed in An `else block` begins with the `else` keyword, followed by a single
curly braces (`{` and `}`) of `statements`. `statement` or a list enclosed in curly braces (`{` and `}`) of `statements`.
#### Let Statement #### Let Statement

View File

@ -82,6 +82,131 @@ fn test_func2() -> Point {
test = '"'; test = '"';
test = "Hello World!"; test = "Hello World!";
test = "This is \"cool\"!"; test = "This is \"cool\"!";
break;
continue;
if (test >= 10);
if (test >= 20)
test -= 2;
test -= 3;
if (test >= 20)
test -= 2;
else
test -= 3;
if (test >= 30) {
test -= 4;
test -= 5;
}
if (test >= 40) {
test -= 6;
} else {
test += 15;
}
if (test >= 50) {
test -= 7;
} else if (test >= 60) {
test--;
} else {
test += 16;
}
do
test += 17;
while (test);
do
test += 18;
while (test)
test += 19;
do
test += 20;
while (test)
else
test += 21;
do
test += 22;
while (test)
test += 23;
else
test += 24;
do
test += 25;
while (test)
test += 26;
else if (test == 32)
test += 27;
do {
test += 18;
} while (test);
do {
test += 29;
} while (test) {
test += 30;
}
do {
test += 31;
} while (test)
else {
test += 32;
}
do {
test += 33;
} while (test) {
test += 34;
} else {
test += 35;
}
while (test >= 20)
test -= 2;
test -= 3;
while (test >= 20)
test -= 2;
else
test -= 3;
while (test >= 30) {
test -= 4;
test -= 5;
}
while (test >= 40) {
test -= 6;
} else {
test += 15;
}
for (i: int = 0; i < length; i++)
$(inData + i) ^= $(pass + ((i + offset) % pLength));
for (i: int = 0; i < length; i++)
$(inData + i) ^= $(pass + ((i + offset) % pLength));
else
test = 16;
for (i: int; i < length; i++) {
$(inData + i) ^= $(pass + ((i + offset) % pLength));
}
for (i = 0; i < length; i++) {
$(inData + i) ^= $(pass + ((i + offset) % pLength));
} else {
test = 17;
}
} }
fn main() -> int { fn main() -> int {

View File

@ -142,7 +142,8 @@ type Expression = (
UnaryExpression | UnaryExpression |
BinaryExpression | BinaryExpression |
TernaryExpression | TernaryExpression |
FunctionCall FunctionCall |
NoOperation
) )
type Statement = Expression | LetStatement | LoopStatements | NestableCodeBlock type Statement = Expression | LetStatement | LoopStatements | NestableCodeBlock
@ -167,7 +168,7 @@ class LoopStatements(Enum):
BreakStatement = "break" BreakStatement = "break"
def tree_str(self, pre: str = "", pre_cont: str = "") -> str: def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
s: str = f"{pre} {self.value.upper()}\n" s: str = f"{pre} {self.value.lower()}\n"
return s return s
@ -276,6 +277,13 @@ _Operator_Precedence: tuple[
) )
class NoOperation:
def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
s: str = f"{pre} Nop\n"
return s
class Identifier: class Identifier:
_content: str _content: str
@ -533,14 +541,14 @@ class ForPreDef:
_identifier: Identifier _identifier: Identifier
_type: DataType _type: DataType
_pointer: bool _pointer: bool
_assignment: Expression _assignment: Expression | None
def __init__( def __init__(
self, self,
identifier: Identifier, identifier: Identifier,
type: DataType, type: DataType,
pointer: bool, pointer: bool,
assignment: Expression, assignment: Expression | None,
): ):
self._identifier = identifier self._identifier = identifier
self._type = type self._type = type
@ -549,10 +557,11 @@ class ForPreDef:
def tree_str(self, pre: str = "", pre_cont: str = "") -> str: def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
s: str = f"{pre} For Loop Pre-Definition: {self._identifier}\n" s: str = f"{pre} For Loop Pre-Definition: {self._identifier}\n"
s += f"{pre_cont}├─ Type: " if self._assignment: s += f"{pre_cont}├─ Type: "
else: s += f"{pre_cont}└─ Type: "
if self._pointer: s+= "@" if self._pointer: s+= "@"
s += f"{self._type}\n" s += f"{self._type}\n"
s += f"{pre_cont}└─ Value: {self._assignment}\n" if self._assignment: s += f"{pre_cont}└─ Value: {self._assignment}\n"
return s return s
@ -579,7 +588,7 @@ class ForBlock:
self._else = else_block self._else = else_block
def tree_str(self, pre: str = "", pre_cont: str = "") -> str: def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
s: str = f"{pre} If Statement\n" s: str = f"{pre} For Loop\n"
if self._code or self._else is not None: if self._code or self._else is not None:
cond_pre = f"{pre_cont}├─" cond_pre = f"{pre_cont}├─"
cond_pre_cont = f"{pre_cont}" cond_pre_cont = f"{pre_cont}"
@ -675,12 +684,8 @@ class DoBlock:
def tree_str(self, pre: str = "", pre_cont: str = "") -> str: def tree_str(self, pre: str = "", pre_cont: str = "") -> str:
s: str = f"{pre} Do Loop\n" s: str = f"{pre} Do Loop\n"
if self._first_code: if self._first_code:
if self._second_code or self._else is not None: s += f"{pre_cont}├─ First Code\n"
s += f"{pre_cont}├─ First Code\n" code_pre = f"{pre_cont}"
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]: for code in self._first_code[:-1]:
s += code.tree_str(code_pre + "├─", code_pre + "") s += code.tree_str(code_pre + "├─", code_pre + "")
s += self._first_code[-1].tree_str( s += self._first_code[-1].tree_str(
@ -950,7 +955,7 @@ class File:
self._children = children[:] self._children = children[:]
def tree_str(self) -> str: def tree_str(self) -> str:
s: str = "File\n" s: str = " File\n"
if self._children: if self._children:
for child in self._children[:-1]: for child in self._children[:-1]:
s += child.tree_str("├─", "") s += child.tree_str("├─", "")
@ -1353,31 +1358,59 @@ def _statement_sa(tokens: list[lexer.Token]) -> Statement:
return LoopStatements(key) return LoopStatements(key)
case 'if': case 'if':
condition = _expression_sa(_get_nested_group(tokens)) condition = _expression_sa(_get_nested_group(tokens))
code = _code_block_sa(tokens) if tokens[0].value == '{':
if tokens[0].value == 'else': code = _code_block_sa(_get_nested_group(tokens, ('{','}')))
else_block = ElseBlock(_code_block_sa(tokens)) else:
code = [_statement_sa(tokens)]
if tokens and tokens[0].value == 'else':
token = tokens.pop(0)
if tokens[0].value == '{':
else_block = ElseBlock(_code_block_sa(_get_nested_group(
tokens, ('{','}'))))
else:
else_block = ElseBlock([_statement_sa(tokens)])
else: else:
else_block = None else_block = None
return IfBlock(condition, code, else_block) return IfBlock(condition, code, else_block)
case 'do': case 'do':
code1 = _code_block_sa(tokens) if tokens[0].value == '{':
code1 = _code_block_sa(_get_nested_group(tokens, ('{','}')))
else:
code1 = [_statement_sa(tokens)]
token = tokens.pop(0) token = tokens.pop(0)
_assert_token(ExpectedKeyword, token, 'while') _assert_token(ExpectedKeyword, token, 'while')
condition = _expression_sa(_get_nested_group(tokens)) condition = _expression_sa(_get_nested_group(tokens))
if tokens[0].value == '{': if tokens[0].value == '{':
code2 = _code_block_sa(tokens) code2 = _code_block_sa(_get_nested_group(tokens, ('{','}')))
elif tokens[0].value != 'else':
code2 = [_statement_sa(tokens)]
if isinstance(code2[0], NoOperation):
code2 = None
else: else:
code2 = None code2 = None
if tokens[0].value == 'else': if tokens and tokens[0].value == 'else':
else_block = ElseBlock(_code_block_sa(tokens)) token = tokens.pop(0)
if tokens[0].value == '{':
else_block = ElseBlock(_code_block_sa(_get_nested_group(
tokens, ('{','}'))))
else:
else_block = ElseBlock([_statement_sa(tokens)])
else: else:
else_block = None else_block = None
return DoBlock(code1, condition, code2, else_block) return DoBlock(code1, condition, code2, else_block)
case 'while': case 'while':
condition = _expression_sa(_get_nested_group(tokens)) condition = _expression_sa(_get_nested_group(tokens))
code = _code_block_sa(tokens) if tokens[0].value == '{':
if tokens[0].value == 'else': code = _code_block_sa(_get_nested_group(tokens, ('{','}')))
else_block = ElseBlock(_code_block_sa(tokens)) else:
code = [_statement_sa(tokens)]
if tokens and tokens[0].value == 'else':
token = tokens.pop(0)
if tokens[0].value == '{':
else_block = ElseBlock(_code_block_sa(_get_nested_group(
tokens, ('{','}'))))
else:
else_block = ElseBlock([_statement_sa(tokens)])
else: else:
else_block = None else_block = None
return WhileBlock(condition, code, else_block) return WhileBlock(condition, code, else_block)
@ -1388,9 +1421,8 @@ def _statement_sa(tokens: list[lexer.Token]) -> Statement:
while token.value != ';': while token.value != ';':
pre_loop_tokens.append(token) pre_loop_tokens.append(token)
token = three_expressions.pop(0) token = three_expressions.pop(0)
token = three_expressions.pop(0)
if ( if (
type(pre_loop_tokens[0]) is lexer.Identifier and isinstance(pre_loop_tokens[0], lexer.Identifier) and
pre_loop_tokens[1].value == ':' pre_loop_tokens[1].value == ':'
): ):
identifier = Identifier(pre_loop_tokens.pop(0).value) identifier = Identifier(pre_loop_tokens.pop(0).value)
@ -1401,6 +1433,8 @@ def _statement_sa(tokens: list[lexer.Token]) -> Statement:
token = pre_loop_tokens.pop(0) token = pre_loop_tokens.pop(0)
_assert_token(ExpectedPunctuation, token, '=') _assert_token(ExpectedPunctuation, token, '=')
pre_loop_expr = _expression_sa(pre_loop_tokens) pre_loop_expr = _expression_sa(pre_loop_tokens)
else:
pre_loop_expr = None
pre_loop = ForPreDef( pre_loop = ForPreDef(
identifier, identifier,
data_type, data_type,
@ -1409,16 +1443,24 @@ def _statement_sa(tokens: list[lexer.Token]) -> Statement:
) )
else: else:
pre_loop = _expression_sa(pre_loop_tokens) pre_loop = _expression_sa(pre_loop_tokens)
token = three_expressions.pop(0)
loop_condition_tokens: list[lexer.Token] = [] loop_condition_tokens: list[lexer.Token] = []
while token.value != ';': while token.value != ';':
loop_condition_tokens.append(token) loop_condition_tokens.append(token)
token = three_expressions.pop(0) token = three_expressions.pop(0)
token = three_expressions.pop(0)
condition = _expression_sa(loop_condition_tokens) condition = _expression_sa(loop_condition_tokens)
post_loop = _expression_sa(three_expressions) post_loop = _expression_sa(three_expressions)
code = _code_block_sa(tokens) if tokens[0].value == '{':
if tokens[0].value == 'else': code = _code_block_sa(_get_nested_group(tokens, ('{','}')))
else_block = ElseBlock(_code_block_sa(tokens)) else:
code = [_statement_sa(tokens)]
if tokens and tokens[0].value == 'else':
token = tokens.pop(0)
if tokens[0].value == '{':
else_block = ElseBlock(_code_block_sa(_get_nested_group(
tokens, ('{','}'))))
else:
else_block = ElseBlock([_statement_sa(tokens)])
else: else:
else_block = None else_block = None
return ForBlock( return ForBlock(
@ -1434,6 +1476,8 @@ def _statement_sa(tokens: list[lexer.Token]) -> Statement:
'while', 'while',
'for', 'for',
] + [i.value for i in BuiltInConst]) ] + [i.value for i in BuiltInConst])
elif token.value == ';':
return NoOperation()
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)