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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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::IDENTIFIER
  182. identifier
  183. when TokenKinds::LBRACKET
  184. array
  185. else
  186. throw "Unexpected token #{token.type}"
  187. end
  188. if @current_token.type == TokenKinds::LPAREN
  189. args = arguments
  190. AST::FunctionCall.new(expr, args)
  191. else
  192. expr
  193. end
  194. end
  195. def identifier
  196. token = eat(TokenKinds::IDENTIFIER)
  197. AST::Identifier.new(token.value)
  198. end
  199. def array
  200. elements = Array.new
  201. eat(TokenKinds::LBRACKET)
  202. until @current_token.type == TokenKinds::RBRACKET
  203. elements << expression
  204. if @current_token.type == TokenKinds::COMMA
  205. eat(TokenKinds::COMMA)
  206. else
  207. break
  208. end
  209. end
  210. eat(TokenKinds::RBRACKET)
  211. AST::Array.new(elements)
  212. end
  213. def arguments
  214. args = Array.new
  215. eat(TokenKinds::LPAREN)
  216. until @current_token.type == TokenKinds::RPAREN
  217. args << expression
  218. if @current_token.type == TokenKinds::COMMA
  219. eat(TokenKinds::COMMA)
  220. else
  221. break
  222. end
  223. end
  224. eat(TokenKinds::RPAREN)
  225. args
  226. end
  227. def eat(type)
  228. token = @current_token
  229. if token.type == type
  230. advance
  231. token
  232. else
  233. if token.nil?
  234. throw "Unexpected #{token.type} - expected #{type}"
  235. else
  236. throw "Unexpected #{token.type} - expected #{type}"
  237. end
  238. end
  239. end
  240. def advance
  241. @current_token = @lexer.get_token
  242. end
  243. def at_end
  244. @current_token.type == TokenKinds::EOF
  245. end
  246. end