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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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 = primary
  156. if @current_token.type == TokenKinds::OPERATOR &&
  157. %i[* /].include?(@current_token.value)
  158. operator = @current_token.value
  159. advance
  160. right = primary
  161. AST::Binary.new(operator, left, right)
  162. else
  163. left
  164. end
  165. end
  166. def primary
  167. token = @current_token
  168. expr = case token.type
  169. when TokenKinds::NULL
  170. advance
  171. AST::Null.new
  172. when TokenKinds::BOOLEAN
  173. advance
  174. AST::Boolean.new(token.value)
  175. when TokenKinds::NUMBER
  176. advance
  177. AST::Number.new(token.value)
  178. when TokenKinds::STRING
  179. advance
  180. AST::String.new(token.value)
  181. when TokenKinds::ATOM
  182. advance
  183. AST::Atom.new(token.value)
  184. when TokenKinds::IDENTIFIER
  185. identifier
  186. when TokenKinds::LBRACKET
  187. array
  188. when TokenKinds::LBRACE
  189. hash
  190. else
  191. throw "Unexpected token #{token.type}"
  192. end
  193. if @current_token.type == TokenKinds::LPAREN
  194. args = arguments
  195. AST::FunctionCall.new(expr, args)
  196. elsif @current_token.type == TokenKinds::LBRACKET
  197. eat(TokenKinds::LBRACKET)
  198. key = expression
  199. eat(TokenKinds::RBRACKET)
  200. AST::Index.new(expr, key)
  201. else
  202. expr
  203. end
  204. end
  205. def identifier
  206. token = eat(TokenKinds::IDENTIFIER)
  207. AST::Identifier.new(token.value)
  208. end
  209. def array
  210. elements = Array.new
  211. eat(TokenKinds::LBRACKET)
  212. until @current_token.type == TokenKinds::RBRACKET
  213. elements << expression
  214. if @current_token.type == TokenKinds::COMMA
  215. eat(TokenKinds::COMMA)
  216. else
  217. break
  218. end
  219. end
  220. eat(TokenKinds::RBRACKET)
  221. AST::Array.new(elements)
  222. end
  223. def hash
  224. h = Hash.new
  225. eat(TokenKinds::LBRACE)
  226. until @current_token.type == TokenKinds::RBRACE
  227. key = eat(TokenKinds::ATOM).value
  228. eat(TokenKinds::ROCKET)
  229. value = expression
  230. h[key] = value
  231. if @current_token.type == TokenKinds::COMMA
  232. eat(TokenKinds::COMMA)
  233. else
  234. break
  235. end
  236. end
  237. eat(TokenKinds::RBRACE)
  238. AST::Hash.new(h)
  239. end
  240. def arguments
  241. args = Array.new
  242. eat(TokenKinds::LPAREN)
  243. until @current_token.type == TokenKinds::RPAREN
  244. args << expression
  245. if @current_token.type == TokenKinds::COMMA
  246. eat(TokenKinds::COMMA)
  247. else
  248. break
  249. end
  250. end
  251. eat(TokenKinds::RPAREN)
  252. args
  253. end
  254. def eat(type)
  255. token = @current_token
  256. if token.type == type
  257. advance
  258. token
  259. else
  260. if token.nil?
  261. throw "Unexpected #{token.type} - expected #{type}"
  262. else
  263. throw "Unexpected #{token.type} - expected #{type}"
  264. end
  265. end
  266. end
  267. def advance
  268. @current_token = @lexer.get_token
  269. end
  270. def at_end
  271. @current_token.type == TokenKinds::EOF
  272. end
  273. end