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

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