Permalink
Browse files

Added symbols syntax.

  • Loading branch information...
1 parent fcd4e15 commit 582d24c22bf2fec9c9a6470020df45f23d215db6 @vic committed Aug 23, 2011
Showing with 86 additions and 3 deletions.
  1. +3 −1 lib/akin/grammar.kpeg
  2. +40 −2 lib/akin/grammar.rb
  3. +43 −0 spec/grammar_spec.rb
View
@@ -28,6 +28,8 @@ right_brace(l) = <brace:b> &{ text == l.last } { l }
literal = float | fixnum | str | regexp
+symbol(h) = p:p ":" value(h):v ~n(p, :symbol, v)
+
regexp = p:p quoted(:text, & "/"):b ~n(p, :regexp, text_node(p, b))
float = p:p sign:s dec:n "." dec:f ~n(p, :float, (s+n+"."+f).to_f)
@@ -79,7 +81,7 @@ keypart = keyword | keyargs
value(h) = msg(h)
| value(h):v args:a ~n(v.pos, :act, v, a.name, *a.args)
| args:a ~n(a.pos, :act, nil, a.name, *a.args)
- | literal | operator | name
+ | literal | operator | name | symbol(h)
comma_left(h) = block(h):a w "," {a}
View
@@ -751,6 +751,40 @@ def _literal
return _tmp
end
+ # symbol = p:p ":" value(h):v {n(p, :symbol, v)}
+ def _symbol(h)
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_p)
+ p = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(":")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply_with_args(:_value, h)
+ v = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; n(p, :symbol, v); end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_symbol unless _tmp
+ return _tmp
+ end
+
# regexp = p:p quoted(:text, &"/"):b {n(p, :regexp, text_node(p, b))}
def _regexp
@@ -2411,7 +2445,7 @@ def _keypart
return _tmp
end
- # value = (msg(h) | value(h):v args:a {n(v.pos, :act, v, a.name, *a.args)} | args:a {n(a.pos, :act, nil, a.name, *a.args)} | literal | operator | name)
+ # value = (msg(h) | value(h):v args:a {n(v.pos, :act, v, a.name, *a.args)} | args:a {n(a.pos, :act, nil, a.name, *a.args)} | literal | operator | name | symbol(h))
def _value(h)
_save = self.pos
@@ -2472,6 +2506,9 @@ def _value(h)
_tmp = apply(:_name)
break if _tmp
self.pos = _save
+ _tmp = apply_with_args(:_symbol, h)
+ break if _tmp
+ self.pos = _save
break
end # end choice
@@ -3705,6 +3742,7 @@ def _eof
Rules[:_left_brace] = rule_info("left_brace", "< brace:b > &{ text == b.first} { b }")
Rules[:_right_brace] = rule_info("right_brace", "< brace:b > &{ text == l.last } { l }")
Rules[:_literal] = rule_info("literal", "(float | fixnum | str | regexp)")
+ Rules[:_symbol] = rule_info("symbol", "p:p \":\" value(h):v {n(p, :symbol, v)}")
Rules[:_regexp] = rule_info("regexp", "p:p quoted(:text, &\"/\"):b {n(p, :regexp, text_node(p, b))}")
Rules[:_float] = rule_info("float", "p:p sign:s dec:n \".\" dec:f {n(p, :float, (s+n+\".\"+f).to_f)}")
Rules[:_fixnum] = rule_info("fixnum", "p:p (hexadec | binary | octal | decimal):n {n(p, :fixnum, n)}")
@@ -3732,7 +3770,7 @@ def _eof
Rules[:_keyword] = rule_info("keyword", "< (!(&(n | \":\" | brace)) .)+ > \":\" &{text.size > 0} !(&(\":\" | \";\" | \".\")) {text}")
Rules[:_keyargs] = rule_info("keyargs", "< (!(&(n | \":\" | brace)) .)+ > args:a \":\" {[text, a]}")
Rules[:_keypart] = rule_info("keypart", "(keyword | keyargs)")
- Rules[:_value] = rule_info("value", "(msg(h) | value(h):v args:a {n(v.pos, :act, v, a.name, *a.args)} | args:a {n(a.pos, :act, nil, a.name, *a.args)} | literal | operator | name)")
+ Rules[:_value] = rule_info("value", "(msg(h) | value(h):v args:a {n(v.pos, :act, v, a.name, *a.args)} | args:a {n(a.pos, :act, nil, a.name, *a.args)} | literal | operator | name | symbol(h))")
Rules[:_comma_left] = rule_info("comma_left", "block(h):a w \",\" {a}")
Rules[:_comma] = rule_info("comma", "(comma_left(h):a w comma(h):b { b.unshift a ; b } | comma_left(h):a w block(h):b { [a,b] } | comma_left(h):a &(sp* (\".\" | \",\" | t | brace)) {[a]})")
Rules[:_tuple] = rule_info("tuple", "comma(h):c {n(p, :tuple, *c)}")
View
@@ -23,6 +23,26 @@
end
end
+ describe 'symbol'do
+ it 'starts with a semicolon char' do
+ s(':foo', :symbol).should == [:symbol, [:name, "foo"]]
+ end
+
+ it 'can be an string' do
+ s(':"foo"', :symbol).should == [:symbol, [:text, "foo"]]
+ end
+
+ it 'can be a number' do
+ s(':22', :symbol).should == [:symbol, [:fixnum, 22]]
+ end
+
+ it 'can be an activation' do
+ s(':(a, b)', :symbol).should == [:symbol, [:act, nil, "()",
+ [:name, "a"],
+ [:name, "b"]]]
+ end
+ end
+
describe 'cons' do
it 'parses a cons of two values' do
s('a :: b', :cons).should == [:cons, [:name, "a"], [:name, "b"]]
@@ -611,5 +631,28 @@
[:name, "a"],
[:act, [:name, "foo"], "{}", [:name, "bar"], [:name, "baz"], [:name, "bat"]]]
end
+
+ it 'doesnt confuse symbols with keyword messages' do
+ code = <<-CODE
+ foo: :bar baz: :bat
+ CODE
+ s(code, :root).should ==
+ [:msg,
+ ["foo", nil, [:symbol, [:name, "bar"]]],
+ ["baz", nil, [:symbol, [:name, "bat"]]]]
+ end
+
+ it 'allows a symbol to be made of a keyword send' do
+ code = <<-CODE
+ foo: :bar :baz: :bat
+ CODE
+ s(code, :root).should ==
+ [:msg,
+ ["foo", nil,
+ [:symbol, [:name, "bar"]],
+ [:symbol,
+ [:msg, ["baz", nil, [:symbol, [:name, "bat"]]]]]]]
+ end
+
end
end

0 comments on commit 582d24c

Please sign in to comment.