diff --git a/lib/ast/operator_expressions.rb b/lib/ast/operator_expressions.rb index 395f84b9..21a7e16d 100644 --- a/lib/ast/operator_expressions.rb +++ b/lib/ast/operator_expressions.rb @@ -25,26 +25,6 @@ module Ast end end - class AssignmentExpression < Expression - attr_reader :assignee, :assigned - def initialize assignee, assigned - @assignee, @assigned = assignee, assigned - end - def inspect - self.class.name + ".new(" + assignee.inspect + ", " + assigned.inspect + ")" - end - - def compile context - value = @assigned.compile(context) - variable = Vm::Variable.new @assignee , :r0 , value - context.locals[@assignee] = variable - variable - end - - def attributes - [:assignee, :assigned] - end - end class OperatorExpression < Expression attr_reader :operator, :left, :right @@ -62,6 +42,14 @@ module Ast parent_locals = context.locals context.locals = {} args = [] + + #assignemnt + value = @assigned.compile(context) + variable = Vm::Variable.new @assignee , :r0 , value + context.locals[@assignee] = variable + variable + + params.each do |param| args << param.compile(context) # making the argument a local end diff --git a/lib/parser/basic_types.rb b/lib/parser/basic_types.rb index 5b1f8067..8dd6a96f 100644 --- a/lib/parser/basic_types.rb +++ b/lib/parser/basic_types.rb @@ -20,7 +20,7 @@ module Parser rule(:double_quote){ str('"') } rule(:minus) { str('-') } rule(:plus) { str('+') } - rule(:equal_sign) { str('=') >> space?} + rule(:sign) { plus | minus } rule(:dot) { str('.') } rule(:digit) { match('[0-9]') } diff --git a/lib/parser/crystal.rb b/lib/parser/crystal.rb index fc897067..7ecfe09f 100644 --- a/lib/parser/crystal.rb +++ b/lib/parser/crystal.rb @@ -5,6 +5,7 @@ require_relative "conditional" require_relative "expression" require_relative "function_call" require_relative "function_definition" +require_relative "operators" module Parser @@ -20,11 +21,12 @@ module Parser include BasicTypes include Tokens include Keywords - include FunctionCall - include FunctionDefinition include Conditional include Expression + include FunctionCall + include FunctionDefinition + include Operators - rule(:root){ (function_definition | expression | assignment | function_call).repeat } + rule(:root){ (function_definition | expression | operator_expression | function_call).repeat } end end diff --git a/lib/parser/expression.rb b/lib/parser/expression.rb index a504c1fd..a225e258 100644 --- a/lib/parser/expression.rb +++ b/lib/parser/expression.rb @@ -2,21 +2,15 @@ module Parser module Expression include Parslet - rule(:assignment) { name.as(:asignee) >> equal_sign >> expression.as(:asigned) } - rule(:simple_expression) { function_call | integer | string | name } rule(:expression) { (conditional | simple_expression ) >> newline.maybe } def delimited_expressions( delimit ) - ( (delimit.absent? >> (assignment | expression)).repeat(1)).as(:expressions) >> delimit >> newline.maybe + ( (delimit.absent? >> (operator_expression | expression)).repeat(1)).as(:expressions) >> delimit >> newline.maybe end rule(:expressions_else) { delimited_expressions(keyword_else) } rule(:expressions_end) { delimited_expressions(keyword_end) } - rule(:operator_expression) do - infix_expression(expression, [multiply, 2, :left], [plus, 1, :right]) - end - end end diff --git a/lib/parser/keywords.rb b/lib/parser/keywords.rb index 8cccf8d2..34540a3c 100644 --- a/lib/parser/keywords.rb +++ b/lib/parser/keywords.rb @@ -1,15 +1,18 @@ module Parser module Keywords include Parslet - rule(:keyword_if) { str('if') >> space? } - rule(:keyword_else) { str('else') >> space? } - rule(:keyword_def) { str('def') >> space? } - rule(:keyword_end) { str('end') >> space? } - rule(:keyword_true) { str('true').as(:true) >> space?} - rule(:keyword_false){ str('false').as(:false) >> space?} - rule(:keyword_nil) { str('null').as(:nil) >> space?} - rule(:keyword_while) { str('while').as(:while) >> space?} - rule(:keyword_do) { str('do').as(:do) >> space?} - rule(:keyword_begin) { str('begin').as(:begin) >> space?} + rule(:keyword_begin) { str('begin').as(:begin) >> space?} + rule(:keyword_def) { str('def') >> space? } + rule(:keyword_do) { str('do').as(:do) >> space?} + rule(:keyword_else) { str('else').as(:else) >> space? } + rule(:keyword_end) { str('end').as(:end) >> space? } + rule(:keyword_false) { str('false').as(:false) >> space?} + rule(:keyword_if) { str('if').as(:if) >> space? } + rule(:keyword_rescue) { str('rescue').as(:rescue) >> space?} + rule(:keyword_true) { str('true').as(:true) >> space?} + rule(:keyword_nil) { str('nil').as(:nil) >> space?} + rule(:keyword_unless) { str('unless').as(:unless) >> space?} + rule(:keyword_until) { str('until').as(:until) >> space?} + rule(:keyword_while) { str('while').as(:while) >> space?} end end \ No newline at end of file diff --git a/lib/parser/operators.rb b/lib/parser/operators.rb index e69de29b..74d026b4 100644 --- a/lib/parser/operators.rb +++ b/lib/parser/operators.rb @@ -0,0 +1,52 @@ +module Parser + module Operators + include Parslet + rule(:exponent) { str('**') >> space?} + rule(:multiply) { match['*/%'] >> space? } + rule(:plus) { match['+-'] >> space? } + rule(:shift) { str(">>") | str("<<") >> space?} + rule(:bit_and) { str('&') >> space?} + rule(:bit_or) { str('|') >> space?} + rule(:greater_equal) { str('>=') >> space?} + rule(:smaller_equal) { str('<=') >> space?} + rule(:larger) { str('>') >> space?} + rule(:smaller) { str('<') >> space?} + rule(:identity) { str('===') >> space?} + rule(:equal) { str('==') >> space?} + rule(:not_equal) { str('!=') >> space?} + rule(:boolean_and) { str('&&') | str("and") >> space?} + rule(:boolean_or) { str('||') | str("or") >> space?} + rule(:assign) { str('=') >> space?} + rule(:op_assign) { str('+=')|str('-=')|str('*=')|str('/=')|str('%=') >> space?} + rule(:eclipse) { str('..') |str("...") >> space?} + rule(:assign) { str('=') >> space?} + + #infix doing the heavy lifting here, + # is defined as an expressions and array of [atoms,priority,binding] triples + rule(:operator_expression) do infix_expression(expression, + [exponent, 120, :left] , + [multiply, 120, :left] , + [plus, 110, :left], + [shift, 100, :left], + [bit_and, 90, :left], + [bit_or, 90, :right], + [greater_equal, 80, :left], + [smaller_equal, 80, :left], + [larger, 80, :left], + [smaller, 80, :left], + [identity, 70, :right], + [equal, 70, :right], + [not_equal, 70, :right], + [boolean_and, 60, :left], + [boolean_or, 50, :right], + [eclipse, 40, :right], + [keyword_rescue, 30, :right], + [assign, 20, :right], + [op_assign, 20, :right], + [keyword_until, 10, :right], + [keyword_while, 10, :right], + [keyword_unless, 10, :right], + [keyword_if, 10, :right]) + end + end +end diff --git a/lib/parser/tokens.rb b/lib/parser/tokens.rb index 1bfbb529..70d60dc2 100644 --- a/lib/parser/tokens.rb +++ b/lib/parser/tokens.rb @@ -15,7 +15,5 @@ module Parser rule(:question_mark) { str('?') >> space? } rule(:excamation_mark) { str('!') >> space? } - rule(:multiply) { match['*/'] >> space? } - rule(:plus) { match['+-'] >> space? } end end \ No newline at end of file diff --git a/lib/parser/transform.rb b/lib/parser/transform.rb index 30254e6a..78a875cb 100644 --- a/lib/parser/transform.rb +++ b/lib/parser/transform.rb @@ -18,14 +18,14 @@ module Parser Ast::FuncallExpression.new(function_call.name, argument_list) end - rule(:conditional => simple(:conditional), - :if_true => {:expressions => sequence(:if_true)}, - :if_false => {:expressions => sequence(:if_false)}) do + rule(:if => simple(:if), :conditional => simple(:conditional), + :if_true => {:expressions => sequence(:if_true) , :else => simple(:else) }, + :if_false => {:expressions => sequence(:if_false) , :end => simple(:e) }) do Ast::ConditionalExpression.new(conditional, if_true, if_false) end rule(:while => simple(:while), :while_cond => simple(:while_cond) , :do => simple(:do), - :body => {:expressions => sequence(:body)}) do + :body => {:expressions => sequence(:body) , :end => simple(:e) }) do Ast::WhileExpression.new(while_cond, body) end @@ -34,14 +34,10 @@ module Parser rule(:function_definition => simple(:function_definition), :parmeter_list => sequence(:parmeter_list), - :expressions => sequence(:expressions)) do + :expressions => sequence(:expressions) , :end => simple(:e)) do Ast::FunctionExpression.new(function_definition.name, parmeter_list, expressions) end - rule(:asignee => simple(:left) , :asigned => simple(:right) ) do - Ast::AssignmentExpression.new(left , right ) - end - rule(l: simple(:l), o: simple(:o) , r: simple(:r)) do Ast::OperatorExpression.new( o.to_s.strip , l ,r) end