node.js - PEGjs: Fallback (backtrack?) to string if floating point rule fail -
i have atom
rule tries parse either number or quoted string first, if fails, treat thing string.
everything parses fine except 1 particular case specific string:
dud 123abc
which fails parse expected " ", "." or [0-9] "a" found.
error.
what expect: should parse , return string "123abc" string atom. can see several of unsuccessful attempts commented out in grammar content below.
any help/tips/pointers/suggestions appreciated!
you can try grammar on online peg.js version. i'm using node v0.8.23 , pegjs 0.7.0
numbers parses correctly:
- `123
- `0
- `0.
- `1.
- `.23
- `0.23
- `1.23
- `0.000
.
<--- string, not number , not error
i want 123abc
parsed string, possible?
this entire grammar file:
start = lines:line+ { return lines; } // --------------------- line structure line = command:command eol { return command; } command = action:atom args:(sep atom)* { var = 0, len = 0; (var = 0, len = args.length; < len; i++) { // discard parsed separator tokens args[i] = args[i][1]; } return [action, args]; } sep = ' '+ eol = "\r" / "\n" / "\r\n" atom = num:number { return num; } / str:string_quoted { return str; } / str:string { return str; } // --------------------- commands // todo: // --------------------- strings string = chars:([^" \r\n]+) { return chars.join(''); } string_quoted = '"' chars:quoted_chars* '"' { return chars.join(''); } quoted_chars = '\\"' { return '"'; } / char:[^"\r\n] { return char; } // --------------------- numbers number = integral:('0' / [1-9][0-9]*) fraction:("." [0-9]*)? { if (fraction && fraction.length) { fraction = fraction[0] + fraction[1].join(''); } else { fraction = ''; } integral = integral instanceof array ? integral[0] + integral[1].join('') : '0'; return parsefloat(integral + fraction); } / ("." / "0.") fraction:[0-9]+ { return parsefloat("0." + fraction.join('')); } /* float = integral:integer? fraction:fraction { return integral + fraction; } fraction = '.' digits:[0-9]* { return parsefloat('0.' + digits.join('')); } integer = digits:('0' / [1-9][0-9]*) { if (digits === '0') return 0; return parseint(digits[0] + digits[1].join(''), 10); } */
solved adding !([0-9\.]+[^0-9\.])
sort of look-ahead infront of number
rule.
i know atom
rule match making number
rule fails bit sooner. can helps ambiguous cases in future.
so number rule becomes:
number = !([0-9\.]+[^0-9\.]) integral:('0' / [1-9][0-9]*) fraction:("." [0-9]*)?
Comments
Post a Comment