Permalink
Browse files

Keyword messages should take a chains as arguments.

  • Loading branch information...
1 parent 5199c10 commit 9228d2dfdbe0e4315d90d03d72691dfb6680c78f @vic committed Sep 1, 2011
Showing with 151 additions and 41 deletions.
  1. +9 −7 lib/akin/grammar.kpeg
  2. +129 −23 lib/akin/grammar.rb
  3. +2 −1 lib/akin/parser.rb
  4. +9 −8 spec/grammar_spec.rb
  5. +2 −2 spec/shuffle_spec.rb
View
@@ -28,7 +28,7 @@ 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)
+symbol(h) = p:p ":" !&":" value(h.keymsg(true)):v ~n(p, :symbol, v)
regexp = p:p quoted(:text, & "/"):b ~n(p, :regexp, text_node(p, b))
@@ -83,7 +83,9 @@ 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 | symbol(h)
+ | literal | symbol(h)
+ | &{h.keymsg?} name | &{!h.keymsg?} name &!(":")
+ | &{h.keymsg?} operator | &{!h.keymsg?} operator &!(":")
comma_left(h) = block(h):a w "," {a}
@@ -100,7 +102,7 @@ cons(h) = cons_left(h):a - chain_val(h):b ~n(p, :cons, a, b)
args = p:p left_brace:l - (comma(ctx) | block(ctx) | {[]}):a - right_brace(l)
~n(p, l.join, *Array(a))
-msg(h) = kmsg(h) | emsg(h)
+msg(h) = &{h.keymsg?} kmsg(h) | emsg(h)
kmsg(h) = kmsg(h):a sp* (&("::") | ":" &(";"|".")) {a}
| part(h):a w kmsg(h.at?(a.pos)):m ~n(a.pos, :msg, a, *m.args)
@@ -111,10 +113,10 @@ part(h) = part(h):p o w block(h.at?(p.pos)):e { p.args.push *Array(e) ; p }
| p:p keyargs:k ~n(p, k.first, k.last.name, *k.last.args)
| p:p keyword:k ~n(p, k, nil)
-part_head(h) = !&keypart (ph_comma(h) | expr(h) | {[]})
+part_head(h) = !&keypart (ph_comma(h.keymsg(false)) | chain(h.keymsg(false)) | {[]})
-ph_comma(h) = expr(h):a w "," - ph_comma(h):b { b.unshift a ; b }
- | expr(h):a w "," - expr(h):b { [a,b] }
+ph_comma(h) = chain(h):a w "," - ph_comma(h):b { b.unshift a ; b }
+ | chain(h):a w "," - chain(h):b { [a,b] }
emsg(h) = emsg(h):a sp* (&("::") | ":" &(";"|".")) {a}
| (epart(h) | spart(h)):a ~n(a.pos, :msg, a)
@@ -127,7 +129,7 @@ spart(h) = spart(h):p o w block(h.at?(p.pos)):e { p.args.push *Array(e) ; p }
| spart(h):p sp* epart_head(h.at?(p.pos)):e { p.args.push *Array(e) ; p }
| p:p ":" (sp|nl|sheebang) ~n(p, nil, nil)
-epart_head(h) = ph_comma(h) | expr(h) | {[]}
+epart_head(h) = ph_comma(h) | chain(h.keymsg(false)) | {[]}
expr(h) = value(h):e &{ e.pos.column > h.pos.column } {e}
View
@@ -751,7 +751,7 @@ def _literal
return _tmp
end
- # symbol = p:p ":" !(&":") value(h):v {n(p, :symbol, v)}
+ # symbol = p:p ":" !(&":") value(h.keymsg(true)):v {n(p, :symbol, v)}
def _symbol(h)
_save = self.pos
@@ -777,7 +777,7 @@ def _symbol(h)
self.pos = _save
break
end
- _tmp = apply_with_args(:_value, h)
+ _tmp = apply_with_args(:_value, h.keymsg(true))
v = @result
unless _tmp
self.pos = _save
@@ -2554,7 +2554,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 | symbol(h))
+ # 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 | symbol(h) | &{h.keymsg?} name | &{!h.keymsg?} name &(!":") | &{h.keymsg?} operator | &{!h.keymsg?} operator &(!":"))
def _value(h)
_save = self.pos
@@ -2609,13 +2609,103 @@ def _value(h)
_tmp = apply(:_literal)
break if _tmp
self.pos = _save
- _tmp = apply(:_operator)
+ _tmp = apply_with_args(:_symbol, h)
break if _tmp
self.pos = _save
- _tmp = apply(:_name)
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = begin; h.keymsg?; end
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_name)
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
break if _tmp
self.pos = _save
- _tmp = apply_with_args(:_symbol, h)
+
+ _save5 = self.pos
+ while true # sequence
+ _save6 = self.pos
+ _tmp = begin; !h.keymsg?; end
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_name)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save7 = self.pos
+ _save8 = self.pos
+ _tmp = match_string(":")
+ _tmp = _tmp ? nil : true
+ self.pos = _save8
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+
+ _save9 = self.pos
+ while true # sequence
+ _save10 = self.pos
+ _tmp = begin; h.keymsg?; end
+ self.pos = _save10
+ unless _tmp
+ self.pos = _save9
+ break
+ end
+ _tmp = apply(:_operator)
+ unless _tmp
+ self.pos = _save9
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+
+ _save11 = self.pos
+ while true # sequence
+ _save12 = self.pos
+ _tmp = begin; !h.keymsg?; end
+ self.pos = _save12
+ unless _tmp
+ self.pos = _save11
+ break
+ end
+ _tmp = apply(:_operator)
+ unless _tmp
+ self.pos = _save11
+ break
+ end
+ _save13 = self.pos
+ _save14 = self.pos
+ _tmp = match_string(":")
+ _tmp = _tmp ? nil : true
+ self.pos = _save14
+ self.pos = _save13
+ unless _tmp
+ self.pos = _save11
+ end
+ break
+ end # end sequence
+
break if _tmp
self.pos = _save
break
@@ -2974,12 +3064,28 @@ def _args
return _tmp
end
- # msg = (kmsg(h) | emsg(h))
+ # msg = (&{h.keymsg?} kmsg(h) | emsg(h))
def _msg(h)
_save = self.pos
while true # choice
- _tmp = apply_with_args(:_kmsg, h)
+
+ _save1 = self.pos
+ while true # sequence
+ _save2 = self.pos
+ _tmp = begin; h.keymsg?; end
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ _tmp = apply_with_args(:_kmsg, h)
+ unless _tmp
+ self.pos = _save1
+ end
+ break
+ end # end sequence
+
break if _tmp
self.pos = _save
_tmp = apply_with_args(:_emsg, h)
@@ -3263,7 +3369,7 @@ def _part(h)
return _tmp
end
- # part_head = !(&keypart) (ph_comma(h) | expr(h) | {[]})
+ # part_head = !(&keypart) (ph_comma(h.keymsg(false)) | chain(h.keymsg(false)) | {[]})
def _part_head(h)
_save = self.pos
@@ -3281,10 +3387,10 @@ def _part_head(h)
_save3 = self.pos
while true # choice
- _tmp = apply_with_args(:_ph_comma, h)
+ _tmp = apply_with_args(:_ph_comma, h.keymsg(false))
break if _tmp
self.pos = _save3
- _tmp = apply_with_args(:_expr, h)
+ _tmp = apply_with_args(:_chain, h.keymsg(false))
break if _tmp
self.pos = _save3
@result = begin; []; end
@@ -3304,15 +3410,15 @@ def _part_head(h)
return _tmp
end
- # ph_comma = (expr(h):a w "," - ph_comma(h):b { b.unshift a ; b } | expr(h):a w "," - expr(h):b { [a,b] })
+ # ph_comma = (chain(h):a w "," - ph_comma(h):b { b.unshift a ; b } | chain(h):a w "," - chain(h):b { [a,b] })
def _ph_comma(h)
_save = self.pos
while true # choice
_save1 = self.pos
while true # sequence
- _tmp = apply_with_args(:_expr, h)
+ _tmp = apply_with_args(:_chain, h)
a = @result
unless _tmp
self.pos = _save1
@@ -3352,7 +3458,7 @@ def _ph_comma(h)
_save2 = self.pos
while true # sequence
- _tmp = apply_with_args(:_expr, h)
+ _tmp = apply_with_args(:_chain, h)
a = @result
unless _tmp
self.pos = _save2
@@ -3373,7 +3479,7 @@ def _ph_comma(h)
self.pos = _save2
break
end
- _tmp = apply_with_args(:_expr, h)
+ _tmp = apply_with_args(:_chain, h)
b = @result
unless _tmp
self.pos = _save2
@@ -3756,15 +3862,15 @@ def _spart(h)
return _tmp
end
- # epart_head = (ph_comma(h) | expr(h) | {[]})
+ # epart_head = (ph_comma(h) | chain(h.keymsg(false)) | {[]})
def _epart_head(h)
_save = self.pos
while true # choice
_tmp = apply_with_args(:_ph_comma, h)
break if _tmp
self.pos = _save
- _tmp = apply_with_args(:_expr, h)
+ _tmp = apply_with_args(:_chain, h.keymsg(false))
break if _tmp
self.pos = _save
@result = begin; []; end
@@ -5092,7 +5198,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[:_symbol] = rule_info("symbol", "p:p \":\" !(&\":\") value(h.keymsg(true)):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)}")
@@ -5120,22 +5226,22 @@ def _eof
Rules[:_keyword] = rule_info("keyword", "< (!(&(n | \":\" | brace)) .)+ > \":\" !(&(\":\" | \";\" | \".\")) {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 | symbol(h))")
+ 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 | symbol(h) | &{h.keymsg?} name | &{!h.keymsg?} name &(!\":\") | &{h.keymsg?} operator | &{!h.keymsg?} operator &(!\":\"))")
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)}")
Rules[:_cons_left] = rule_info("cons_left", "expr(h):a sp* \"::\" !(&(\":\" | \";\" | \".\")) {a}")
Rules[:_cons] = rule_info("cons", "cons_left(h):a - chain_val(h):b {n(p, :cons, a, b)}")
Rules[:_args] = rule_info("args", "p:p left_brace:l - (comma(ctx) | block(ctx) | {[]}):a - right_brace(l) {n(p, l.join, *Array(a))}")
- Rules[:_msg] = rule_info("msg", "(kmsg(h) | emsg(h))")
+ Rules[:_msg] = rule_info("msg", "(&{h.keymsg?} kmsg(h) | emsg(h))")
Rules[:_kmsg] = rule_info("kmsg", "(kmsg(h):a sp* (&\"::\" | \":\" &(\";\" | \".\")) {a} | part(h):a w kmsg(h.at?(a.pos)):m {n(a.pos, :msg, a, *m.args)} | part(h):a {n(a.pos, :msg, a)})")
Rules[:_part] = rule_info("part", "(part(h):p o w block(h.at?(p.pos)):e { p.args.push *Array(e) ; p } | part(h):p sp+ part_head(h.at?(p.pos)):e { p.args.push *Array(e) ; p } | p:p keyargs:k {n(p, k.first, k.last.name, *k.last.args)} | p:p keyword:k {n(p, k, nil)})")
- Rules[:_part_head] = rule_info("part_head", "!(&keypart) (ph_comma(h) | expr(h) | {[]})")
- Rules[:_ph_comma] = rule_info("ph_comma", "(expr(h):a w \",\" - ph_comma(h):b { b.unshift a ; b } | expr(h):a w \",\" - expr(h):b { [a,b] })")
+ Rules[:_part_head] = rule_info("part_head", "!(&keypart) (ph_comma(h.keymsg(false)) | chain(h.keymsg(false)) | {[]})")
+ Rules[:_ph_comma] = rule_info("ph_comma", "(chain(h):a w \",\" - ph_comma(h):b { b.unshift a ; b } | chain(h):a w \",\" - chain(h):b { [a,b] })")
Rules[:_emsg] = rule_info("emsg", "(emsg(h):a sp* (&\"::\" | \":\" &(\";\" | \".\")) {a} | (epart(h) | spart(h)):a {n(a.pos, :msg, a)})")
Rules[:_epart] = rule_info("epart", "(epart(h):p o w block(h.at?(p.pos)):e { p.args.push *Array(e) ; p } | epart(h):p sp+ epart_head(h.at?(p.pos)):e { p.args.push *Array(e) ; p } | args:a \":\" !(&\":\") {n(a.pos, nil, a.name, *a.args)})")
Rules[:_spart] = rule_info("spart", "(spart(h):p o w block(h.at?(p.pos)):e { p.args.push *Array(e) ; p } | spart(h):p sp* epart_head(h.at?(p.pos)):e { p.args.push *Array(e) ; p } | p:p \":\" (sp | nl | sheebang) {n(p, nil, nil)})")
- Rules[:_epart_head] = rule_info("epart_head", "(ph_comma(h) | expr(h) | {[]})")
+ Rules[:_epart_head] = rule_info("epart_head", "(ph_comma(h) | chain(h.keymsg(false)) | {[]})")
Rules[:_expr] = rule_info("expr", "value(h):e &{ e.pos.column > h.pos.column } {e}")
Rules[:_chain] = rule_info("chain", "(chain(h):a w \".\" - chain(h):b {chain_cont(a, b)} | operator:a !(&brace) o w chain(h):b {n(a.pos, :chain, a, *Array(b.name == :chain && b.args || b))} | chain_val(h):a sp* chain(h.at(a.pos)):b {chain_cont(a, b)} | chain_val(h))")
Rules[:_chain_val] = rule_info("chain_val", "(cons(h) | expr(h))")
View
@@ -38,7 +38,8 @@ class Context < Struct.new(:pos)
def self.attr(name, val = true)
module_eval "
#{"def"} #{name}?
- !!(@#{name} ||= #{val})
+ @#{name} = #{val} if @#{name}.nil?
+ @#{name}
end
#{"def"} #{name}!
@#{name} = !#{name}?
View
@@ -327,7 +327,8 @@
code = "a b: c :: d"
s(code, :root).should ==
[:chain, [:name, "a"],
- [:cons, [:msg, ["b", nil, [:name, "c"]]], [:name, "d"]]]
+ [:msg, ["b", nil,
+ [:cons, [:name, "c"], [:name, "d"]]]]]
end
end
@@ -607,9 +608,9 @@
s(code, :root).should ==
[:msg,
["foo", nil,
- [:symbol, [:name, "bar"]],
- [:symbol,
- [:msg, ["baz", nil, [:symbol, [:name, "bat"]]]]]]]
+ [:chain, [:symbol, [:name, "bar"]],
+ [:symbol,
+ [:msg, ["baz", nil, [:symbol, [:name, "bat"]]]]]]]]
end
it 'flattens message chain' do
@@ -646,17 +647,17 @@
[:chain,
[:name, "foo"],
[:msg, [nil, nil,
- [:name, "bar"],
- [:msg, [nil, nil, [:name, "baz"]]]]]]
+ [:chain, [:name, "bar"],
+ [:msg, [nil, nil, [:name, "baz"]]]]]]]
end
it 'parses an empty keyword message' do
s('foo : bar baz: bat', :root).should ==
[:chain,
[:name, "foo"],
[:msg, [nil, nil,
- [:name, "bar"],
- [:msg, ["baz", nil, [:name, "bat"]]]]]]
+ [:chain, [:name, "bar"],
+ [:msg, ["baz", nil, [:name, "bat"]]]]]]]
end
it 'parses an empty keyword message' do
View
@@ -191,9 +191,9 @@
[:act, "+", nil, [:name, "c"]]]]]
end
- it 'shuffles chain inside keyword arg', :pending => true do
+ it 'shuffles chain inside keyword arg' do
n('a: b + c').should ==
- [:msg, ["a", "()",
+ [:msg, ["a", nil,
[:chain, [:name, "b"],
[:act, "+", nil, [:name, "c"]]]]]
end

0 comments on commit 9228d2d

Please sign in to comment.