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.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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. unless expr.is_a?(AST::Identifier)
  141. raise 'Invalid left hand side of assignment'
  142. end
  143. eat(TokenKinds::EQUALS)
  144. value = expression
  145. AST::Assignment.new(expr, value)
  146. else
  147. expr
  148. end
  149. end
  150. def binary
  151. left = comparison
  152. if @current_token.type == TokenKinds::OPERATOR
  153. operator = @current_token.value
  154. advance
  155. right = comparison
  156. AST::Binary.new(operator, left, right)
  157. else
  158. left
  159. end
  160. end
  161. def comparison
  162. left = multiplication
  163. if @current_token.type == TokenKinds::OPERATOR &&
  164. %i[< > <= >=].include?(@current_token.type)
  165. operator = @current_token.value
  166. advance
  167. right = multiplication
  168. AST::Binary.new(operator, left, right)
  169. else
  170. left
  171. end
  172. end
  173. def addition
  174. left = multiplication
  175. if @current_token.type == TokenKinds::OPERATOR &&
  176. %i[+ -].include?(@current_token.value)
  177. operator = @current_token.value
  178. advance
  179. right = multiplication
  180. AST::Binary.new(operator, left, right)
  181. else
  182. left
  183. end
  184. end
  185. def multiplication
  186. left = unary
  187. if @current_token.type == TokenKinds::OPERATOR &&
  188. %i[* /].include?(@current_token.value)
  189. operator = @current_token.value
  190. advance
  191. right = unary
  192. AST::Binary.new(operator, left, right)
  193. else
  194. left
  195. end
  196. end
  197. def unary
  198. if @current_token.type == TokenKinds::OPERATOR &&
  199. %i[- !].include?(@current_token.value)
  200. operator = eat(TokenKinds::OPERATOR).value
  201. expr = primary
  202. AST::Unary.new(operator, expr)
  203. else
  204. primary
  205. end
  206. end
  207. def primary
  208. token = @current_token
  209. expr =
  210. case token.type
  211. when TokenKinds::NULL
  212. advance
  213. AST::Null.new
  214. when TokenKinds::BOOLEAN
  215. advance
  216. AST::Boolean.new(token.value)
  217. when TokenKinds::NUMBER
  218. advance
  219. AST::Number.new(token.value)
  220. when TokenKinds::STRING
  221. advance
  222. AST::String.new(token.value)
  223. when TokenKinds::ATOM
  224. advance
  225. AST::Atom.new(token.value)
  226. when TokenKinds::IDENTIFIER
  227. identifier
  228. when TokenKinds::LBRACKET
  229. array
  230. when TokenKinds::LBRACE
  231. hash
  232. when TokenKinds::LPAREN
  233. eat(TokenKinds::LPAREN)
  234. e = expression
  235. eat(TokenKinds::RPAREN)
  236. e
  237. when TokenKinds::FUNCTION
  238. function_expression
  239. else
  240. raise "Unexpected token #{token.type}"
  241. end
  242. if @current_token.type == TokenKinds::LPAREN
  243. args = arguments
  244. AST::FunctionCall.new(expr, args)
  245. elsif @current_token.type == TokenKinds::LBRACKET
  246. eat(TokenKinds::LBRACKET)
  247. key = expression
  248. eat(TokenKinds::RBRACKET)
  249. AST::Index.new(expr, key)
  250. else
  251. expr
  252. end
  253. end
  254. def function_expression
  255. eat(TokenKinds::FUNCTION)
  256. params = parameters
  257. body = block
  258. AST::FunctionDefinition.new(nil, params, body)
  259. end
  260. def identifier
  261. token = eat(TokenKinds::IDENTIFIER)
  262. AST::Identifier.new(token.value)
  263. end
  264. def array
  265. elements = Array.new
  266. eat(TokenKinds::LBRACKET)
  267. until @current_token.type == TokenKinds::RBRACKET
  268. elements << expression
  269. if @current_token.type == TokenKinds::COMMA
  270. eat(TokenKinds::COMMA)
  271. else
  272. break
  273. end
  274. end
  275. eat(TokenKinds::RBRACKET)
  276. AST::Array.new(elements)
  277. end
  278. def hash
  279. h = Hash.new
  280. eat(TokenKinds::LBRACE)
  281. until @current_token.type == TokenKinds::RBRACE
  282. key = eat(TokenKinds::ATOM).value
  283. eat(TokenKinds::ROCKET)
  284. value = expression
  285. h[key] = value
  286. if @current_token.type == TokenKinds::COMMA
  287. eat(TokenKinds::COMMA)
  288. else
  289. break
  290. end
  291. end
  292. eat(TokenKinds::RBRACE)
  293. AST::Hash.new(h)
  294. end
  295. def arguments
  296. args = Array.new
  297. eat(TokenKinds::LPAREN)
  298. until @current_token.type == TokenKinds::RPAREN
  299. args << expression
  300. if @current_token.type == TokenKinds::COMMA
  301. eat(TokenKinds::COMMA)
  302. else
  303. break
  304. end
  305. end
  306. eat(TokenKinds::RPAREN)
  307. args
  308. end
  309. def eat(type)
  310. token = @current_token
  311. if token.type == type
  312. advance
  313. token
  314. else
  315. if token.nil?
  316. raise "Unexpected #{token.type} - expected #{type}"
  317. else
  318. raise "Unexpected #{token.type} - expected #{type}"
  319. end
  320. end
  321. end
  322. def advance
  323. @current_token = @lexer.get_token
  324. end
  325. def at_end
  326. @current_token.type == TokenKinds::EOF
  327. end
  328. end