A toy dynamic programming language written in Ruby
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

parser.rb 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. class Parser
  2. def initialize(lexer)
  3. @lexer = lexer
  4. @current_token = @lexer.get_token
  5. end
  6. def parse
  7. tree = Array.new
  8. tree << statement until at_end
  9. tree
  10. end
  11. def statement
  12. if @current_token.type == TokenKinds::IF
  13. conditional
  14. elsif @current_token.type == TokenKinds::LET
  15. variable_declaration
  16. elsif @current_token.type == TokenKinds::FUNCTION
  17. next_token = @lexer.peek
  18. if next_token && next_token.type == TokenKinds::IDENTIFIER
  19. function_definition
  20. else
  21. expression_statement
  22. end
  23. elsif @current_token.type == TokenKinds::CLASS
  24. class_definition
  25. elsif @current_token.type == TokenKinds::FOR
  26. for_loop
  27. else
  28. expression_statement
  29. end
  30. end
  31. def expression_statement
  32. expr = expression
  33. eat(TokenKinds::SEMICOLON)
  34. return expr
  35. end
  36. def variable_declaration
  37. eat(TokenKinds::LET)
  38. name = identifier
  39. eat(TokenKinds::EQUALS)
  40. value = expression
  41. eat(TokenKinds::SEMICOLON)
  42. AST::VariableDeclaration.new(name, value)
  43. end
  44. def function_definition
  45. eat(TokenKinds::FUNCTION)
  46. name = identifier
  47. params = parameters
  48. body = block
  49. AST::FunctionDefinition.new(name, params, body)
  50. end
  51. def class_definition
  52. eat(TokenKinds::CLASS)
  53. class_name = AST::Identifier.new(eat(TokenKinds::CLASS_NAME).value)
  54. eat(TokenKinds::LBRACE)
  55. members = Array.new
  56. while [TokenKinds::PUBLIC, TokenKinds::PRIVATE].include?(
  57. @current_token.type
  58. )
  59. is_public =
  60. if @current_token.type == TokenKinds::PUBLIC
  61. eat(TokenKinds::PUBLIC)
  62. true
  63. elsif @current_token.type == TokenKinds::PRIVATE
  64. eat(TokenKinds::PRIVATE)
  65. false
  66. end
  67. while !at_end && true
  68. name = identifier
  69. members << AST::Member.new(name, is_public)
  70. if @current_token.type == TokenKinds::COMMA
  71. eat(TokenKinds::COMMA)
  72. else
  73. break
  74. end
  75. end
  76. eat(TokenKinds::SEMICOLON)
  77. end
  78. methods = Array.new
  79. while @current_token.type == TokenKinds::FUNCTION
  80. methods << function_definition
  81. end
  82. eat(TokenKinds::RBRACE)
  83. AST::ClassDefinition.new(class_name, members, methods)
  84. end
  85. def conditional
  86. branches = Array.new
  87. eat(TokenKinds::IF)
  88. condition = expression
  89. block = self.block
  90. branches << AST::Branch.new(condition, block)
  91. while @current_token.type == TokenKinds::ELSEIF
  92. eat(TokenKinds::ELSEIF)
  93. condition = expression
  94. block = self.block
  95. branches << AST::Branch.new(condition, block)
  96. end
  97. if @current_token.type == TokenKinds::ELSE
  98. eat(TokenKinds::ELSE)
  99. block = self.block
  100. branches << AST::Branch.new(AST::Boolean.new(true), block)
  101. end
  102. AST::Conditional.new(branches)
  103. end
  104. def for_loop
  105. eat(TokenKinds::FOR)
  106. iterator = identifier
  107. eat(TokenKinds::IN)
  108. iterable = expression
  109. body = block
  110. AST::ForLoop.new(iterator, iterable, body)
  111. end
  112. def parameters
  113. params = Array.new
  114. eat(TokenKinds::LPAREN)
  115. while @current_token.type == TokenKinds::IDENTIFIER
  116. params << identifier
  117. if @current_token.type == TokenKinds::COMMA
  118. eat(TokenKinds::COMMA)
  119. else
  120. break
  121. end
  122. end
  123. eat(TokenKinds::RPAREN)
  124. params
  125. end
  126. def block
  127. statements = Array.new
  128. eat(TokenKinds::LBRACE)
  129. statements << statement until @current_token.type == TokenKinds::RBRACE
  130. eat(TokenKinds::RBRACE)
  131. AST::Block.new(statements)
  132. end
  133. def expression
  134. assignment
  135. end
  136. private
  137. def assignment
  138. expr = binary
  139. if @current_token.type == TokenKinds::EQUALS
  140. raise 'Invalid left hand side of assignment' unless expr.is_a?(AST::Identifier)
  141. eat(TokenKinds::EQUALS)
  142. value = expression
  143. AST::Assignment.new(expr, value)
  144. else
  145. expr
  146. end
  147. end
  148. def binary
  149. left = comparison
  150. if @current_token.type == TokenKinds::OPERATOR
  151. operator = @current_token.value
  152. advance
  153. right = comparison
  154. AST::Binary.new(operator, left, right)
  155. else
  156. left
  157. end
  158. end
  159. def comparison
  160. left = multiplication
  161. if @current_token.type == TokenKinds::OPERATOR &&
  162. %i[< > <= >=].include?(@current_token.type)
  163. operator = @current_token.value
  164. advance
  165. right = multiplication
  166. AST::Binary.new(operator, left, right)
  167. else
  168. left
  169. end
  170. end
  171. def addition
  172. left = multiplication
  173. if @current_token.type == TokenKinds::OPERATOR &&
  174. %i[+ -].include?(@current_token.value)
  175. operator = @current_token.value
  176. advance
  177. right = multiplication
  178. AST::Binary.new(operator, left, right)
  179. else
  180. left
  181. end
  182. end
  183. def multiplication
  184. left = unary
  185. if @current_token.type == TokenKinds::OPERATOR &&
  186. %i[* /].include?(@current_token.value)
  187. operator = @current_token.value
  188. advance
  189. right = unary
  190. AST::Binary.new(operator, left, right)
  191. else
  192. left
  193. end
  194. end
  195. def unary
  196. if @current_token.type == TokenKinds::OPERATOR &&
  197. %i[- !].include?(@current_token.value)
  198. operator = eat(TokenKinds::OPERATOR).value
  199. expr = primary
  200. AST::Unary.new(operator, expr)
  201. else
  202. primary
  203. end
  204. end
  205. def primary
  206. token = @current_token
  207. expr =
  208. case token.type
  209. when TokenKinds::NULL
  210. advance
  211. AST::Null.new
  212. when TokenKinds::BOOLEAN
  213. advance
  214. AST::Boolean.new(token.value)
  215. when TokenKinds::NUMBER
  216. advance
  217. AST::Number.new(token.value)
  218. when TokenKinds::STRING
  219. advance
  220. AST::String.new(token.value)
  221. when TokenKinds::ATOM
  222. advance
  223. AST::Atom.new(token.value)
  224. when TokenKinds::IDENTIFIER
  225. identifier
  226. when TokenKinds::LBRACKET
  227. array
  228. when TokenKinds::LBRACE
  229. hash
  230. when TokenKinds::LPAREN
  231. eat(TokenKinds::LPAREN)
  232. e = expression
  233. eat(TokenKinds::RPAREN)
  234. e
  235. when TokenKinds::FUNCTION
  236. function_expression
  237. else
  238. raise "Unexpected token #{token.type}"
  239. end
  240. if @current_token.type == TokenKinds::LPAREN
  241. args = arguments
  242. AST::FunctionCall.new(expr, args)
  243. elsif @current_token.type == TokenKinds::LBRACKET
  244. eat(TokenKinds::LBRACKET)
  245. key = expression
  246. eat(TokenKinds::RBRACKET)
  247. AST::Index.new(expr, key)
  248. else
  249. expr
  250. end
  251. end
  252. def function_expression
  253. eat(TokenKinds::FUNCTION)
  254. params = parameters
  255. body = block
  256. AST::FunctionDefinition.new(nil, params, body)
  257. end
  258. def identifier
  259. token = eat(TokenKinds::IDENTIFIER)
  260. AST::Identifier.new(token.value)
  261. end
  262. def array
  263. elements = Array.new
  264. eat(TokenKinds::LBRACKET)
  265. until @current_token.type == TokenKinds::RBRACKET
  266. elements << expression
  267. if @current_token.type == TokenKinds::COMMA
  268. eat(TokenKinds::COMMA)
  269. else
  270. break
  271. end
  272. end
  273. eat(TokenKinds::RBRACKET)
  274. AST::Array.new(elements)
  275. end
  276. def hash
  277. h = Hash.new
  278. eat(TokenKinds::LBRACE)
  279. until @current_token.type == TokenKinds::RBRACE
  280. key = eat(TokenKinds::ATOM).value
  281. eat(TokenKinds::ROCKET)
  282. value = expression
  283. h[key] = value
  284. if @current_token.type == TokenKinds::COMMA
  285. eat(TokenKinds::COMMA)
  286. else
  287. break
  288. end
  289. end
  290. eat(TokenKinds::RBRACE)
  291. AST::Hash.new(h)
  292. end
  293. def arguments
  294. args = Array.new
  295. eat(TokenKinds::LPAREN)
  296. until @current_token.type == TokenKinds::RPAREN
  297. args << expression
  298. if @current_token.type == TokenKinds::COMMA
  299. eat(TokenKinds::COMMA)
  300. else
  301. break
  302. end
  303. end
  304. eat(TokenKinds::RPAREN)
  305. args
  306. end
  307. def eat(type)
  308. token = @current_token
  309. if token.type == type
  310. advance
  311. token
  312. else
  313. if token.nil?
  314. raise "Unexpected #{token.type} - expected #{type}"
  315. else
  316. raise "Unexpected #{token.type} - expected #{type}"
  317. end
  318. end
  319. end
  320. def advance
  321. @current_token = @lexer.get_token
  322. end
  323. def at_end
  324. @current_token.type == TokenKinds::EOF
  325. end
  326. end