parser.py 14 KB

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