parser.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. import src.zelkelc.lexer.token as token
  2. import src.zelkelc.ast.types as types
  3. from typing import Optional
  4. class Parser:
  5. tokens: list[token.Token]
  6. cursor: int
  7. def __init__(self, tokens: list[token.Token], cursor: int):
  8. self.tokens = tokens
  9. self.cursor = cursor
  10. def expect(self, tok: token.Token):
  11. if not self.tokens[self.cursor] == tok:
  12. print(f"Expected {tok}, but found {self.tokens[self.cursor]}")
  13. exit(1)
  14. self.cursor += 1
  15. def expect_type(self, tok_type: token.Token) -> token.Token:
  16. if not type(self.tokens[self.cursor]) == tok_type:
  17. print(f"Expected {tok_type}, but found {type(self.tokens[self.cursor])}")
  18. exit(1)
  19. self.cursor += 1
  20. return self.tokens[self.cursor - 1]
  21. def current(self, tok: token.Token):
  22. if not self.tokens[self.cursor] == tok:
  23. return False
  24. return True
  25. def current_type(self, tok_type: token.Token) -> bool:
  26. if not type(self.tokens[self.cursor]) == tok_type:
  27. return False
  28. return True
  29. def parse_type(self, is_return_type: bool) -> types.Value:
  30. identifier = self.expect_type(token.Identifier)
  31. match identifier.value:
  32. case "str":
  33. return types.String
  34. case "i64":
  35. return types.Integer64
  36. case "f64":
  37. return types.Float64
  38. case "void" if is_return_type == True:
  39. return types.Void
  40. case _:
  41. print("Invalid type found in parse_type")
  42. exit(1)
  43. def parse(self):
  44. ast: list[types.FunctionDeclaration | types.ClassDeclaration] = []
  45. while self.cursor < len(self.tokens):
  46. t = self.tokens[self.cursor]
  47. match t:
  48. case token.Identifier():
  49. match t.value:
  50. case "fn":
  51. ast.append(self.parse_function_declaration("_main.zk_")) # TODO: replace with actual filepath to the file
  52. case "struct":
  53. ast.append(self.parse_struct_declaration("_main.zk_"))
  54. case "class":
  55. ast.append(self.parse_class_declaration("_main.zk_"))
  56. case _:
  57. print(f"Invalid keyword in global {t.value}")
  58. exit(1)
  59. case token.Pound(): # TODO: hard coded to that all macro calls are treated as #llvm() macro calls
  60. self.expect(token.Pound())
  61. ident = self.expect_type(token.Identifier)
  62. match ident.value:
  63. case "fn":
  64. print(f"Macro declaration is not implemented")
  65. exit(1)
  66. case _:
  67. ast.append(self.parse_macro_call(ident))
  68. case _:
  69. print(f"Invalid token found while parsing global {t}")
  70. exit(1)
  71. return ast
  72. def parse_macro_call(self, ident: token.Identifier) -> types.MacroCall:
  73. # Hard core builtin #llvm macro block
  74. self.expect(token.LParen())
  75. body = self.expect_type(token.String)
  76. self.expect(token.RParen())
  77. return types.MacroCall(body.value)
  78. def parse_struct_declaration(self, path: str) -> types.StructDeclaration:
  79. self.expect(token.Identifier("struct"))
  80. name = self.expect_type(token.Identifier).value
  81. self.expect(token.LBrace())
  82. members: list[types.MemberDeclaration] = []
  83. while self.cursor < len(self.tokens) and not self.tokens[self.cursor] == token.RBrace():
  84. t = self.tokens[self.cursor]
  85. match t:
  86. case token.Identifier():
  87. match t.value:
  88. case "val":
  89. members.append(self.parse_member_declaration(False, len(members)))
  90. case "var":
  91. members.append(self.parse_member_declaration(True, len(members)))
  92. case _:
  93. print(f"Invalid keyword in struct body {t.value}")
  94. exit(1)
  95. case _:
  96. print(f"Invalid token found while parsing class declaration: {t}")
  97. exit(1)
  98. self.expect(token.RBrace())
  99. return types.StructDeclaration(
  100. name,
  101. members,
  102. irname = f"{path}.s_{name}"
  103. )
  104. def parse_member_declaration(self, mutable: bool, member_idx: int) -> types.MemberDeclaration:
  105. if mutable:
  106. self.expect(token.Identifier("var"))
  107. else:
  108. self.expect(token.Identifier("val"))
  109. name = self.expect_type(token.Identifier).value
  110. self.expect(token.Colon())
  111. typ = self.parse_type(False)
  112. return types.MemberDeclaration(
  113. name,
  114. mutable,
  115. typ,
  116. real_idx = member_idx
  117. )
  118. def parse_class_declaration(self, path: str) -> types.ClassDeclaration:
  119. self.expect(token.Identifier("class"))
  120. name = self.expect_type(token.Identifier).value
  121. self.expect(token.LBrace())
  122. members: list[types.ValueDeclaration] = []
  123. methods: list[types.FunctionDeclaration] = []
  124. while self.cursor < len(self.tokens) and not self.tokens[self.cursor] == token.RBrace():
  125. t = self.tokens[self.cursor]
  126. match t:
  127. case token.Identifier():
  128. match t.value:
  129. case "fn":
  130. methods.append(self.parse_function_declaration(f"{path}.c_{name}"))
  131. case "val":
  132. members.append(self.parse_member_declaration(False, len(members)))
  133. case "var":
  134. members.append(self.parse_member_declaration(True, len(members)))
  135. case _:
  136. print(f"Invalid keyword in class body {t.value}")
  137. exit(1)
  138. case _:
  139. print(f"Invalid token found while parsing class declaration: {t}")
  140. exit(1)
  141. self.expect(token.RBrace())
  142. return types.ClassDeclaration(
  143. name,
  144. members,
  145. methods,
  146. irname = f"{path}.c_{name}"
  147. )
  148. def parse_function_declaration(self, path: str) -> types.FunctionDeclaration:
  149. self.expect(token.Identifier("fn"))
  150. name = self.expect_type(token.Identifier).value
  151. self.expect(token.LParen())
  152. args: dict[str, types.Value] = {}
  153. while self.cursor < len(self.tokens) and not self.current(token.RParen()):
  154. arg_name = self.expect_type(token.Identifier).value
  155. self.expect(token.Colon())
  156. typ = self.parse_type(False)
  157. args[arg_name] = typ
  158. if not self.current(token.Comma()):
  159. break
  160. else:
  161. self.expect(token.Comma())
  162. self.expect(token.RParen())
  163. self.expect(token.Arrow())
  164. typ = self.parse_type(True)
  165. self.expect(token.LBrace())
  166. body: list[types.Node] = []
  167. hasReturn: bool = False # TODO: should be replaced with real return tree checking, this is not a good system
  168. while self.cursor < len(self.tokens) and not self.tokens[self.cursor] == token.RBrace():
  169. t = self.tokens[self.cursor]
  170. match t:
  171. case token.Identifier():
  172. match t.value:
  173. case "fn":
  174. body.append(self.parse_function_declaration(f"{path}.f_{name}"))
  175. case "val":
  176. body.append(self.parse_value_declaration(False))
  177. case "var":
  178. body.append(self.parse_value_declaration(True))
  179. case "return":
  180. body.append(self.parse_return())
  181. hasReturn = True
  182. case _:
  183. print(f"Invalid keyword in function body {t.value}")
  184. exit(1)
  185. case token.Pound(): # TODO: hard coded to that all macro calls are treated as #llvm() macro calls
  186. self.expect(token.Pound())
  187. ident = self.expect_type(token.Identifier)
  188. match ident.value:
  189. case "fn":
  190. print(f"Macro declaration is not implemented")
  191. exit(1)
  192. case _:
  193. body.append(self.parse_macro_call(ident))
  194. case _:
  195. #TODO: expression statement
  196. print(f"implement expression statement: {t}")
  197. exit(1)
  198. if hasReturn == False:
  199. print("Function must have return")
  200. exit(1)
  201. self.expect(token.RBrace())
  202. irname = f"{path}.f_{name}_{typ}"
  203. if name == "main":
  204. irname = "zkmain"
  205. return types.FunctionDeclaration(
  206. name = name,
  207. typ = typ,
  208. args = args,
  209. body = body,
  210. irname = irname
  211. )
  212. def parse_return(self) -> types.ReturnStatement:
  213. self.expect(token.Identifier("return"))
  214. expr: Optional[types.Expression] = None
  215. if not self.current(token.RBrace()):
  216. expr = self.parse_expression()
  217. return types.ReturnStatement(
  218. expr
  219. )
  220. def parse_value_declaration(self, mutable: bool) -> types.ValueDeclaration:
  221. if mutable:
  222. self.expect(token.Identifier("var"))
  223. else:
  224. self.expect(token.Identifier("val"))
  225. name = self.expect_type(token.Identifier).value
  226. self.expect(token.Colon())
  227. typ = self.parse_type(False)
  228. self.expect(token.Equals())
  229. expr = self.parse_expression()
  230. return types.ValueDeclaration(
  231. name,
  232. mutable,
  233. typ,
  234. expr,
  235. irname = f"v_{self.cursor}_{name}"
  236. )
  237. def parse_expression(self) -> types.Expression:
  238. return self.parse_binary_expression(0)
  239. def parse_binary_expression(self, min_precedence: int = 0) -> types.Expression:
  240. left = self.parse_unary_expression()
  241. while self.current_type(token.Operator):
  242. op_token = self.tokens[self.cursor]
  243. op = op_token.value
  244. precedence = self._operator_precedence(op)
  245. if precedence < min_precedence:
  246. break
  247. self.cursor += 1
  248. right = self.parse_binary_expression(precedence + 1)
  249. left = types.BinaryExpression(left, right, op, left.typ)
  250. return left
  251. def parse_unary_expression(self) -> types.Expression:
  252. if self.current_type(token.Operator):
  253. op = self.expect_type(token.Operator).value
  254. if op not in ("-", "+"):
  255. print(f"Invalid unary operator: {op}")
  256. exit(1)
  257. operand = self.parse_unary_expression()
  258. return types.UnaryExpression(operand, op, operand.typ)
  259. return self.parse_primary_expression()
  260. def parse_primary_expression(self) -> Optional[types.Expression]:
  261. t = self.tokens[self.cursor]
  262. match t:
  263. case token.Identifier():
  264. self.cursor += 1
  265. if self.current(token.LParen()):
  266. self.cursor += 1
  267. args: list[types.Expression] = []
  268. while self.cursor < len(self.tokens) and self.tokens[self.cursor] != token.RParen():
  269. if len(args) != 0:
  270. self.expect(token.Comma())
  271. args.append(self.parse_expression())
  272. self.expect(token.RParen())
  273. return types.PrimaryExpression(types.FunctionCall(t.value, args, None), types.FunctionCall)
  274. else:
  275. return types.PrimaryExpression(types.VariableRef(t.value, None, None), types.VariableRef)
  276. case token.Integer():
  277. self.cursor += 1
  278. return types.PrimaryExpression(types.Integer64(t.value), types.Integer64)
  279. case token.Float():
  280. self.cursor += 1
  281. return types.PrimaryExpression(types.Float64(t.value), types.Float64)
  282. case token.String():
  283. self.cursor += 1
  284. return types.PrimaryExpression(types.String(t.value), types.String)
  285. case token.LParen():
  286. self.expect(token.LParen())
  287. expr = self.parse_expression()
  288. self.expect(token.RParen())
  289. return expr
  290. case _:
  291. return None
  292. def _operator_precedence(self, op: str) -> int:
  293. table = {
  294. "||": 1,
  295. "&&": 2,
  296. "==": 3, "!=": 3,
  297. "<": 4, "<=": 4, ">": 4, ">=": 4,
  298. "+": 5, "-": 5,
  299. "*": 6, "/": 6, "%": 6,
  300. }
  301. return table.get(op, 0)