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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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 = case token.type
  179. when TokenKinds::NULL
  180. advance
  181. AST::Null.new
  182. when TokenKinds::BOOLEAN
  183. advance
  184. AST::Boolean.new(token.value)
  185. when TokenKinds::NUMBER
  186. advance
  187. AST::Number.new(token.value)
  188. when TokenKinds::STRING
  189. advance
  190. AST::String.new(token.value)
  191. when TokenKinds::ATOM
  192. advance
  193. AST::Atom.new(token.value)
  194. when TokenKinds::IDENTIFIER
  195. identifier
  196. when TokenKinds::LBRACKET
  197. array
  198. when TokenKinds::LBRACE
  199. hash
  200. else
  201. raise "Unexpected token #{token.type}"
  202. end
  203. if @current_token.type == TokenKinds::LPAREN
  204. args = arguments
  205. AST::FunctionCall.new(expr, args)
  206. elsif @current_token.type == TokenKinds::LBRACKET
  207. eat(TokenKinds::LBRACKET)
  208. key = expression
  209. eat(TokenKinds::RBRACKET)
  210. AST::Index.new(expr, key)
  211. else
  212. expr
  213. end
  214. end
  215. def identifier
  216. token = eat(TokenKinds::IDENTIFIER)
  217. AST::Identifier.new(token.value)
  218. end
  219. def array
  220. elements = Array.new
  221. eat(TokenKinds::LBRACKET)
  222. until @current_token.type == TokenKinds::RBRACKET
  223. elements << expression
  224. if @current_token.type == TokenKinds::COMMA
  225. eat(TokenKinds::COMMA)
  226. else
  227. break
  228. end
  229. end
  230. eat(TokenKinds::RBRACKET)
  231. AST::Array.new(elements)
  232. end
  233. def hash
  234. h = Hash.new
  235. eat(TokenKinds::LBRACE)
  236. until @current_token.type == TokenKinds::RBRACE
  237. key = eat(TokenKinds::ATOM).value
  238. eat(TokenKinds::ROCKET)
  239. value = expression
  240. h[key] = value
  241. if @current_token.type == TokenKinds::COMMA
  242. eat(TokenKinds::COMMA)
  243. else
  244. break
  245. end
  246. end
  247. eat(TokenKinds::RBRACE)
  248. AST::Hash.new(h)
  249. end
  250. def arguments
  251. args = Array.new
  252. eat(TokenKinds::LPAREN)
  253. until @current_token.type == TokenKinds::RPAREN
  254. args << expression
  255. if @current_token.type == TokenKinds::COMMA
  256. eat(TokenKinds::COMMA)
  257. else
  258. break
  259. end
  260. end
  261. eat(TokenKinds::RPAREN)
  262. args
  263. end
  264. def eat(type)
  265. token = @current_token
  266. if token.type == type
  267. advance
  268. token
  269. else
  270. if token.nil?
  271. raise "Unexpected #{token.type} - expected #{type}"
  272. else
  273. raise "Unexpected #{token.type} - expected #{type}"
  274. end
  275. end
  276. end
  277. def advance
  278. @current_token = @lexer.get_token
  279. end
  280. def at_end
  281. @current_token.type == TokenKinds::EOF
  282. end
  283. end