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

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