VARIABLESSSS
This commit is contained in:
32
AST.py
32
AST.py
@@ -7,6 +7,7 @@ class NodeType(Enum):
|
|||||||
|
|
||||||
# Statements
|
# Statements
|
||||||
ExpressionStatement = "ExpressionStatement"
|
ExpressionStatement = "ExpressionStatement"
|
||||||
|
AssignmentStatement = "AssignmentStatement"
|
||||||
|
|
||||||
# Expressions
|
# Expressions
|
||||||
InfixExpression = "InfixExpression"
|
InfixExpression = "InfixExpression"
|
||||||
@@ -14,6 +15,7 @@ class NodeType(Enum):
|
|||||||
# Literals
|
# Literals
|
||||||
IntegerLiteral = "IntegerLiteral"
|
IntegerLiteral = "IntegerLiteral"
|
||||||
FloatLiteral = "FloatLiteral"
|
FloatLiteral = "FloatLiteral"
|
||||||
|
IdentifierLiteral = "IdentifierLiteral"
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@@ -56,6 +58,23 @@ class ExpressionStatement(Statement):
|
|||||||
"type": self.type().value,
|
"type": self.type().value,
|
||||||
"expr": self.expr.json()
|
"expr": self.expr.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AssignmentStatement(Statement):
|
||||||
|
def __init__(self, name: Expression = None, value: Expression = None, value_type: str = None) -> None:
|
||||||
|
self.name = name
|
||||||
|
self.value = value
|
||||||
|
self.value_type = value_type
|
||||||
|
|
||||||
|
def type(self) -> NodeType:
|
||||||
|
return NodeType.AssignmentStatement
|
||||||
|
|
||||||
|
def json(self) -> dict:
|
||||||
|
return {
|
||||||
|
"type": self.type().value,
|
||||||
|
"name": self.name.json(),
|
||||||
|
"value": self.value.json(),
|
||||||
|
"value_type": self.value_type
|
||||||
|
}
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Expressions
|
# region Expressions
|
||||||
@@ -103,4 +122,17 @@ class FloatLiteral(Expression):
|
|||||||
"type": self.type().value,
|
"type": self.type().value,
|
||||||
"value": self.value
|
"value": self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class IdentifierLiteral(Expression):
|
||||||
|
def __init__(self, value: str = None) -> None:
|
||||||
|
self.value: str = value
|
||||||
|
|
||||||
|
def type(self) -> NodeType:
|
||||||
|
return NodeType.IdentifierLiteral
|
||||||
|
|
||||||
|
def json(self) -> dict:
|
||||||
|
return {
|
||||||
|
"type": self.type().value,
|
||||||
|
"value": self.value
|
||||||
|
}
|
||||||
# endregion
|
# endregion
|
||||||
152
compiler.py
Normal file
152
compiler.py
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
from llvmlite import ir
|
||||||
|
|
||||||
|
from AST import Node, NodeType, Program, Expression
|
||||||
|
from AST import ExpressionStatement, AssignmentStatement
|
||||||
|
from AST import InfixExpression
|
||||||
|
from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral
|
||||||
|
|
||||||
|
from environment import Environment
|
||||||
|
|
||||||
|
|
||||||
|
class Compiler:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.type_map: dict[str, ir.type] = {
|
||||||
|
"bool": ir.IntType(1),
|
||||||
|
"byte": ir.IntType(8),
|
||||||
|
"short": ir.IntType(16),
|
||||||
|
"int": ir.IntType(32),
|
||||||
|
"long": ir.IntType(64),
|
||||||
|
"float": ir.FloatType(),
|
||||||
|
"double": ir.DoubleType()
|
||||||
|
}
|
||||||
|
|
||||||
|
self.module: ir.Module = ir.Module("main")
|
||||||
|
self.builder: ir.IRBuilder = ir.IRBuilder()
|
||||||
|
self.environment: Environment = Environment()
|
||||||
|
|
||||||
|
def compile(self, node: Node) -> None:
|
||||||
|
match node.type():
|
||||||
|
case NodeType.Program:
|
||||||
|
self.__visit_program(node)
|
||||||
|
|
||||||
|
# Statements
|
||||||
|
case NodeType.ExpressionStatement:
|
||||||
|
self.__visit_expression_statement(node)
|
||||||
|
case NodeType.AssignmentStatement:
|
||||||
|
self.__visit_assignment_statement(node)
|
||||||
|
|
||||||
|
# Expressions
|
||||||
|
case NodeType.InfixExpression:
|
||||||
|
self.__visit_infix_expression(node)
|
||||||
|
|
||||||
|
# region Visit Methods
|
||||||
|
def __visit_program(self, node: Program) -> None:
|
||||||
|
func_main: str = "main"
|
||||||
|
param_types: list[ir.Type] = []
|
||||||
|
return_type = ir.Type = self.type_map["int"]
|
||||||
|
|
||||||
|
fnty = ir.FunctionType(return_type, param_types)
|
||||||
|
func = ir.Function(self.module, fnty, func_main)
|
||||||
|
|
||||||
|
block = func.append_basic_block(f"{func_main}_entry")
|
||||||
|
|
||||||
|
self.builder = ir.IRBuilder(block)
|
||||||
|
|
||||||
|
for stmt in node.statements:
|
||||||
|
self.compile(stmt)
|
||||||
|
|
||||||
|
return_value: ir.Constant = ir.Constant(self.type_map["int"], 123)
|
||||||
|
self.builder.ret(return_value)
|
||||||
|
|
||||||
|
# region Statements
|
||||||
|
def __visit_expression_statement(self, node: ExpressionStatement) -> None:
|
||||||
|
self.compile(node.expr)
|
||||||
|
|
||||||
|
def __visit_assignment_statement(self, node: AssignmentStatement) -> None:
|
||||||
|
name: str = node.name.value
|
||||||
|
value: Expression = node.value
|
||||||
|
value_type: str = node.value_type # TODO: implemented
|
||||||
|
|
||||||
|
value, Type = self.__resolve_value(node=value)
|
||||||
|
|
||||||
|
if self.environment.lookup(name) is None:
|
||||||
|
# Define and allocate the new variable
|
||||||
|
ptr = self.builder.alloca(Type)
|
||||||
|
|
||||||
|
# Storing the value to the ptr
|
||||||
|
self.builder.store(value, ptr)
|
||||||
|
|
||||||
|
# Add the variable to the environment
|
||||||
|
self.environment.define(name, value, Type)
|
||||||
|
else:
|
||||||
|
ptr, _ = self.environment.lookup(name)
|
||||||
|
self.builder.store(value, ptr)
|
||||||
|
# endregion
|
||||||
|
|
||||||
|
# region Expressions
|
||||||
|
def __visit_infix_expression(self, node: InfixExpression) -> None:
|
||||||
|
operator: str = node.operator
|
||||||
|
|
||||||
|
left_value, left_type = self.__resolve_value(node.left_node)
|
||||||
|
right_value, right_type = self.__resolve_value(node.right_node)
|
||||||
|
|
||||||
|
value = None
|
||||||
|
Type = None
|
||||||
|
if isinstance(right_type, ir.IntType) and isinstance(left_type, ir.IntType):
|
||||||
|
Type = self.type_map["int"]
|
||||||
|
match operator:
|
||||||
|
case "+":
|
||||||
|
value = self.builder.add(left_value, right_value)
|
||||||
|
case "-":
|
||||||
|
value = self.builder.sub(left_value, right_value)
|
||||||
|
case "*":
|
||||||
|
value = self.builder.mul(left_value, right_value)
|
||||||
|
case "/":
|
||||||
|
value = self.builder.sdiv(left_value, right_value)
|
||||||
|
case "%":
|
||||||
|
value = self.builder.srem(left_value, right_value)
|
||||||
|
case "^":
|
||||||
|
# TODO
|
||||||
|
pass
|
||||||
|
elif isinstance(right_type, ir.FloatType) and isinstance(left_type, ir.FloatType):
|
||||||
|
Type = self.type_map["float"]
|
||||||
|
match operator:
|
||||||
|
case "+":
|
||||||
|
value = self.builder.fadd(left_value, right_value)
|
||||||
|
case "-":
|
||||||
|
value = self.builder.fsub(left_value, right_value)
|
||||||
|
case "*":
|
||||||
|
value = self.builder.fmul(left_value, right_value)
|
||||||
|
case "/":
|
||||||
|
value = self.builder.fdiv(left_value, right_value)
|
||||||
|
case "%":
|
||||||
|
value = self.builder.frem(left_value, right_value)
|
||||||
|
case "^":
|
||||||
|
# TODO
|
||||||
|
pass
|
||||||
|
|
||||||
|
return value, Type
|
||||||
|
# endregion
|
||||||
|
|
||||||
|
# endregion
|
||||||
|
|
||||||
|
# region Helper Methods
|
||||||
|
def __resolve_value(self, node: Expression) -> tuple[ir.Value, ir.Type]:
|
||||||
|
match node.type():
|
||||||
|
case NodeType.IntegerLiteral:
|
||||||
|
node: IntegerLiteral = node
|
||||||
|
value, Type = node.value, self.type_map['int']
|
||||||
|
return ir.Constant(Type, value), Type
|
||||||
|
case NodeType.FloatLiteral:
|
||||||
|
node: FloatLiteral = node
|
||||||
|
value, Type = node.value, self.type_map['float']
|
||||||
|
return ir.Constant(Type, value), Type
|
||||||
|
case NodeType.IdentifierLiteral:
|
||||||
|
node: IdentifierLiteral = node
|
||||||
|
ptr, Type = self.environment.lookup(node.value)
|
||||||
|
return self.builder.load(ptr), Type
|
||||||
|
|
||||||
|
# expression value
|
||||||
|
case NodeType.InfixExpression:
|
||||||
|
return self.__visit_infix_expression(node)
|
||||||
|
# endregion
|
||||||
@@ -2,36 +2,17 @@
|
|||||||
"type": "Program",
|
"type": "Program",
|
||||||
"statements": [
|
"statements": [
|
||||||
{
|
{
|
||||||
"ExpressionStatement": {
|
"AssignmentStatement": {
|
||||||
"type": "ExpressionStatement",
|
"type": "AssignmentStatement",
|
||||||
"expr": {
|
"name": {
|
||||||
"type": "InfixExpression",
|
"type": "IdentifierLiteral",
|
||||||
"left_node": {
|
"value": "myVar"
|
||||||
"type": "InfixExpression",
|
},
|
||||||
"left_node": {
|
"value": {
|
||||||
"type": "InfixExpression",
|
"type": "IntegerLiteral",
|
||||||
"left_node": {
|
"value": 1
|
||||||
"type": "IntegerLiteral",
|
},
|
||||||
"value": 5
|
"value_type": "Bool"
|
||||||
},
|
|
||||||
"operator": "+",
|
|
||||||
"right_node": {
|
|
||||||
"type": "IntegerLiteral",
|
|
||||||
"value": 5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"operator": "*",
|
|
||||||
"right_node": {
|
|
||||||
"type": "IntegerLiteral",
|
|
||||||
"value": 3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"operator": "+",
|
|
||||||
"right_node": {
|
|
||||||
"type": "IntegerLiteral",
|
|
||||||
"value": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
13
debug/ir.ll
Normal file
13
debug/ir.ll
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
; ModuleID = "main"
|
||||||
|
target triple = "x86_64-pc-windows-msvc"
|
||||||
|
target datalayout = ""
|
||||||
|
|
||||||
|
define i32 @"main"()
|
||||||
|
{
|
||||||
|
main_entry:
|
||||||
|
%".2" = alloca float
|
||||||
|
store float 0x3ff3ae1480000000, float* %".2"
|
||||||
|
%".4" = alloca i32
|
||||||
|
store i32 456, i32* %".4"
|
||||||
|
ret i32 123
|
||||||
|
}
|
||||||
23
environment.py
Normal file
23
environment.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from llvmlite import ir
|
||||||
|
|
||||||
|
|
||||||
|
class Environment:
|
||||||
|
def __init__(self, records: dict[str, tuple[ir.Value, ir.Type]] = None, parent = None, name: str = "global") -> None:
|
||||||
|
self.records: dict[str, tuple[ir.Value, ir.Type]] = records if records else {}
|
||||||
|
self.parent = parent
|
||||||
|
self.name: str = name
|
||||||
|
|
||||||
|
def define(self, name: str, value: ir.Value, _type: ir.Type) -> ir.Value:
|
||||||
|
self.records[name] = (value, _type)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def lookup(self, name: str) -> tuple[ir.Value, ir.Type]:
|
||||||
|
return self.__resolve(name)
|
||||||
|
|
||||||
|
def __resolve(self, name: str) -> tuple[ir.Value, ir.Type]:
|
||||||
|
if name in self.records:
|
||||||
|
return self.records[name]
|
||||||
|
elif self.parent:
|
||||||
|
return self.parent.__resolve(name)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
20
lexer.py
20
lexer.py
@@ -1,4 +1,4 @@
|
|||||||
from lexer_token import Token, TokenType
|
from lexer_token import Token, TokenType, lookup_ident
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
@@ -36,6 +36,9 @@ class Lexer:
|
|||||||
def __is_digit(self, char: str) -> bool:
|
def __is_digit(self, char: str) -> bool:
|
||||||
return "0" <= char and char <= "9"
|
return "0" <= char and char <= "9"
|
||||||
|
|
||||||
|
def __is_letter(self, char: str) -> bool:
|
||||||
|
return "a" <= char and char <= "z" or "A" <= char and char <= "Z" or char == "_"
|
||||||
|
|
||||||
def __read_number(self) -> Token:
|
def __read_number(self) -> Token:
|
||||||
start_pos: int = self.position
|
start_pos: int = self.position
|
||||||
dot_count: int = 0
|
dot_count: int = 0
|
||||||
@@ -61,6 +64,13 @@ class Lexer:
|
|||||||
else:
|
else:
|
||||||
return self.__new_token(TokenType.FLOAT, float(output))
|
return self.__new_token(TokenType.FLOAT, float(output))
|
||||||
|
|
||||||
|
def __read_identifier(self) -> str:
|
||||||
|
position = self.position
|
||||||
|
while self.current_char is not None and (self.__is_letter(self.current_char) or self.current_char.isalnum()):
|
||||||
|
self.__read_char()
|
||||||
|
|
||||||
|
return self.source[position:self.position]
|
||||||
|
|
||||||
def next_token(self) -> Token:
|
def next_token(self) -> Token:
|
||||||
tok: Token = None
|
tok: Token = None
|
||||||
|
|
||||||
@@ -79,6 +89,8 @@ class Lexer:
|
|||||||
tok = self.__new_token(TokenType.POW, self.current_char)
|
tok = self.__new_token(TokenType.POW, self.current_char)
|
||||||
case "%":
|
case "%":
|
||||||
tok = self.__new_token(TokenType.MODULUS, self.current_char)
|
tok = self.__new_token(TokenType.MODULUS, self.current_char)
|
||||||
|
case "=":
|
||||||
|
tok = self.__new_token(TokenType.EQ, 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 ")":
|
||||||
@@ -98,6 +110,12 @@ class Lexer:
|
|||||||
case None:
|
case None:
|
||||||
tok = self.__new_token(TokenType.EOF, "")
|
tok = self.__new_token(TokenType.EOF, "")
|
||||||
case _:
|
case _:
|
||||||
|
if self.__is_letter(self.current_char):
|
||||||
|
literal: str = self.__read_identifier()
|
||||||
|
tt: TokenType = lookup_ident(literal)
|
||||||
|
tok = self.__new_token(tt, literal)
|
||||||
|
return tok
|
||||||
|
|
||||||
if self.__is_digit(self.current_char):
|
if self.__is_digit(self.current_char):
|
||||||
tok = self.__read_number()
|
tok = self.__read_number()
|
||||||
return tok
|
return tok
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class TokenType(Enum):
|
|||||||
ILLEGAL = "ILLEGAL"
|
ILLEGAL = "ILLEGAL"
|
||||||
|
|
||||||
# Data types
|
# Data types
|
||||||
|
IDENT = "IDENT"
|
||||||
INT = "INT"
|
INT = "INT"
|
||||||
FLOAT = "FLOAT"
|
FLOAT = "FLOAT"
|
||||||
|
|
||||||
@@ -19,6 +20,9 @@ class TokenType(Enum):
|
|||||||
POW = "POW"
|
POW = "POW"
|
||||||
MODULUS = "MODULUS"
|
MODULUS = "MODULUS"
|
||||||
|
|
||||||
|
# Assignment symbols
|
||||||
|
EQ = "EQ"
|
||||||
|
|
||||||
# Symbols
|
# Symbols
|
||||||
LPAREN = "LPAREN"
|
LPAREN = "LPAREN"
|
||||||
RPAREN = "RPAREN"
|
RPAREN = "RPAREN"
|
||||||
@@ -29,6 +33,11 @@ class TokenType(Enum):
|
|||||||
COLON = "COLON"
|
COLON = "COLON"
|
||||||
SEMICOLON = "SEMICOLON"
|
SEMICOLON = "SEMICOLON"
|
||||||
|
|
||||||
|
# Keywords
|
||||||
|
|
||||||
|
# Typing
|
||||||
|
TYPE = "TYPE"
|
||||||
|
|
||||||
class Token:
|
class Token:
|
||||||
def __init__(self, type: TokenType, literal: Any, line_no: int, position: int) -> None:
|
def __init__(self, type: TokenType, literal: Any, line_no: int, position: int) -> None:
|
||||||
self.type = type
|
self.type = type
|
||||||
@@ -41,3 +50,28 @@ class Token:
|
|||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
|
KEYWORDS: dict[str, TokenType] = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ALT_KEYWORDS: dict[str, TokenType] = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE_KEYWORDS: list[str] = ["Int", "Float", "String", "Bool", "List", "Nil"]
|
||||||
|
|
||||||
|
def lookup_ident(ident: str) -> TokenType:
|
||||||
|
tt: TokenType | None = KEYWORDS.get(ident)
|
||||||
|
if tt is not None:
|
||||||
|
return tt
|
||||||
|
|
||||||
|
tt: TokenType | None = ALT_KEYWORDS.get(ident)
|
||||||
|
if tt is not None:
|
||||||
|
return tt
|
||||||
|
|
||||||
|
if ident in TYPE_KEYWORDS:
|
||||||
|
return TokenType.TYPE
|
||||||
|
|
||||||
|
return TokenType.IDENT
|
||||||
30
main.py
30
main.py
@@ -1,14 +1,20 @@
|
|||||||
from lexer import Lexer
|
from lexer import Lexer
|
||||||
from plasma_parser import Parser
|
from plasma_parser import Parser
|
||||||
|
from compiler import Compiler
|
||||||
from AST import Program
|
from AST import Program
|
||||||
import json
|
import json
|
||||||
|
|
||||||
LEXER_DEBUG: bool = True
|
from llvmlite import ir
|
||||||
PARSER_DEBUG: bool = True
|
from llvmlite.binding import targets
|
||||||
|
from ctypes import CFUNCTYPE, c_int, c_float
|
||||||
|
|
||||||
|
LEXER_DEBUG: bool = False
|
||||||
|
PARSER_DEBUG: bool = False
|
||||||
|
COMPILER_DEBUG: bool = True
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
with open("tests/parser.pla") as f:
|
with open("tests/test.pla") as f:
|
||||||
code: str = f.read()
|
code: str = f.read()
|
||||||
|
|
||||||
if LEXER_DEBUG:
|
if LEXER_DEBUG:
|
||||||
@@ -19,11 +25,27 @@ if __name__ == "__main__":
|
|||||||
l: Lexer = Lexer(source=code)
|
l: Lexer = Lexer(source=code)
|
||||||
p: Parser = Parser(lexer=l)
|
p: Parser = Parser(lexer=l)
|
||||||
|
|
||||||
|
program: Program = p.parse_program()
|
||||||
|
if len(p.errors) > 0:
|
||||||
|
for err in p.errors:
|
||||||
|
print(err)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
if PARSER_DEBUG:
|
if PARSER_DEBUG:
|
||||||
print("===== PARSER DEBUG =====")
|
print("===== PARSER DEBUG =====")
|
||||||
program: Program = p.parse_program()
|
#program: Program = p.parse_program()
|
||||||
|
|
||||||
with open("debug/ast.json", "w") as f:
|
with open("debug/ast.json", "w") as f:
|
||||||
json.dump(program.json(), f, indent=4)
|
json.dump(program.json(), f, indent=4)
|
||||||
|
|
||||||
print("Wrote AST to debug/ast.json successfully.")
|
print("Wrote AST to debug/ast.json successfully.")
|
||||||
|
|
||||||
|
c: Compiler = Compiler()
|
||||||
|
c.compile(program)
|
||||||
|
|
||||||
|
module: ir.Module = c.module
|
||||||
|
module.triple = targets.get_default_triple()
|
||||||
|
|
||||||
|
if COMPILER_DEBUG:
|
||||||
|
with open("debug/ir.ll", "w") as f:
|
||||||
|
f.write(str(module))
|
||||||
@@ -4,9 +4,9 @@ from typing import Callable
|
|||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
|
|
||||||
from AST import Statement, Expression, Program
|
from AST import Statement, Expression, Program
|
||||||
from AST import ExpressionStatement
|
from AST import ExpressionStatement, AssignmentStatement
|
||||||
from AST import InfixExpression
|
from AST import InfixExpression
|
||||||
from AST import IntegerLiteral, FloatLiteral
|
from AST import IntegerLiteral, FloatLiteral, IdentifierLiteral
|
||||||
|
|
||||||
class PrecedenceType(Enum):
|
class PrecedenceType(Enum):
|
||||||
P_LOWEST = 0
|
P_LOWEST = 0
|
||||||
@@ -63,6 +63,9 @@ class Parser:
|
|||||||
self.current_token = self.peek_token
|
self.current_token = self.peek_token
|
||||||
self.peek_token = self.lexer.next_token()
|
self.peek_token = self.lexer.next_token()
|
||||||
|
|
||||||
|
def __current_token_is(self, tt: TokenType) -> bool:
|
||||||
|
return self.current_token.type == tt
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -108,7 +111,11 @@ class Parser:
|
|||||||
|
|
||||||
# region Statement Methods
|
# region Statement Methods
|
||||||
def __parse_statement(self) -> Statement:
|
def __parse_statement(self) -> Statement:
|
||||||
return self.__parse_expression_statement()
|
match self.current_token.type:
|
||||||
|
case TokenType.IDENT:
|
||||||
|
return self.__parse_assignment_statement()
|
||||||
|
case _:
|
||||||
|
return self.__parse_expression_statement()
|
||||||
|
|
||||||
def __parse_expression_statement(self) -> ExpressionStatement:
|
def __parse_expression_statement(self) -> ExpressionStatement:
|
||||||
expr = self.__parse_expression(PrecedenceType.P_LOWEST)
|
expr = self.__parse_expression(PrecedenceType.P_LOWEST)
|
||||||
@@ -119,6 +126,30 @@ class Parser:
|
|||||||
stmt: ExpressionStatement = ExpressionStatement(expr=expr)
|
stmt: ExpressionStatement = ExpressionStatement(expr=expr)
|
||||||
|
|
||||||
return stmt
|
return stmt
|
||||||
|
|
||||||
|
def __parse_assignment_statement(self) -> AssignmentStatement:
|
||||||
|
# x: Int = 10;
|
||||||
|
stmt: AssignmentStatement = AssignmentStatement(name=IdentifierLiteral(self.current_token.literal))
|
||||||
|
|
||||||
|
if not self.__expect_peek(TokenType.COLON):
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not self.__expect_peek(TokenType.TYPE):
|
||||||
|
return None
|
||||||
|
|
||||||
|
stmt.value_type = self.current_token.literal
|
||||||
|
|
||||||
|
if not self.__expect_peek(TokenType.EQ):
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.__next_token()
|
||||||
|
|
||||||
|
stmt.value = self.__parse_expression(PrecedenceType.P_LOWEST)
|
||||||
|
|
||||||
|
while not self.__current_token_is(TokenType.SEMICOLON) and not self.__current_token_is(TokenType.EOF):
|
||||||
|
self.__next_token()
|
||||||
|
|
||||||
|
return stmt
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Expression Methods
|
# region Expression Methods
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
depend "io.pla"
|
depend "io.pla"
|
||||||
|
|
||||||
if (1 + 2 == 3) {
|
if (1 + 2 == 3) {
|
||||||
print("The universe is functional!")
|
print("The universe is functional!");
|
||||||
}
|
}
|
||||||
unless
|
unless
|
||||||
{
|
{
|
||||||
print("WHAT, HOW")
|
print("WHAT, HOW");
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ depend "io.pla"
|
|||||||
depend "string.pla"
|
depend "string.pla"
|
||||||
|
|
||||||
add = Func(a: Int, b: Int): Int {
|
add = Func(a: Int, b: Int): Int {
|
||||||
return a + b
|
return a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
print(String(add(1, 3)))
|
print(String(add(1, 3)));
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
depend "io.pla"
|
depend "io.pla"
|
||||||
print("Hello, World!")
|
print("Hello, World!");
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
123
|
|
||||||
0.456
|
|
||||||
[]
|
|
||||||
{}
|
|
||||||
(1 + 3 * 2 ^ 4) % 2
|
|
||||||
2 - 1
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
(5 + 5) * 3 + 2
|
|
||||||
2
tests/test.pla
Normal file
2
tests/test.pla
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
a: Float = 1.23;
|
||||||
|
b: Int = 456;
|
||||||
@@ -16,4 +16,4 @@ speak = Func(sentence: String): Nil {
|
|||||||
print(sentence)
|
print(sentence)
|
||||||
}
|
}
|
||||||
|
|
||||||
max: Person = {"Max", 17, }
|
max: Person = {"Max", 17, speak, Gender.male};
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
depend "string.pla"
|
depend "string.pla"
|
||||||
depend "io.h"
|
depend "io.h"
|
||||||
|
|
||||||
myInt: Int = 123
|
myInt: Int = 123;
|
||||||
myDecimal: Float = 0.456
|
myDecimal: Float = 0.456;
|
||||||
myBoolean: Bool = true
|
myBoolean: Bool = true;
|
||||||
myString: String = "Hello!\n"
|
myString: String = "Hello!\n";
|
||||||
myList: List = [1, "hi", true, [1, 2, 3], 0.789]
|
myList: List = [1, "hi", true, [1, 2, 3], 0.789];
|
||||||
|
|
||||||
MY_CONSTANT: Const(String) = "foo bar"
|
MY_CONSTANT: Const(String) = "foo bar";
|
||||||
|
|
||||||
print(String(myInt))
|
print(String(myInt));
|
||||||
print(String(myDecimal))
|
print(String(myDecimal));
|
||||||
print(String(myBoolean))
|
print(String(myBoolean));
|
||||||
print(myString)
|
print(myString);
|
||||||
print(String(myList))
|
print(String(myList));
|
||||||
Reference in New Issue
Block a user