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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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. when TokenKinds::FUNCTION
  217. function_expression
  218. else
  219. raise "Unexpected token #{token.type}"
  220. end
  221. if @current_token.type == TokenKinds::LPAREN
  222. args = arguments
  223. AST::FunctionCall.new(expr, args)
  224. elsif @current_token.type == TokenKinds::LBRACKET
  225. eat(TokenKinds::LBRACKET)
  226. key = expression
  227. eat(TokenKinds::RBRACKET)
  228. AST::Index.new(expr, key)
  229. else
  230. expr
  231. end
  232. end
  233. def function_expression
  234. eat(TokenKinds::FUNCTION)
  235. params = parameters
  236. body = block
  237. AST::FunctionDefinition.new(nil, params, body)
  238. end
  239. def identifier
  240. token = eat(TokenKinds::IDENTIFIER)
  241. AST::Identifier.new(token.value)
  242. end
  243. def array
  244. elements = Array.new
  245. eat(TokenKinds::LBRACKET)
  246. until @current_token.type == TokenKinds::RBRACKET
  247. elements << expression
  248. if @current_token.type == TokenKinds::COMMA
  249. eat(TokenKinds::COMMA)
  250. else
  251. break
  252. end
  253. end
  254. eat(TokenKinds::RBRACKET)
  255. AST::Array.new(elements)
  256. end
  257. def hash
  258. h = Hash.new
  259. eat(TokenKinds::LBRACE)
  260. until @current_token.type == TokenKinds::RBRACE
  261. key = eat(TokenKinds::ATOM).value
  262. eat(TokenKinds::ROCKET)
  263. value = expression
  264. h[key] = value
  265. if @current_token.type == TokenKinds::COMMA
  266. eat(TokenKinds::COMMA)
  267. else
  268. break
  269. end
  270. end
  271. eat(TokenKinds::RBRACE)
  272. AST::Hash.new(h)
  273. end
  274. def arguments
  275. args = Array.new
  276. eat(TokenKinds::LPAREN)
  277. until @current_token.type == TokenKinds::RPAREN
  278. args << expression
  279. if @current_token.type == TokenKinds::COMMA
  280. eat(TokenKinds::COMMA)
  281. else
  282. break
  283. end
  284. end
  285. eat(TokenKinds::RPAREN)
  286. args
  287. end
  288. def eat(type)
  289. token = @current_token
  290. if token.type == type
  291. advance
  292. token
  293. else
  294. if token.nil?
  295. raise "Unexpected #{token.type} - expected #{type}"
  296. else
  297. raise "Unexpected #{token.type} - expected #{type}"
  298. end
  299. end
  300. end
  301. def advance
  302. @current_token = @lexer.get_token
  303. end
  304. def at_end
  305. @current_token.type == TokenKinds::EOF
  306. end
  307. end