a good stab at array anf hash constants
This commit is contained in:
parent
25a7c3ea68
commit
fdb5dd4f67
39
lib/ast/compound_expressions.rb
Normal file
39
lib/ast/compound_expressions.rb
Normal 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
|
@ -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"
|
||||
|
@ -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
|
20
lib/parser/compound_types.rb
Normal file
20
lib/parser/compound_types.rb
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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],
|
||||
|
@ -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? }
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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"
|
||||
|
44
test/parser/test_compound.rb
Normal file
44
test/parser/test_compound.rb
Normal 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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user