From 7940efc64df5bec44d6b6e553092897216c07493 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Mon, 12 May 2014 12:14:04 +0300 Subject: [PATCH] still trying that while loop. Check as everything else works --- lib/parser/basic_types.rb | 2 +- lib/parser/conditional.rb | 14 ++++---- lib/parser/expression.rb | 3 +- lib/parser/keywords.rb | 7 ++++ lib/parser/transform.rb | 3 +- test/parser/test_conditional.rb | 22 ++++++------- test/parser/test_function_definition.rb | 43 +++++++++++++++++-------- 7 files changed, 56 insertions(+), 38 deletions(-) diff --git a/lib/parser/basic_types.rb b/lib/parser/basic_types.rb index 8dd6a96f..4204e659 100644 --- a/lib/parser/basic_types.rb +++ b/lib/parser/basic_types.rb @@ -27,7 +27,7 @@ module Parser rule(:exponent) { (str('e')| str('E')) } # identifier must start with lower case - rule(:name) { (match['a-z'] >> match['a-zA-Z0-9'].repeat).as(:name) >> space? } + rule(:name) { keyword.absent? >> (match['a-z'] >> match['a-zA-Z0-9'].repeat).as(:name) >> space? } rule(:escape) { str('\\') >> any.as(:esc) } rule(:string) { quote >> ( diff --git a/lib/parser/conditional.rb b/lib/parser/conditional.rb index 0a73184d..fd166740 100644 --- a/lib/parser/conditional.rb +++ b/lib/parser/conditional.rb @@ -1,15 +1,13 @@ module Parser module Conditional include Parslet - rule(:conditional) { + rule(:conditional) do keyword_if >> left_parenthesis >> expression.as(:conditional) >> right_parenthesis >> newline >> - delimited_expressions(keyword_else).as(:if_true) >> - delimited_expressions(keyword_end).as(:if_false) - } + expressions_else.as(:if_true) >> expressions_end.as(:if_false) + end - rule(:while) { - keyword_while >> expression.as(:while_cond) >> keyword_do >> newline >> - delimited_expressions(keyword_end).as(:body) - } + rule(:while_do) do + keyword_while >> expressions_do.as(:while_cond) >> expressions_end.as(:body) + end end end diff --git a/lib/parser/expression.rb b/lib/parser/expression.rb index a225e258..600ab65d 100644 --- a/lib/parser/expression.rb +++ b/lib/parser/expression.rb @@ -3,12 +3,13 @@ module Parser include Parslet rule(:simple_expression) { function_call | integer | string | name } - rule(:expression) { (conditional | simple_expression ) >> newline.maybe } + rule(:expression) { (while_do | conditional | simple_expression ) >> newline.maybe } def delimited_expressions( delimit ) ( (delimit.absent? >> (operator_expression | expression)).repeat(1)).as(:expressions) >> delimit >> newline.maybe end + rule(:expressions_do) { delimited_expressions(keyword_do) } rule(:expressions_else) { delimited_expressions(keyword_else) } rule(:expressions_end) { delimited_expressions(keyword_end) } diff --git a/lib/parser/keywords.rb b/lib/parser/keywords.rb index 34540a3c..8d75c509 100644 --- a/lib/parser/keywords.rb +++ b/lib/parser/keywords.rb @@ -1,6 +1,7 @@ module Parser module Keywords include Parslet + rule(:keyword_begin) { str('begin').as(:begin) >> space?} rule(:keyword_def) { str('def') >> space? } rule(:keyword_do) { str('do').as(:do) >> space?} @@ -14,5 +15,11 @@ module Parser rule(:keyword_unless) { str('unless').as(:unless) >> space?} rule(:keyword_until) { str('until').as(:until) >> space?} rule(:keyword_while) { str('while').as(:while) >> space?} + + # this rule is just to make sure identifiers can't be keywords. Kind of duplication here, but we need the + # space in above rules, so just make sure to add any here too. + rule(:keyword){ str('begin') | str('def') | str('do') | str('else') | str('end') | + str('false')| str('if')| str('rescue')| str('true')| str('nil') | + str('unless')| str('until')| str('while')} end end \ No newline at end of file diff --git a/lib/parser/transform.rb b/lib/parser/transform.rb index 78a875cb..4f4714eb 100644 --- a/lib/parser/transform.rb +++ b/lib/parser/transform.rb @@ -24,7 +24,8 @@ module Parser Ast::ConditionalExpression.new(conditional, if_true, if_false) end - rule(:while => simple(:while), :while_cond => simple(:while_cond) , :do => simple(:do), + rule(:while => simple(:while), + :while_cond => { :expressions => sequence(:while_cond) , :do => simple(:do)} , :body => {:expressions => sequence(:body) , :end => simple(:e) }) do Ast::WhileExpression.new(while_cond, body) end diff --git a/test/parser/test_conditional.rb b/test/parser/test_conditional.rb index 5e3977e1..bcb9177a 100644 --- a/test/parser/test_conditional.rb +++ b/test/parser/test_conditional.rb @@ -25,23 +25,19 @@ HERE @string_input = <"while", - :while_cond=>{:integer=>"1"}, - :do=>"do", - :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, {:l=>{:name=>"a"}, :o=>"= ", :r=>{:name=>"b"}}], - :end=>"end"}} + :while_cond=>{:expressions=>[{:integer=>"1"}], + :do=>"do"}, + :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, + {:function_call=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"b"}}]}], :end=>"end"}} @transform_output = Ast::WhileExpression.new( - Ast::IntegerExpression.new(1), - [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), - Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::NameExpression.new("b"))] ) - @parser = @parser.while + [Ast::IntegerExpression.new(1)], + [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), + Ast::FuncallExpression.new("puts", [Ast::NameExpression.new("b")] )] ) + @parser = @parser.while_do end end \ No newline at end of file diff --git a/test/parser/test_function_definition.rb b/test/parser/test_function_definition.rb index 56b200a0..aa1b6aca 100644 --- a/test/parser/test_function_definition.rb +++ b/test/parser/test_function_definition.rb @@ -31,24 +31,39 @@ HERE @parser = @parser.function_definition end - def ttest_function_while + def test_function_if @string_input = < 1 do - tmp = a - a = b - b = tmp + b - puts b - n = n - 1 +def ofthen(n) + if(0) + 42 + else + 667 end end HERE - @parse_output = { :function_definition => { :name => "foo" } , - :parmeter_list => [{ :parmeter => { :name => "x" } }], - :expressions => [ { :asignee => { :name => "abba" }, :asigned => { :integer => "5" } } ] - } + @parse_output = {:function_definition=>{:name=>"ofthen"}, + :parmeter_list=>[{:parmeter=>{:name=>"n"}}], + :expressions=>[ + {:if=>"if", :conditional=>{:integer=>"0"}, + :if_true=>{:expressions=>[{:integer=>"42"}], + :else=>"else"}, + :if_false=>{:expressions=>[{:integer=>"667"}], :end=>"end"}}], :end=>"end"} + @transform_output = Ast::FunctionExpression.new(:ofthen, + [Ast::NameExpression.new("n")] , + [Ast::ConditionalExpression.new(Ast::IntegerExpression.new(0), + [Ast::IntegerExpression.new(42)],[Ast::IntegerExpression.new(667)] )] ) + @parser = @parser.function_definition + end + + def test_function_while + @string_input = <