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

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