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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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. when TokenKinds::LPAREN
  201. eat(TokenKinds::LPAREN)
  202. e = expression
  203. eat(TokenKinds::RPAREN)
  204. e
  205. else
  206. raise "Unexpected token #{token.type}"
  207. end
  208. if @current_token.type == TokenKinds::LPAREN
  209. args = arguments
  210. AST::FunctionCall.new(expr, args)
  211. elsif @current_token.type == TokenKinds::LBRACKET
  212. eat(TokenKinds::LBRACKET)
  213. key = expression
  214. eat(TokenKinds::RBRACKET)
  215. AST::Index.new(expr, key)
  216. else
  217. expr
  218. end
  219. end
  220. def identifier
  221. token = eat(TokenKinds::IDENTIFIER)
  222. AST::Identifier.new(token.value)
  223. end
  224. def array
  225. elements = Array.new
  226. eat(TokenKinds::LBRACKET)
  227. until @current_token.type == TokenKinds::RBRACKET
  228. elements << expression
  229. if @current_token.type == TokenKinds::COMMA
  230. eat(TokenKinds::COMMA)
  231. else
  232. break
  233. end
  234. end
  235. eat(TokenKinds::RBRACKET)
  236. AST::Array.new(elements)
  237. end
  238. def hash
  239. h = Hash.new
  240. eat(TokenKinds::LBRACE)
  241. until @current_token.type == TokenKinds::RBRACE
  242. key = eat(TokenKinds::ATOM).value
  243. eat(TokenKinds::ROCKET)
  244. value = expression
  245. h[key] = value
  246. if @current_token.type == TokenKinds::COMMA
  247. eat(TokenKinds::COMMA)
  248. else
  249. break
  250. end
  251. end
  252. eat(TokenKinds::RBRACE)
  253. AST::Hash.new(h)
  254. end
  255. def arguments
  256. args = Array.new
  257. eat(TokenKinds::LPAREN)
  258. until @current_token.type == TokenKinds::RPAREN
  259. args << expression
  260. if @current_token.type == TokenKinds::COMMA
  261. eat(TokenKinds::COMMA)
  262. else
  263. break
  264. end
  265. end
  266. eat(TokenKinds::RPAREN)
  267. args
  268. end
  269. def eat(type)
  270. token = @current_token
  271. if token.type == type
  272. advance
  273. token
  274. else
  275. if token.nil?
  276. raise "Unexpected #{token.type} - expected #{type}"
  277. else
  278. raise "Unexpected #{token.type} - expected #{type}"
  279. end
  280. end
  281. end
  282. def advance
  283. @current_token = @lexer.get_token
  284. end
  285. def at_end
  286. @current_token.type == TokenKinds::EOF
  287. end
  288. end