started work on assignment operators
This commit is contained in:
20
AST.py
20
AST.py
@@ -21,6 +21,7 @@ class NodeType(Enum):
|
|||||||
# Expressions
|
# Expressions
|
||||||
InfixExpression = "InfixExpression"
|
InfixExpression = "InfixExpression"
|
||||||
CallExpression = "CallExpression"
|
CallExpression = "CallExpression"
|
||||||
|
PrefixExpression = "PrefixExpression"
|
||||||
|
|
||||||
# Literals
|
# Literals
|
||||||
IntegerLiteral = "IntegerLiteral"
|
IntegerLiteral = "IntegerLiteral"
|
||||||
@@ -221,8 +222,9 @@ class FunctionStatement(Statement):
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ReassignStatement(Statement):
|
class ReassignStatement(Statement):
|
||||||
def __init__(self, ident: Expression = None, right_value: Expression = None) -> None:
|
def __init__(self, ident: Expression = None, operator: str = "", right_value: Expression = None) -> None:
|
||||||
self.ident = ident
|
self.ident = ident
|
||||||
|
self.operator = operator
|
||||||
self.right_value = right_value
|
self.right_value = right_value
|
||||||
|
|
||||||
def type(self) -> NodeType:
|
def type(self) -> NodeType:
|
||||||
@@ -232,6 +234,7 @@ class ReassignStatement(Statement):
|
|||||||
return {
|
return {
|
||||||
"type": self.type().value,
|
"type": self.type().value,
|
||||||
"ident": self.ident.json(),
|
"ident": self.ident.json(),
|
||||||
|
"operator": self.operator,
|
||||||
"right_value": self.right_value.json()
|
"right_value": self.right_value.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,4 +345,19 @@ class CallExpression(Expression):
|
|||||||
"function": self.function.json(),
|
"function": self.function.json(),
|
||||||
"arguments": [arg.json() for arg in self.arguments]
|
"arguments": [arg.json() for arg in self.arguments]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PrefixExpression(Expression):
|
||||||
|
def __init__(self, operator: str, right_node: Expression = None) -> None:
|
||||||
|
self.operator = operator
|
||||||
|
self.right_node = right_node
|
||||||
|
|
||||||
|
def type(self) -> NodeType:
|
||||||
|
return NodeType.PrefixExpression
|
||||||
|
|
||||||
|
def json(self) -> dict:
|
||||||
|
return {
|
||||||
|
"type": self.type().value,
|
||||||
|
"operator": self.operator,
|
||||||
|
"right_node": self.right_node.json()
|
||||||
|
}
|
||||||
# endregion
|
# endregion
|
||||||
68
README.md
68
README.md
@@ -1,3 +1,71 @@
|
|||||||
# Plasma
|
# Plasma
|
||||||
|
|
||||||
The Plasma programming language.
|
The Plasma programming language.
|
||||||
|
|
||||||
|
# Syntax Guide
|
||||||
|
## Functions
|
||||||
|
All your logic must be contained in the "main" function, which looks like this:
|
||||||
|
```cpp
|
||||||
|
main = Func(): Int {
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This is how you define functions. In this example, "main" is the name of the function, and `Int` is the return type. My function takes no arguments.
|
||||||
|
If I wanted to make a function that takes arguments, it might look like this:
|
||||||
|
```cpp
|
||||||
|
add = Func(number1: Int, number2: Int): Int {
|
||||||
|
return number1 + number2
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This is a function that adds two numbers together, here's the same function in Python:
|
||||||
|
```py
|
||||||
|
def add(number1: int, number2: int) -> int:
|
||||||
|
return number1 + number2
|
||||||
|
```
|
||||||
|
|
||||||
|
### Calling Functions
|
||||||
|
To call a function, you type a dollar sign (the $ symbol), then the name of the function, and then you pass any of your arguments inbetween paranthesis, like this:
|
||||||
|
```cpp
|
||||||
|
add = Func(number1: Int, number2: Int): Int {
|
||||||
|
return number1 + number2
|
||||||
|
}
|
||||||
|
...
|
||||||
|
later in my code...
|
||||||
|
...
|
||||||
|
$add(9, 10);
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's a "Hello, World!" program in Plasma:
|
||||||
|
```cpp
|
||||||
|
main = Func(): Int {
|
||||||
|
$print("Hello, World!\n");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
`print` is a builtin function, it's defined in every piece of code you write. It has the same formatting as the `printf` function in C, so if I wanted to print an integer I could do it like so:
|
||||||
|
```cpp
|
||||||
|
$print("%i\n", 123);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
To create a variable, it's as simple as:
|
||||||
|
```cpp
|
||||||
|
name: Type = value;
|
||||||
|
```
|
||||||
|
|
||||||
|
There are several types in Plasma, which are: `Int`, `Float`, `Bool`, `String`
|
||||||
|
|
||||||
|
Here's another example:
|
||||||
|
```cpp
|
||||||
|
name: String = "bob";
|
||||||
|
age: Int = 23;
|
||||||
|
```
|
||||||
|
|
||||||
|
To change the value of an already defined variable, you just have to provide the name, and then write an equals sign, like this:
|
||||||
|
```cpp
|
||||||
|
-- defining the variable
|
||||||
|
age: Int = 23;
|
||||||
|
|
||||||
|
-- changing it later
|
||||||
|
age = age + 1;
|
||||||
|
```
|
||||||
79
compiler.py
79
compiler.py
@@ -3,7 +3,7 @@ from llvmlite import ir
|
|||||||
from AST import Node, NodeType, Program, Expression
|
from AST import Node, NodeType, Program, Expression
|
||||||
from AST import ExpressionStatement, AssignmentStatement, BlockStatement, ReturnStatement, FunctionStatement, ReassignStatement, IfStatement
|
from AST import ExpressionStatement, AssignmentStatement, BlockStatement, ReturnStatement, FunctionStatement, ReassignStatement, IfStatement
|
||||||
from AST import WhileStatement, BreakStatement, ContinueStatement, ForStatement
|
from AST import WhileStatement, BreakStatement, ContinueStatement, ForStatement
|
||||||
from AST import InfixExpression, CallExpression
|
from AST import InfixExpression, CallExpression, PrefixExpression
|
||||||
from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral, StringLiteral
|
from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral, StringLiteral
|
||||||
from AST import FunctionParameter
|
from AST import FunctionParameter
|
||||||
|
|
||||||
@@ -189,15 +189,56 @@ class Compiler:
|
|||||||
|
|
||||||
def __visit_reassign_statement(self, node: ReassignStatement) -> None:
|
def __visit_reassign_statement(self, node: ReassignStatement) -> None:
|
||||||
name: str = node.ident.value
|
name: str = node.ident.value
|
||||||
|
operator: str = node.operator
|
||||||
value: Expression = node.right_value
|
value: Expression = node.right_value
|
||||||
|
|
||||||
value, Type = self.__resolve_value(value)
|
|
||||||
|
|
||||||
if self.environment.lookup(name) is None:
|
if self.environment.lookup(name) is None:
|
||||||
self.errors.append(f"Identifier {name} has not been declared before it was re-assigned.")
|
self.errors.append(f"Identifier {name} has not been declared before it was re-assigned.")
|
||||||
else:
|
return
|
||||||
ptr, _ = self.environment.lookup(name)
|
|
||||||
self.builder.store(value, ptr)
|
right_value, right_type = self.__resolve_value(value)
|
||||||
|
|
||||||
|
var_ptr, _ = self.environment.lookup(name)
|
||||||
|
orig_value = self.builder.load(var_ptr)
|
||||||
|
|
||||||
|
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.FloatType):
|
||||||
|
orig_value = self.builder.sitofp(orig_value, ir.FloatType())
|
||||||
|
|
||||||
|
if isinstance(orig_value.type, ir.FloatType) and isinstance(right_type, ir.IntType):
|
||||||
|
right_value = self.builder.sitofp(right_value, ir.FloatType())
|
||||||
|
|
||||||
|
value = None
|
||||||
|
Type = None
|
||||||
|
match operator:
|
||||||
|
case "=":
|
||||||
|
value = right_value
|
||||||
|
case "+=":
|
||||||
|
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.IntType):
|
||||||
|
value = self.builder.add(orig_value, right_value)
|
||||||
|
else:
|
||||||
|
value = self.builder.fadd(orig_value, right_value)
|
||||||
|
case "-=":
|
||||||
|
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.IntType):
|
||||||
|
value = self.builder.sub(orig_value, right_value)
|
||||||
|
else:
|
||||||
|
value = self.builder.fsub(orig_value, right_value)
|
||||||
|
case "*=":
|
||||||
|
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.IntType):
|
||||||
|
value = self.builder.mul(orig_value, right_value)
|
||||||
|
else:
|
||||||
|
value = self.builder.fmul(orig_value, right_value)
|
||||||
|
case "/=":
|
||||||
|
if isinstance(orig_value.type, ir.IntType) and isinstance(right_type, ir.IntType):
|
||||||
|
value = self.builder.sdiv(orig_value, right_value)
|
||||||
|
else:
|
||||||
|
value = self.builder.fdiv(orig_value, right_value)
|
||||||
|
case _:
|
||||||
|
print("Unsupported assignment operator.")
|
||||||
|
|
||||||
|
ptr, _ = self.environment.lookup(name)
|
||||||
|
self.builder.store(value, ptr)
|
||||||
|
|
||||||
def __visit_if_statement(self, node: IfStatement) -> None:
|
def __visit_if_statement(self, node: IfStatement) -> None:
|
||||||
condition = node.condition
|
condition = node.condition
|
||||||
@@ -388,6 +429,32 @@ class Compiler:
|
|||||||
ret = self.builder.call(func, args)
|
ret = self.builder.call(func, args)
|
||||||
|
|
||||||
return ret, ret_type
|
return ret, ret_type
|
||||||
|
|
||||||
|
def __visit_prefix_expression(self, node: PrefixExpression) -> tuple[ir.Value, ir.Type]:
|
||||||
|
operator: str = node.operator
|
||||||
|
right_node: Expression = node.right_node
|
||||||
|
|
||||||
|
right_value, right_type = self.__resolve_value(right_node)
|
||||||
|
|
||||||
|
Type = None
|
||||||
|
value = None
|
||||||
|
|
||||||
|
if isinstance(right_type, ir.FloatType):
|
||||||
|
Type = ir.FloatType
|
||||||
|
match operator:
|
||||||
|
case "-":
|
||||||
|
value = self.builder.fmul(right_value, ir.Constant(ir.FloatType(), -1.0))
|
||||||
|
case "!":
|
||||||
|
value = ir.Constant(ir.IntType(1), 0)
|
||||||
|
elif isinstance(right_type, ir.IntType):
|
||||||
|
Type = ir.IntType(32)
|
||||||
|
match operator:
|
||||||
|
case "-":
|
||||||
|
value = self.builder.mul(right_value, ir.Constant(ir.IntType(32), -1))
|
||||||
|
case "!":
|
||||||
|
value = self.builder.not_(right_value)
|
||||||
|
|
||||||
|
return value, Type
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
@@ -420,6 +487,8 @@ class Compiler:
|
|||||||
return self.__visit_infix_expression(node)
|
return self.__visit_infix_expression(node)
|
||||||
case NodeType.CallExpression:
|
case NodeType.CallExpression:
|
||||||
return self.__visit_call_expression(node)
|
return self.__visit_call_expression(node)
|
||||||
|
case NodeType.PrefixExpression:
|
||||||
|
return self.__visit_prefix_expression(node)
|
||||||
|
|
||||||
def __convert_string(self, string: str) -> tuple[ir.Constant, ir.ArrayType]:
|
def __convert_string(self, string: str) -> tuple[ir.Constant, ir.ArrayType]:
|
||||||
string = string.replace("\\n", "\n\0")
|
string = string.replace("\\n", "\n\0")
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
{
|
|
||||||
"type": "Program",
|
|
||||||
"statements": [
|
|
||||||
{
|
|
||||||
"FunctionStatement": {
|
|
||||||
"type": "FunctionStatement",
|
|
||||||
"name": {
|
|
||||||
"type": "IdentifierLiteral",
|
|
||||||
"value": "main"
|
|
||||||
},
|
|
||||||
"return_type": "Int",
|
|
||||||
"parameters": [],
|
|
||||||
"body": {
|
|
||||||
"type": "BlockStatement",
|
|
||||||
"statements": [
|
|
||||||
{
|
|
||||||
"type": "ForStatement",
|
|
||||||
"var_declaration": {
|
|
||||||
"type": "AssignmentStatement",
|
|
||||||
"name": {
|
|
||||||
"type": "IdentifierLiteral",
|
|
||||||
"value": "x"
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "IntegerLiteral",
|
|
||||||
"value": 1
|
|
||||||
},
|
|
||||||
"value_type": "Int"
|
|
||||||
},
|
|
||||||
"condition": {
|
|
||||||
"type": "InfixExpression",
|
|
||||||
"left_node": {
|
|
||||||
"type": "IdentifierLiteral",
|
|
||||||
"value": "x"
|
|
||||||
},
|
|
||||||
"operator": "<=",
|
|
||||||
"right_node": {
|
|
||||||
"type": "IntegerLiteral",
|
|
||||||
"value": 20
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"body": {
|
|
||||||
"type": "BlockStatement",
|
|
||||||
"statements": [
|
|
||||||
{
|
|
||||||
"type": "ExpressionStatement",
|
|
||||||
"expr": {
|
|
||||||
"type": "CallExpression",
|
|
||||||
"function": {
|
|
||||||
"type": "IdentifierLiteral",
|
|
||||||
"value": "print"
|
|
||||||
},
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"type": "StringLiteral",
|
|
||||||
"value": "i = %i\\n"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "IdentifierLiteral",
|
|
||||||
"value": "x"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ReturnStatement",
|
|
||||||
"return_value": {
|
|
||||||
"type": "IdentifierLiteral",
|
|
||||||
"value": "x"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
34
debug/ir.ll
34
debug/ir.ll
@@ -1,34 +0,0 @@
|
|||||||
; ModuleID = "main"
|
|
||||||
target triple = "x86_64-pc-windows-msvc"
|
|
||||||
target datalayout = ""
|
|
||||||
|
|
||||||
declare i32 @"printf"(i8* %".1", ...)
|
|
||||||
|
|
||||||
@"true" = constant i1 1
|
|
||||||
@"false" = constant i1 0
|
|
||||||
define i32 @"main"()
|
|
||||||
{
|
|
||||||
main_entry:
|
|
||||||
%".2" = alloca i32
|
|
||||||
store i32 0, i32* %".2"
|
|
||||||
%".4" = load i32, i32* %".2"
|
|
||||||
%".5" = icmp slt i32 %".4", 10
|
|
||||||
br i1 %".5", label %"while_loop_entry_1", label %"while_loop_otherwise_1"
|
|
||||||
while_loop_entry_1:
|
|
||||||
%".7" = load i32, i32* %".2"
|
|
||||||
%".8" = alloca [9 x i8]*
|
|
||||||
store [9 x i8]* @"__str_2", [9 x i8]** %".8"
|
|
||||||
%".10" = bitcast [9 x i8]* @"__str_2" to i8*
|
|
||||||
%".11" = call i32 (i8*, ...) @"printf"(i8* %".10", i32 %".7")
|
|
||||||
%".12" = load i32, i32* %".2"
|
|
||||||
%".13" = add i32 %".12", 1
|
|
||||||
store i32 %".13", i32* %".2"
|
|
||||||
%".15" = load i32, i32* %".2"
|
|
||||||
%".16" = icmp slt i32 %".15", 10
|
|
||||||
br i1 %".16", label %"while_loop_entry_1", label %"while_loop_otherwise_1"
|
|
||||||
while_loop_otherwise_1:
|
|
||||||
%".18" = load i32, i32* %".2"
|
|
||||||
ret i32 %".18"
|
|
||||||
}
|
|
||||||
|
|
||||||
@"__str_2" = internal constant [9 x i8] c"a = %i\0a\00\00"
|
|
||||||
31
lexer.py
31
lexer.py
@@ -84,13 +84,33 @@ class Lexer:
|
|||||||
|
|
||||||
match self.current_char:
|
match self.current_char:
|
||||||
case "+":
|
case "+":
|
||||||
tok = self.__new_token(TokenType.PLUS, self.current_char)
|
if self.__peek_char() == "=":
|
||||||
|
ch = self.current_char
|
||||||
|
self.__read_char()
|
||||||
|
tok = self.__new_token(TokenType.PLUS_EQ, ch + self.current_char)
|
||||||
|
else:
|
||||||
|
tok = self.__new_token(TokenType.PLUS, self.current_char)
|
||||||
case "-":
|
case "-":
|
||||||
tok = self.__new_token(TokenType.MINUS, self.current_char)
|
if self.__peek_char() == "=":
|
||||||
|
ch = self.current_char
|
||||||
|
self.__read_char()
|
||||||
|
tok = self.__new_token(TokenType.MINUS_EQ, ch + self.current_char)
|
||||||
|
else:
|
||||||
|
tok = self.__new_token(TokenType.MINUS, self.current_char)
|
||||||
case "*":
|
case "*":
|
||||||
tok = self.__new_token(TokenType.ASTERISK, self.current_char)
|
if self.__peek_char() == "=":
|
||||||
|
ch = self.current_char
|
||||||
|
self.__read_char()
|
||||||
|
tok = self.__new_token(TokenType.MUL_EQ, ch + self.current_char)
|
||||||
|
else:
|
||||||
|
tok = self.__new_token(TokenType.ASTERISK, self.current_char)
|
||||||
case "/":
|
case "/":
|
||||||
tok = self.__new_token(TokenType.SLASH, self.current_char)
|
if self.__peek_char() == "=":
|
||||||
|
ch = self.current_char
|
||||||
|
self.__read_char()
|
||||||
|
tok = self.__new_token(TokenType.DIV_EQ, ch + self.current_char)
|
||||||
|
else:
|
||||||
|
tok = self.__new_token(TokenType.SLASH, self.current_char)
|
||||||
case "^":
|
case "^":
|
||||||
tok = self.__new_token(TokenType.POW, self.current_char)
|
tok = self.__new_token(TokenType.POW, self.current_char)
|
||||||
case "%":
|
case "%":
|
||||||
@@ -126,8 +146,7 @@ class Lexer:
|
|||||||
self.__read_char()
|
self.__read_char()
|
||||||
tok = self.__new_token(TokenType.NOT_EQ, ch + self.current_char)
|
tok = self.__new_token(TokenType.NOT_EQ, ch + self.current_char)
|
||||||
else:
|
else:
|
||||||
# TODO: handle BANG
|
tok = self.__new_token(TokenType.BANG, self.current_char)
|
||||||
tok = self.__new_token(TokenType.ILLEGAL, self.current_char)
|
|
||||||
case "(":
|
case "(":
|
||||||
tok = self.__new_token(TokenType.LPAREN, self.current_char)
|
tok = self.__new_token(TokenType.LPAREN, self.current_char)
|
||||||
case ")":
|
case ")":
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ class TokenType(Enum):
|
|||||||
|
|
||||||
# Assignment symbols
|
# Assignment symbols
|
||||||
EQ = "EQ"
|
EQ = "EQ"
|
||||||
|
PLUS_EQ = "PLUS_EQ"
|
||||||
|
MINUS_EQ = "MINUS_EQ"
|
||||||
|
MUL_EQ = "MUL_EQ"
|
||||||
|
DIV_EQ = "DIV_EQ"
|
||||||
|
|
||||||
# Comparison symbols
|
# Comparison symbols
|
||||||
LT = "<"
|
LT = "<"
|
||||||
@@ -43,6 +47,7 @@ class TokenType(Enum):
|
|||||||
SEMICOLON = "SEMICOLON"
|
SEMICOLON = "SEMICOLON"
|
||||||
COMMA = "COMMA"
|
COMMA = "COMMA"
|
||||||
DOLLARSIGN = "DOLLARSIGN"
|
DOLLARSIGN = "DOLLARSIGN"
|
||||||
|
BANG = "BANG"
|
||||||
|
|
||||||
# Keywords
|
# Keywords
|
||||||
RETURN = "RETURN"
|
RETURN = "RETURN"
|
||||||
|
|||||||
2
main.py
2
main.py
@@ -10,7 +10,7 @@ import llvmlite.binding as llvm
|
|||||||
from ctypes import CFUNCTYPE, c_int, c_float
|
from ctypes import CFUNCTYPE, c_int, c_float
|
||||||
|
|
||||||
LEXER_DEBUG: bool = False
|
LEXER_DEBUG: bool = False
|
||||||
PARSER_DEBUG: bool = False
|
PARSER_DEBUG: bool = True
|
||||||
COMPILER_DEBUG: bool = False
|
COMPILER_DEBUG: bool = False
|
||||||
RUN_CODE: bool = True
|
RUN_CODE: bool = True
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ from enum import Enum, auto
|
|||||||
|
|
||||||
from AST import Statement, Expression, Program
|
from AST import Statement, Expression, Program
|
||||||
from AST import ExpressionStatement, AssignmentStatement, FunctionStatement, ReturnStatement, BlockStatement, ReassignStatement, IfStatement, WhileStatement
|
from AST import ExpressionStatement, AssignmentStatement, FunctionStatement, ReturnStatement, BlockStatement, ReassignStatement, IfStatement, WhileStatement
|
||||||
from AST import InfixExpression, CallExpression, BreakStatement, ContinueStatement, ForStatement
|
from AST import InfixExpression, CallExpression, PrefixExpression
|
||||||
|
from AST import BreakStatement, ContinueStatement, ForStatement
|
||||||
from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral, StringLiteral
|
from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral, BooleanLiteral, StringLiteral
|
||||||
from AST import FunctionParameter
|
from AST import FunctionParameter
|
||||||
|
|
||||||
@@ -57,7 +58,10 @@ class Parser:
|
|||||||
|
|
||||||
TokenType.STRING: self.__parse_string_literal,
|
TokenType.STRING: self.__parse_string_literal,
|
||||||
|
|
||||||
TokenType.DOLLARSIGN: self.__parse_call_expression
|
TokenType.DOLLARSIGN: self.__parse_call_expression,
|
||||||
|
|
||||||
|
TokenType.MINUS: self.__parse_prefix_expression,
|
||||||
|
TokenType.BANG: self.__parse_prefix_expression,
|
||||||
}
|
}
|
||||||
self.infix_parse_functions: dict[Token, Callable] = { # 5 + 5
|
self.infix_parse_functions: dict[Token, Callable] = { # 5 + 5
|
||||||
TokenType.PLUS: self.__parse_infix_expression,
|
TokenType.PLUS: self.__parse_infix_expression,
|
||||||
@@ -89,6 +93,16 @@ class Parser:
|
|||||||
def __peek_token_is(self, tt: TokenType) -> bool:
|
def __peek_token_is(self, tt: TokenType) -> bool:
|
||||||
return self.peek_token.type == tt
|
return self.peek_token.type == tt
|
||||||
|
|
||||||
|
def __peek_token_is_assignment(self) -> bool:
|
||||||
|
assignment_operators: list[TokenType] = [
|
||||||
|
TokenType.EQ,
|
||||||
|
TokenType.PLUS_EQ,
|
||||||
|
TokenType.MINUS_EQ,
|
||||||
|
TokenType.MUL_EQ,
|
||||||
|
TokenType.DIV_EQ,
|
||||||
|
]
|
||||||
|
return self.peek_token.type in assignment_operators
|
||||||
|
|
||||||
def __expect_peek(self, tt: TokenType) -> bool:
|
def __expect_peek(self, tt: TokenType) -> bool:
|
||||||
if self.__peek_token_is(tt):
|
if self.__peek_token_is(tt):
|
||||||
self.__next_token()
|
self.__next_token()
|
||||||
@@ -161,12 +175,13 @@ class Parser:
|
|||||||
# x: Int = 10;
|
# x: Int = 10;
|
||||||
stmt: AssignmentStatement = AssignmentStatement(name=IdentifierLiteral(self.current_token.literal))
|
stmt: AssignmentStatement = AssignmentStatement(name=IdentifierLiteral(self.current_token.literal))
|
||||||
|
|
||||||
if self.__peek_token_is(TokenType.EQ): # function definition
|
if self.__peek_token_is_assignment(): # function definition
|
||||||
# x = Func(): Int { return 10; }
|
# x = Func(): Int { return 10; }
|
||||||
|
|
||||||
|
|
||||||
self.__next_token()
|
self.__next_token()
|
||||||
|
|
||||||
if self.__peek_token_is(TokenType.TYPE):
|
if self.__current_token_is(TokenType.EQ) and self.__peek_token_is(TokenType.TYPE):
|
||||||
func_stmt: FunctionStatement = FunctionStatement(name=stmt.name)
|
func_stmt: FunctionStatement = FunctionStatement(name=stmt.name)
|
||||||
|
|
||||||
if self.peek_token.literal != "Func":
|
if self.peek_token.literal != "Func":
|
||||||
@@ -197,9 +212,12 @@ class Parser:
|
|||||||
else: # reassignment statement
|
else: # reassignment statement
|
||||||
assign_stmt: ReassignStatement = ReassignStatement()
|
assign_stmt: ReassignStatement = ReassignStatement()
|
||||||
|
|
||||||
|
|
||||||
|
assign_stmt.operator = self.current_token.literal
|
||||||
|
assign_stmt.ident = stmt.name
|
||||||
|
|
||||||
self.__next_token()
|
self.__next_token()
|
||||||
|
|
||||||
assign_stmt.ident = stmt.name
|
|
||||||
assign_stmt.right_value = self.__parse_expression(PrecedenceType.P_LOWEST)
|
assign_stmt.right_value = self.__parse_expression(PrecedenceType.P_LOWEST)
|
||||||
|
|
||||||
|
|
||||||
@@ -430,6 +448,15 @@ class Parser:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
return e_list
|
return e_list
|
||||||
|
|
||||||
|
def __parse_prefix_expression(self) -> PrefixExpression:
|
||||||
|
prefix_expr: PrefixExpression = PrefixExpression(operator=self.current_token.literal)
|
||||||
|
|
||||||
|
self.__next_token()
|
||||||
|
|
||||||
|
prefix_expr.right_node = self.__parse_expression(PrecedenceType.P_PREFIX)
|
||||||
|
|
||||||
|
return prefix_expr
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Prefix Methods
|
# region Prefix Methods
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
main = Func(): Int {
|
main = Func(): Int {
|
||||||
for (x: Int = 1; x <= 20; x = x + 1;) {
|
a: Int = 10;
|
||||||
$print("i = %i\n", x)
|
|
||||||
}
|
|
||||||
|
|
||||||
return x;
|
a += 1;
|
||||||
|
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user