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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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. property_declarations = 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. property_declarations << AST::PropertyDeclaration.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, property_declarations, 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. while [TokenKinds::LPAREN, TokenKinds::LBRACKET].include?(@current_token.type)
  243. case @current_token.type
  244. when TokenKinds::LPAREN
  245. args = arguments
  246. expr = AST::FunctionCall.new(expr, args)
  247. when TokenKinds::LBRACKET
  248. eat(TokenKinds::LBRACKET)
  249. key = expression
  250. eat(TokenKinds::RBRACKET)
  251. expr = AST::Index.new(expr, key)
  252. end
  253. end
  254. expr
  255. end
  256. def function_expression
  257. eat(TokenKinds::FUNCTION)
  258. params = parameters
  259. body = block
  260. AST::FunctionDefinition.new(nil, params, body)
  261. end
  262. def identifier
  263. token = eat(TokenKinds::IDENTIFIER)
  264. AST::Identifier.new(token.value)
  265. end
  266. def array
  267. elements = Array.new
  268. eat(TokenKinds::LBRACKET)
  269. until @current_token.type == TokenKinds::RBRACKET
  270. elements << expression
  271. if @current_token.type == TokenKinds::COMMA
  272. eat(TokenKinds::COMMA)
  273. else
  274. break
  275. end
  276. end
  277. eat(TokenKinds::RBRACKET)
  278. AST::Array.new(elements)
  279. end
  280. def hash
  281. h = Hash.new
  282. eat(TokenKinds::LBRACE)
  283. until @current_token.type == TokenKinds::RBRACE
  284. key = eat(TokenKinds::ATOM).value
  285. eat(TokenKinds::ROCKET)
  286. value = expression
  287. h[key] = value
  288. if @current_token.type == TokenKinds::COMMA
  289. eat(TokenKinds::COMMA)
  290. else
  291. break
  292. end
  293. end
  294. eat(TokenKinds::RBRACE)
  295. AST::Hash.new(h)
  296. end
  297. def arguments
  298. args = Array.new
  299. eat(TokenKinds::LPAREN)
  300. until @current_token.type == TokenKinds::RPAREN
  301. args << expression
  302. if @current_token.type == TokenKinds::COMMA
  303. eat(TokenKinds::COMMA)
  304. else
  305. break
  306. end
  307. end
  308. eat(TokenKinds::RPAREN)
  309. args
  310. end
  311. def eat(type)
  312. token = @current_token
  313. if token.type == type
  314. advance
  315. token
  316. else
  317. if token.nil?
  318. raise "Unexpected #{token.type} - expected #{type}"
  319. else
  320. raise "Unexpected #{token.type} - expected #{type}"
  321. end
  322. end
  323. end
  324. def advance
  325. @current_token = @lexer.get_token
  326. end
  327. def at_end
  328. @current_token.type == TokenKinds::EOF
  329. end
  330. end