Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Improved whitespace handling in comma and message rules.

  • Loading branch information...
commit cffd4eda1c5a6bcda05cecd00f81ee440a2cc1a1 1 parent c293fc5
@vic authored
Showing with 226 additions and 92 deletions.
  1. +12 −9 lib/akin/grammar.kpeg
  2. +176 −82 lib/akin/grammar.rb
  3. +38 −1 spec/grammar_spec.rb
View
21 lib/akin/grammar.kpeg
@@ -14,7 +14,9 @@ p = &. ~current_position
sheebang = "#!" /.*?$/
-t = sheebang | nl | ";"
+w = (sp | sheebang | nl)*
+o = sp* (sheebang | nl)
+t = ";" | sheebang | nl
n = t | sp | "."
- = n*
@@ -77,10 +79,11 @@ value(h) = msg(h)
| args:a ~n(a.pos, :act, nil, a.name, *a.args)
| literal | operator | name
-comma_left(h) = block(h):a sp* "," {a}
+comma_left(h) = block(h):a w "," {a}
-comma(h) = comma_left(h):a - comma(h):b { b.unshift a ; b }
- | comma_left(h):a - block(h):b { [a,b] }
+comma(h) = 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]}
tuple(h) = comma(h):c ~n(p, :tuple, *c)
@@ -93,24 +96,24 @@ args = p:p left_brace:l - (comma(h) | block(h) | {[]}):a - right_brace(l)
~n(p, l.join, *Array(a))
msg(h) = msg(h):a sp* ":" &(":"|";"|".") {a}
- | part(h):a - msg(h | a.pos):m ~n(a.pos, :msg, a, *m.args)
+ | part(h):a w msg(h | a.pos):m ~n(a.pos, :msg, a, *m.args)
| part(h):a ~n(a.pos, :msg, a)
-part(h) = part(h):p sp* t - block(h | p.pos):e { p.args.push *Array(e) ; p }
+part(h) = part(h):p o w block(h | p.pos):e { p.args.push *Array(e) ; p }
| part(h):p part_head(h | p.pos):e { p.args.push *Array(e) ; p }
| p:p keyword:k args:a ~n(p, k, a.name, *a.args)
| p:p keyword:k ~n(p, k, "()")
part_head(h) = sp+ !&keyword (ph_comma(h) | expr(h) | {[]})
-ph_comma(h) = expr(h):a sp* "," - ph_comma(h):b { b.unshift a ; b }
- | expr(h):a sp* "," - expr(h):b { [a,b] }
+ph_comma(h) = expr(h):a w "," - ph_comma(h):b { b.unshift a ; b }
+ | expr(h):a w "," - expr(h):b { [a,b] }
expr(h) = value(h):e &{ e.pos.column > h.column } {e}
chain(h) = chain(h):a sp* "." - chain(h)?:b
{ b && n(a.pos, :chain, a, b) || a }
- | operator:a !&brace sp* t - chain(h):b
+ | operator:a !&brace o w chain(h):b
~n(a.pos, :chain, a, *Array(b.name == :chain && b.args || b))
| chain_cont(h)
| expr(h):a sp* chain(a.pos):b
View
258 lib/akin/grammar.rb
@@ -461,18 +461,79 @@ def _sheebang
set_failed_rule :_sheebang unless _tmp
return _tmp
end
-
+
+ # w = (sp | sheebang | nl)*
+ def _w
+ while true
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_sp)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_sheebang)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_nl)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ set_failed_rule :_w unless _tmp
+ return _tmp
+ end
+
+ # o = sp* (sheebang | nl)
+ def _o
+
+ _save = self.pos
+ while true # sequence
+ while true
+ _tmp = apply(:_sp)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_sheebang)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_nl)
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_o unless _tmp
+ return _tmp
+ end
+
# t = (";" | sheebang | nl)
def _t
_save = self.pos
- while true # choice
+ while true # choice
_tmp = match_string(";")
break if _tmp
- self.pos = _save
+ self.pos = _save
_tmp = apply(:_sheebang)
break if _tmp
- self.pos = _save
+ self.pos = _save
_tmp = apply(:_nl)
break if _tmp
self.pos = _save
@@ -2287,7 +2348,7 @@ def _value(h)
set_failed_rule :_value unless _tmp
return _tmp
end
-
+
# comma_left = block(h):a w "," {a}
def _comma_left(h)
@@ -2298,11 +2359,7 @@ def _comma_left(h)
unless _tmp
self.pos = _save
break
- end
- while true
- _tmp = apply(:_sp)
- break unless _tmp
- end
+ end
_tmp = apply(:_w)
unless _tmp
self.pos = _save
@@ -2324,7 +2381,7 @@ def _comma_left(h)
set_failed_rule :_comma_left unless _tmp
return _tmp
end
-
+
# 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]})
def _comma(h)
@@ -2338,7 +2395,7 @@ def _comma(h)
unless _tmp
self.pos = _save1
break
- end
+ end
_tmp = apply(:_w)
unless _tmp
self.pos = _save1
@@ -2368,7 +2425,7 @@ def _comma(h)
unless _tmp
self.pos = _save2
break
- end
+ end
_tmp = apply(:_w)
unless _tmp
self.pos = _save2
@@ -2389,6 +2446,67 @@ def _comma(h)
end # end sequence
break if _tmp
+ self.pos = _save
+
+ _save3 = self.pos
+ while true # sequence
+ _tmp = apply_with_args(:_comma_left, h)
+ a = @result
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _save4 = self.pos
+
+ _save5 = self.pos
+ while true # sequence
+ while true
+ _tmp = apply(:_sp)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+
+ _save7 = self.pos
+ while true # choice
+ _tmp = match_string(".")
+ break if _tmp
+ self.pos = _save7
+ _tmp = match_string(",")
+ break if _tmp
+ self.pos = _save7
+ _tmp = apply(:_t)
+ break if _tmp
+ self.pos = _save7
+ _tmp = apply(:_brace)
+ break if _tmp
+ self.pos = _save7
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ @result = begin; [a]; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
self.pos = _save
break
end # end choice
@@ -2617,7 +2735,7 @@ def _args
set_failed_rule :_args unless _tmp
return _tmp
end
-
+
# msg = (msg(h):a sp* ":" &(":" | ";" | ".") {a} | part(h):a w msg(h | a.pos):m {n(a.pos, :msg, a, *m.args)} | part(h):a {n(a.pos, :msg, a)})
def _msg(h)
@@ -2685,7 +2803,7 @@ def _msg(h)
unless _tmp
self.pos = _save5
break
- end
+ end
_tmp = apply(:_w)
unless _tmp
self.pos = _save5
@@ -2732,7 +2850,7 @@ def _msg(h)
set_failed_rule :_msg unless _tmp
return _tmp
end
-
+
# part = (part(h):p o w block(h | p.pos):e { p.args.push *Array(e) ; p } | part(h):p part_head(h | p.pos):e { p.args.push *Array(e) ; p } | p:p keyword:k args:a {n(p, k, a.name, *a.args)} | p:p keyword:k {n(p, k, "()")})
def _part(h)
@@ -2746,21 +2864,12 @@ def _part(h)
unless _tmp
self.pos = _save1
break
- end
- while true
- _tmp = apply(:_sp)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save1
- break
- end
+ end
_tmp = apply(:_o)
unless _tmp
self.pos = _save1
break
- end
+ end
_tmp = apply(:_w)
unless _tmp
self.pos = _save1
@@ -2782,24 +2891,24 @@ def _part(h)
break if _tmp
self.pos = _save
-
+
_save2 = self.pos
while true # sequence
_tmp = apply_with_args(:_part, h)
p = @result
- unless _tmp
+ unless _tmp
self.pos = _save2
break
end
_tmp = apply_with_args(:_part_head, h | p.pos)
e = @result
- unless _tmp
+ unless _tmp
self.pos = _save2
break
end
@result = begin; p.args.push *Array(e) ; p ; end
_tmp = true
- unless _tmp
+ unless _tmp
self.pos = _save2
end
break
@@ -2807,30 +2916,30 @@ def _part(h)
break if _tmp
self.pos = _save
-
+
_save3 = self.pos
while true # sequence
_tmp = apply(:_p)
p = @result
- unless _tmp
+ unless _tmp
self.pos = _save3
break
end
_tmp = apply(:_keyword)
k = @result
- unless _tmp
+ unless _tmp
self.pos = _save3
break
end
_tmp = apply(:_args)
a = @result
- unless _tmp
+ unless _tmp
self.pos = _save3
break
end
@result = begin; n(p, k, a.name, *a.args); end
_tmp = true
- unless _tmp
+ unless _tmp
self.pos = _save3
end
break
@@ -2838,24 +2947,24 @@ def _part(h)
break if _tmp
self.pos = _save
-
+
_save4 = self.pos
while true # sequence
_tmp = apply(:_p)
p = @result
- unless _tmp
+ unless _tmp
self.pos = _save4
break
end
_tmp = apply(:_keyword)
k = @result
- unless _tmp
+ unless _tmp
self.pos = _save4
break
end
@result = begin; n(p, k, "()"); end
_tmp = true
- unless _tmp
+ unless _tmp
self.pos = _save4
end
break
@@ -2925,7 +3034,7 @@ def _part_head(h)
set_failed_rule :_part_head unless _tmp
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] })
def _ph_comma(h)
@@ -2939,11 +3048,7 @@ def _ph_comma(h)
unless _tmp
self.pos = _save1
break
- end
- while true
- _tmp = apply(:_sp)
- break unless _tmp
- end
+ end
_tmp = apply(:_w)
unless _tmp
self.pos = _save1
@@ -2975,43 +3080,39 @@ def _ph_comma(h)
break if _tmp
self.pos = _save
-
+
_save2 = self.pos
while true # sequence
_tmp = apply_with_args(:_expr, h)
a = @result
- unless _tmp
+ unless _tmp
self.pos = _save2
break
- end
- while true
- _tmp = apply(:_sp)
- break unless _tmp
- end
+ end
_tmp = apply(:_w)
- unless _tmp
+ unless _tmp
self.pos = _save2
break
end
_tmp = match_string(",")
- unless _tmp
+ unless _tmp
self.pos = _save2
break
end
_tmp = apply(:__hyphen_)
- unless _tmp
+ unless _tmp
self.pos = _save2
break
end
_tmp = apply_with_args(:_expr, h)
b = @result
- unless _tmp
+ unless _tmp
self.pos = _save2
break
end
@result = begin; [a,b] ; end
_tmp = true
- unless _tmp
+ unless _tmp
self.pos = _save2
end
break
@@ -3055,7 +3156,7 @@ def _expr(h)
set_failed_rule :_expr unless _tmp
return _tmp
end
-
+
# chain = (chain(h):a sp* "." - chain(h)?:b { b && n(a.pos, :chain, a, b) || a } | operator:a !(&brace) o w chain(h):b {n(a.pos, :chain, a, *Array(b.name == :chain && b.args || b))} | chain_cont(h) | expr(h):a sp* chain(a.pos):b {n(a.pos, :chain, a, *Array(b.name == :chain && b.args || b))} | chain_val(h))
def _chain(h)
@@ -3129,21 +3230,12 @@ def _chain(h)
unless _tmp
self.pos = _save4
break
- end
- while true
- _tmp = apply(:_sp)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save4
- break
- end
+ end
_tmp = apply(:_o)
unless _tmp
self.pos = _save4
break
- end
+ end
_tmp = apply(:_w)
unless _tmp
self.pos = _save4
@@ -3168,12 +3260,12 @@ def _chain(h)
_tmp = apply_with_args(:_chain_cont, h)
break if _tmp
self.pos = _save
-
+
_save7 = self.pos
while true # sequence
_tmp = apply_with_args(:_expr, h)
a = @result
- unless _tmp
+ unless _tmp
self.pos = _save7
break
end
@@ -3182,19 +3274,19 @@ def _chain(h)
break unless _tmp
end
_tmp = true
- unless _tmp
+ unless _tmp
self.pos = _save7
break
end
_tmp = apply_with_args(:_chain, a.pos)
b = @result
- unless _tmp
+ unless _tmp
self.pos = _save7
break
end
@result = begin; n(a.pos, :chain, a, *Array(b.name == :chain && b.args || b)); end
_tmp = true
- unless _tmp
+ unless _tmp
self.pos = _save7
end
break
@@ -3467,7 +3559,9 @@ def _eof
Rules[:_nl] = rule_info("nl", "(\"\\n\" | \"
\\n\")")
Rules[:_sp] = rule_info("sp", "(\" \" | \"\\t\" | \"\\\\\" nl)")
- Rules[:_p] = rule_info("p", "&. {current_position}")
+ Rules[:_p] = rule_info("p", "&. {current_position}")
+ Rules[:_sheebang] = rule_info("sheebang", "\"\#!\" /.*?$/")
+ Rules[:_w] = rule_info("w", "(sp | sheebang | nl)*")
Rules[:_o] = rule_info("o", "sp* (sheebang | nl)")
Rules[:_t] = rule_info("t", "(\";\" | sheebang | nl)")
Rules[:_n] = rule_info("n", "(t | sp | \".\")")
@@ -3500,18 +3594,18 @@ def _eof
Rules[:_oper] = rule_info("oper", "< opchr (opchr | /[=]/)* > {text}")
Rules[:_operator] = rule_info("operator", "p:p oper:o {n(p, :oper, o)}")
Rules[:_name] = rule_info("name", "p:p < (&(!(sp | nl | brace | opchr | \":\" | \";\" | \",\" | \".\")) .)+ > {n(p, :name, text)}")
- Rules[:_keyword] = rule_info("keyword", "\":\" < (!(&(n | \":\" | brace)) .)+ > !(&(\":\" | \";\" | \".\")) &{text.size > 0} {text}")
- 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[:_keyword] = rule_info("keyword", "\":\" < (!(&(n | \":\" | brace)) .)+ > !(&(\":\" | \";\" | \".\")) &{text.size > 0} {text}")
+ 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[:_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 - cons(h):b {n(p, :cons, a, b)} | cons_left(h):a - expr(h):b {n(p, :cons, a, b)})")
- Rules[:_args] = rule_info("args", "p:p left_brace:l - (comma(h) | block(h) | {[]}):a - right_brace(l) {n(p, l.join, *Array(a))}")
+ Rules[:_cons] = rule_info("cons", "(cons_left(h):a - cons(h):b {n(p, :cons, a, b)} | cons_left(h):a - expr(h):b {n(p, :cons, a, b)})")
+ Rules[:_args] = rule_info("args", "p:p left_brace:l - (comma(h) | block(h) | {[]}):a - right_brace(l) {n(p, l.join, *Array(a))}")
Rules[:_msg] = rule_info("msg", "(msg(h):a sp* \":\" &(\":\" | \";\" | \".\") {a} | part(h):a w msg(h | 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 sp* t - block(h | p.pos):e { p.args.push *Array(e) ; p } | part(h):p part_head(h | p.pos):e { p.args.push *Array(e) ; p } | p:p keyword:k args:a {n(p, k, a.name, *a.args)} | p:p keyword:k {n(p, k, \"()\")})")
+ Rules[:_part] = rule_info("part", "(part(h):p o w block(h | p.pos):e { p.args.push *Array(e) ; p } | part(h):p part_head(h | p.pos):e { p.args.push *Array(e) ; p } | p:p keyword:k args:a {n(p, k, a.name, *a.args)} | p:p keyword:k {n(p, k, \"()\")})")
Rules[:_part_head] = rule_info("part_head", "sp+ !(&keyword) (ph_comma(h) | expr(h) | {[]})")
- Rules[:_ph_comma] = rule_info("ph_comma", "(expr(h):a sp* \",\" - ph_comma(h):b { b.unshift a ; b } | expr(h):a sp* \",\" - expr(h):b { [a,b] })")
+ 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[:_expr] = rule_info("expr", "value(h):e &{ e.pos.column > h.column } {e}")
Rules[:_chain] = rule_info("chain", "(chain(h):a sp* \".\" - chain(h)?:b { b && n(a.pos, :chain, a, b) || a } | operator:a !(&brace) o w chain(h):b {n(a.pos, :chain, a, *Array(b.name == :chain && b.args || b))} | chain_cont(h) | expr(h):a sp* chain(a.pos):b {n(a.pos, :chain, a, *Array(b.name == :chain && b.args || b))} | chain_val(h))")
Rules[:_chain_cont] = rule_info("chain_cont", "chain_val(h):a {(h | a.pos || h()).incr}:i sp* (comma(h) | (nl | sheebang) - block(i)):c { if a.name == :act a.args.push *Array(c); a else n(a.pos, :act, a, \"()\", *Array(c)) end }")
View
39 spec/grammar_spec.rb
@@ -427,6 +427,20 @@
[:msg, ["g", "()", [:name, "h"]]]]]]
end
+ it 'parses nested blocks until semicolon' do
+ code = <<-CODE
+ a :b u
+ :c e
+ ;
+ :d
+ CODE
+ s(code, :root).should ==
+ [:block, [:chain, [:name, "a"],
+ [:msg, ["b", "()", [:name, "u"]], ["c", "()", [:name, "e"]]]],
+ [:msg, ["d", "()"]]]
+
+ end
+
it 'parses messages with args' do
code = <<-CODE
a :b(
@@ -528,7 +542,7 @@
[:act, [:name, "foo"], "()", [:name, "baz"], [:name, "bar"]]]
end
- it 'appends args from end' do
+ it 'takes last tuple as arguments' do
code = <<-CODE
a foo bar, baz
CODE
@@ -538,6 +552,17 @@
[:act, [:name, "foo"], "()", [:name, "bar"], [:name, "baz"]]]
end
+
+ it 'takes last one-tuple-ending-with-dot as argument' do
+ code = <<-CODE
+ a foo bar ,.
+ CODE
+ s(code, :root).should ==
+ [:chain,
+ [:name, "a"],
+ [:act, [:name, "foo"], "()", [:name, "bar"]]]
+ end
+
it 'allows args to have many lines' do
code = <<-CODE
a foo bar,
@@ -549,6 +574,18 @@
[:act, [:name, "foo"], "()", [:name, "bar"], [:name, "baz"]]]
end
+ it 'allows args to have many lines ignoring white space between comma' do
+ code = <<-CODE
+ a foo bar
+ ,
+ baz
+ CODE
+ s(code, :root).should ==
+ [:chain,
+ [:name, "a"],
+ [:act, [:name, "foo"], "()", [:name, "bar"], [:name, "baz"]]]
+ end
+
it 'allows nested block with curly act' do
code = <<-CODE
a foo{} bar,
Please sign in to comment.
Something went wrong with that request. Please try again.