a good stab at array anf hash constants

This commit is contained in:
Torsten Ruger 2014-05-12 21:36:38 +03:00
parent 25a7c3ea68
commit fdb5dd4f67
14 changed files with 126 additions and 24 deletions

View File

@ -0,0 +1,39 @@
module Ast
class ArrayExpression < Expression
attr_reader :values
def initialize vals
@values = vals
end
def inspect
self.class.name + ".new(" + values.to_s+ ")"
end
def compile context
to.do
end
def attributes
[:values]
end
end
class AssociationExpression < Expression
attr_reader :key , :value
def initialize key , value
@key , @value = key , value
end
def inspect
self.class.name + ".new(" + key.inspect + " , " + value.inspect + ")"
end
def compile context
to.do
end
def attributes
[:key , :value]
end
end
class HashExpression < ArrayExpression
def compile context
to.do
end
end
end

View File

@ -15,9 +15,6 @@ module Ast
def compile context
raise "abstract #{self}"
end
def inspectt
self.class.name + ".new(" + self.attributes.collect{|m| self.send(m).inspect }.join( ",") +")"
end
def attributes
raise "abstract #{self}"
end
@ -36,6 +33,7 @@ module Ast
end
require_relative "basic_expressions"
require_relative "compound_expressions"
require_relative "conditional_expression"
require_relative "while_expression"
require_relative "function_expression"

View File

@ -1,7 +1,5 @@
module Parser
# Basic types are numbers and strings
# later maybe arrays and hashes
# floats ?
module BasicTypes
include Parslet
# space really is just space. ruby is newline sensitive, so there is more whitespace footwork
@ -35,19 +33,10 @@ module Parser
nonquote.as(:char)
).repeat(1).as(:string) >> quote }
# rule(:string_special) { match['\0\t\n\r"\\\\'] }
# rule(:escaped_special) { str("\\") >> match['0tnr"\\\\'] }
#anything in double quotes
# rule(:string){
# double_quote >>
# ( escaped_special | string_special.absent? >> any ).repeat.as(:string) >>
# double_quote >> space?
# }
rule(:integer) { sign.maybe >> digit.repeat(1).as(:integer) >> space? }
rule(:float) { integer >> dot >> integer >>
(exponent >> sign.maybe >> digit.repeat(1,3)).maybe >> space?}
rule(:basic_type){ integer | name | string | float }
end
end

View File

@ -0,0 +1,20 @@
module Parser
# Compound types are Arrays and Hashes
module CompundTypes
include Parslet
rule(:array) do
left_bracket >>
( ((operator_expression|value_expression).as(:element) >> space? >>
(comma >> space? >> (operator_expression|value_expression).as(:element)).repeat(0)).repeat(0,1)).as(:array) >>
space? >> right_bracket
end
rule(:hash_pair) { basic_type.as(:argument) >> association >> (operator_expression|value_expression).as(:element) }
rule(:hash) { left_brace >> ((hash_pair.as(:hash_pair) >>
(comma >> space? >> hash_pair.as(:hash_pair)).repeat(0)).repeat(0,1)).as(:hash)>>
space? >> right_brace }
end
end

View File

@ -3,13 +3,13 @@ module Parser
include Parslet
rule(:conditional) do
keyword_if >>
(( (simple_expression|operator_expression).as(:conditional) ) |
left_parenthesis >> (operator_expression|simple_expression).as(:conditional) >> right_parenthesis) >>
(( (value_expression|operator_expression).as(:conditional) ) |
left_parenthesis >> (operator_expression|value_expression).as(:conditional) >> right_parenthesis) >>
newline >> expressions_else.as(:if_true) >> newline >> expressions_end.as(:if_false)
end
rule(:while_do) do
keyword_while >> left_parenthesis >> (operator_expression|simple_expression).as(:while_cond) >>
keyword_while >> left_parenthesis >> (operator_expression|value_expression).as(:while_cond) >>
right_parenthesis >> keyword_do >> newline >>
expressions_end.as(:body)
end

View File

@ -1,4 +1,5 @@
require_relative "basic_types"
require_relative "compound_types"
require_relative "tokens"
require_relative "keywords"
require_relative "control"
@ -19,6 +20,7 @@ module Parser
class Crystal < Parslet::Parser
include BasicTypes
include CompundTypes
include Tokens
include Keywords
include Control

View File

@ -2,7 +2,7 @@ module Parser
module Expression
include Parslet
rule(:simple_expression) { function_call | integer | string | name }
rule(:value_expression) { function_call | basic_type }
rule(:expression) { (while_do | conditional | operator_expression | function_call ) >> newline }

View File

@ -4,8 +4,8 @@ module Parser
rule(:argument_list) {
left_parenthesis >>
( (simple_expression.as(:argument) >> space? >>
(comma >> space? >> simple_expression.as(:argument)).repeat(0)).repeat(0,1)).as(:argument_list) >>
( (value_expression.as(:argument) >> space? >>
(comma >> space? >> value_expression.as(:argument)).repeat(0)).repeat(0,1)).as(:argument_list) >>
space? >> right_parenthesis
}

View File

@ -23,7 +23,7 @@ module Parser
#infix doing the heavy lifting here,
# is defined as an expressions and array of [atoms,priority,binding] triples
rule(:operator_expression) do infix_expression(simple_expression,
rule(:operator_expression) do infix_expression(value_expression,
[exponent, 120, :left] ,
[multiply, 120, :left] ,
[plus, 110, :left],

View File

@ -8,7 +8,10 @@ module Parser
rule(:right_parenthesis) { str(')') >> space? }
rule(:left_brace) { str('{') >> space? }
rule(:right_brace) { str('}') >> space? }
rule(:left_bracket) { str('[') >> space? }
rule(:right_bracket) { str(']') >> space? }
rule(:association) { str("=>") >> space? }
rule(:comma) { str(',') >> space? }
rule(:colon) { str(':') >> space? }
rule(:semicolon) { str(';') >> space? }

View File

@ -10,6 +10,12 @@ module Parser
rule(:integer => simple(:value)) { Ast::IntegerExpression.new(value.to_i) }
rule(:name => simple(:name)) { Ast::NameExpression.new(name.to_s) }
rule(:array => sequence(:array) ) { Ast::ArrayExpression.new(array) }
rule(:element => simple(:element)) { element }
rule(:hash => sequence(:hash) ) { Ast::HashExpression.new(hash) }
rule(:argument => simple(:argument) , :element => simple(:element)) { Ast::AssociationExpression.new(argument,element) }
rule(:hash_pair => simple(:hash_pair) ) { hash_pair }
rule(:argument => simple(:argument)) { argument }
rule(:argument_list => sequence(:argument_list)) { argument_list }

View File

@ -1,5 +1,6 @@
require_relative "test_basic"
require_relative "test_compund"
require_relative "test_arguments"
require_relative "test_expressions"
require_relative "test_function_call"

View File

@ -0,0 +1,44 @@
require_relative "helper"
class TestCompound < MiniTest::Test
# include the magic (setup and parse -> test method translation), see there
include ParserHelper
def test_one_array
@string_input = '[42]'
@parse_output = {:array=>[{:element=>{:integer=>"42"}}]}
@transform_output = Ast::ArrayExpression.new([Ast::IntegerExpression.new(42)])
@parser = @parser.array
end
def test_array_list
@string_input = '[42, foo]'
@parse_output = {:array=>[{:element=>{:integer=>"42"}}, {:element=>{:name=>"foo"}}]}
@transform_output = Ast::ArrayExpression.new([Ast::IntegerExpression.new(42), Ast::NameExpression.new("foo")])
@parser = @parser.array
end
def test_array_ops
@string_input = '[ 3 + 4 , foo(22) ]'
@parse_output = {:array=>[{:element=>{:l=>{:integer=>"3"}, :o=>"+ ", :r=>{:integer=>"4"}}}, {:element=>{:function_call=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"22"}}]}}]}
@transform_output = Ast::ArrayExpression.new(
[Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),
Ast::FuncallExpression.new("foo", [Ast::IntegerExpression.new(22)] )])
@parser = @parser.array
end
def test_hash
@string_input = '{ foo => 33 }'
@parse_output = {:hash=>[{:hash_pair=>{:argument=>{:name=>"foo"}, :element=>{:integer=>"33"}}}]}
@transform_output = Ast::HashExpression.new([Ast::AssociationExpression.new(Ast::NameExpression.new("foo") , Ast::IntegerExpression.new(33))])
@parser = @parser.hash
end
def test_hash_list
@string_input = "{foo => 33 , bar => 42}"
@parse_output = {:hash=>[{:hash_pair=>{:argument=>{:name=>"foo"}, :element=>{:integer=>"33"}}}, {:hash_pair=>{:argument=>{:name=>"bar"}, :element=>{:integer=>"42"}}}]}
@transform_output = Ast::HashExpression.new([Ast::AssociationExpression.new(Ast::NameExpression.new("foo") , Ast::IntegerExpression.new(33)),Ast::AssociationExpression.new(Ast::NameExpression.new("bar") , Ast::IntegerExpression.new(42))])
@parser = @parser.hash
end
end

View File

@ -1,11 +1,11 @@
def fibonaccit(n)
a = 0
b = 1
while n > 1 do
while( n > 1 ) do
tmp = a
a = b
b = tmp + b
puts b
puts(b)
n = n - 1
end
end