Skip to content

Commit

Permalink
fixes #141; lexer: overhauled range expansion
Browse files Browse the repository at this point in the history
  • Loading branch information
satyr committed Jun 20, 2012
1 parent 681781c commit 0b21f54
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 33 deletions.
22 changes: 14 additions & 8 deletions lib/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1227,7 +1227,7 @@ function addImplicitBraces(tokens){
}
}
function expandLiterals(tokens){
var i, token, sig, lno, from, char, to, tochar, by, ts, n, word, that, __ref, __step, __i, __len;
var i, token, sig, lno, from, char, to, tochar, by, byp, ts, n, word, that, __ref, __i, __len;
i = 0;
while (token = tokens[++i]) {
switch (token[0]) {
Expand All @@ -1244,16 +1244,22 @@ function expandLiterals(tokens){
__ref = decode(token[1], lno = token[2]), from = __ref[0], char = __ref[1];
__ref = decode(tokens[i + 1][1], lno), to = __ref[0], tochar = __ref[1];
if (char ^ tochar) {
carp('bad "to" in range');
carp('bad "to" in range', lno);
}
if (by = ((__ref = tokens[i + 2]) != null ? __ref[0] : void 8) === 'RANGE_BY') {
if (isNaN(by = (__ref = tokens[i + 3]) != null ? __ref[1] : void 8)) {
carp('bad "by" in range');
by = 1;
if (byp = ((__ref = tokens[i + 2]) != null ? __ref[0] : void 8) === 'RANGE_BY') {
if (!(by = +((__ref = tokens[i + 3]) != null ? __ref[1] : void 8))) {
carp('bad "by" in range', tokens[i + 2][2]);
}
}
if (token.op === 'til') {
to -= by / 2;
if (from > to ^ by < 0) {
to = from;
}
}
ts = [];
to -= token.op === 'til' && 1e-15;
for (n = from, __step = +by || 1; __step < 0 ? n >= to : n <= to; n += __step) {
for (n = from; by < 0 ? n >= to : n <= to; n += by) {
if (0x10000 < ts.push([
'STRNUM', char
? character(n)
Expand All @@ -1263,7 +1269,7 @@ function expandLiterals(tokens){
}
}
ts.pop() || carp('empty range', lno);
tokens.splice.apply(tokens, [i, by ? 4 : 2].concat(__slice.call(ts)));
tokens.splice.apply(tokens, [i, 2 + 2 * byp].concat(__slice.call(ts)));
i += ts.length - 1;
break;
case 'WORDS':
Expand Down
18 changes: 11 additions & 7 deletions src/lexer.co
Original file line number Diff line number Diff line change
Expand Up @@ -827,17 +827,21 @@ character = if JSON!? then uxxxx else ->
tokens.splice i++ 0 [\+- sig, token.2]
continue if token.callable
case \RANGE
[from, char] = decode token.1, lno = token.2
[from, char] = decode token. 1, lno = token.2
[to, tochar] = decode tokens[i+1]1, lno
carp 'bad "to" in range' if char ^ tochar
if by = tokens[i+2]?0 is \RANGE_BY
carp 'bad "by" in range' if isNaN by = tokens[i+3]?1
ts = []; to -= token.op is \til and 1e-15
for n from from to to by +by or 1
carp 'bad "to" in range' lno if char ^ tochar
by = 1
if byp = tokens[i+2]?0 is \RANGE_BY
carp 'bad "by" in range' tokens[i+2]2 unless by = +tokens[i+3]?1
if token.op is \til
to -= by / 2
to = from if from > to ^ by < 0
ts = []
for n from from to to by by
carp 'range limit exceeded' lno if 0x10000 < ts.push \
[\STRNUM, if char then character n else "#n", lno] [\, \, lno]
ts.pop! or carp 'empty range' lno
tokens.splice i, if by then 4 else 2, ...ts
tokens.splice i, 2 + 2 * byp, ...ts
i += ts.length - 1
case \WORDS
ts = [[\[ \[ lno = token.2]]
Expand Down
38 changes: 28 additions & 10 deletions test/literal.co
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,6 @@ eq 36, 0XF + 36RT
eq 100m2, 10m ** 2
eq 3000c, 30$ * 100

# [#31](https://github.com/satyr/coco/issues/31): Numeric Ranges
eq '1,2,3' String [1 to +3]
eq '1,0,-1' String Array 1 to -1 by -1

til = String
eq 2, [Number]0 til 2

throws 'range limit exceeded on line 1' -> Coco.tokens '0 to 1 by 1e-5'
throws 'empty range on line 3' -> Coco.tokens '\n\n 1 to 0'

# [coffee#764](https://github.com/jashkenas/coffee-script/issues/764)
# Boolean/Number should be indexable.
ok 42['toString']
Expand Down Expand Up @@ -419,5 +409,33 @@ eq o.3, 3
eq o.5, 5


### Numeric/Character Ranges
show = -> @@ * ' '

eq '-1 0 1 2' show -1 to +2
eq '1 0 -1' show +1 to -1 by -1

eq '999 1000' show 999 til 1001
eq '1e-9' show 1e-9 til 1e-8
eq '9999999' show 9999999 til 1e7
eq '10000000' show 1e7 til 9999999 by -1

eq '0.5 0.75 1' show 0.5 til 1.2 by 0.25

til = String
eq 2, [Number]0 til 2

eq 'A F K P U Z' show \A to \Z by 5
eq 'y u q m i e' show \y til \a by -4

ok \\u2028 to \\u2029

throws 'range limit exceeded on line 2' -> Coco.tokens '\n0 to 1 by 1e-5'
throws 'empty range on line 2' -> Coco.tokens '\n1 to 0'
throws 'bad "to" in range on line 2' -> Coco.tokens '\n0 to "q"'
throws 'bad "by" in range on line 2' -> Coco.tokens '\n0 to 9 by "2"'
throws 'bad string in range on line 2' -> Coco.tokens '\n"a" to "bc"'


### Misc
throws \unimplemented -> ...
8 changes: 0 additions & 8 deletions test/string.co
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,6 @@ eq('+', \+)
eq '\\', [\\\].0
eq '$', {\$}.\$

eq 'AFKPUZ' [\A to \Z by 5]*''

throws 'bad "to" in range on line 1' -> Coco.tokens '0 to "q"'
throws 'bad "by" in range on line 1' -> Coco.tokens '0 to 9 by "2"'
throws 'bad string in range on line 1' -> Coco.tokens '"a" to "bc"'

ok \\u2028 to \\u2029


# [coffee#923](https://github.com/jashkenas/coffee-script/issues/923)
eq "#{ "{" }", "{"
Expand Down

0 comments on commit 0b21f54

Please sign in to comment.