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 7.7KB

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