add module names and instance variables as parse rules

This commit is contained in:
Torsten Ruger 2014-05-30 12:06:42 +03:00
parent 3e93517986
commit f03d445f3d
4 changed files with 42 additions and 1 deletions

View File

@ -42,6 +42,11 @@ module Ast
end end
end end
class VariableExpression < NameExpression
end
class ModuleName < NameExpression
end
class StringExpression < Expression class StringExpression < Expression
attr_reader :string attr_reader :string
def initialize str def initialize str

View File

@ -25,7 +25,13 @@ module Parser
rule(:exponent) { (str('e')| str('E')) } rule(:exponent) { (str('e')| str('E')) }
# identifier must start with lower case # identifier must start with lower case
rule(:name) { keyword.absent? >> (match['a-z'] >> match['a-zA-Z0-9'].repeat).as(:name) >> space? } # TODO rule forbit names like if_true, because it starts with a keyword. a little looser please!
rule(:name) { keyword.absent? >> (match['a-z_'] >> match['a-zA-Z0-9_'].repeat).as(:name) >> space? }
# instance variables must have the @
rule(:instance_variable) { (match('@') >> name).as(:instance_variable) }
# and class/module names must start with capital
# (admittatly the rule matches constants too, but one step at a time)
rule(:module_name) { keyword.absent? >> (match['A-Z'] >> match['a-zA-Z0-9_'].repeat).as(:module_name) >> space? }
rule(:escape) { str('\\') >> any.as(:esc) } rule(:escape) { str('\\') >> any.as(:esc) }
rule(:string) { quote >> ( rule(:string) { quote >> (

View File

@ -9,6 +9,8 @@ module Parser
rule(:integer => simple(:value)) { Ast::IntegerExpression.new(value.to_i) } rule(:integer => simple(:value)) { Ast::IntegerExpression.new(value.to_i) }
rule(:name => simple(:name)) { Ast::NameExpression.new(name.to_s) } rule(:name => simple(:name)) { Ast::NameExpression.new(name.to_s) }
rule(:instance_variable => simple(:instance_variable)) { Ast::VariableExpression.new(instance_variable.name) }
rule(:module_name => simple(:module_name)) { Ast::ModuleName.new(module_name.to_s) }
rule(:array_constant => sequence(:array_constant) ) { Ast::ArrayExpression.new(array_constant) } rule(:array_constant => sequence(:array_constant) ) { Ast::ArrayExpression.new(array_constant) }
rule(:array_element => simple(:array_element)) { array_element } rule(:array_element => simple(:array_element)) { array_element }

View File

@ -18,6 +18,34 @@ class TestBasic < MiniTest::Test
@parser = @parser.name @parser = @parser.name
end end
def test_name_underscode_start
@string_input = '_bar '
@parse_output = {:name => '_bar'}
@transform_output = Ast::NameExpression.new('_bar')
@parser = @parser.name
end
def test_name_underscode_middle
@string_input = 'foo_bar '
@parse_output = {:name => 'foo_bar'}
@transform_output = Ast::NameExpression.new('foo_bar')
@parser = @parser.name
end
def test_instance_variable
@string_input = '@foo_bar '
@parse_output = {:instance_variable=>{:name=>"foo_bar"}}
@transform_output = Ast::VariableExpression.new('foo_bar')
@parser = @parser.instance_variable
end
def test_module_name
@string_input = 'FooBar '
@parse_output = {:module_name=>"FooBar"}
@transform_output = Ast::ModuleName.new("FooBar")
@parser = @parser.module_name
end
def test_comment def test_comment
out = "# i am a comment \n" out = "# i am a comment \n"
@string_input = out.dup #NEEDS the return, which is what delimits the comment @string_input = out.dup #NEEDS the return, which is what delimits the comment