| Index: utils/tests/peg/peg_test.dart
|
| diff --git a/utils/tests/peg/peg_test.dart b/utils/tests/peg/peg_test.dart
|
| index b48453b3fec686aef9b3cff037291a61f2e75527..e15648e573322c423b1c8d51f0ec82eb84250c9f 100644
|
| --- a/utils/tests/peg/peg_test.dart
|
| +++ b/utils/tests/peg/peg_test.dart
|
| @@ -3,6 +3,7 @@
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| library peg_tests;
|
| +
|
| import 'dart:core' hide Symbol;
|
| import '../../peg/pegparser.dart';
|
|
|
| @@ -10,7 +11,7 @@ testParens() {
|
| Grammar g = new Grammar();
|
| Symbol a = g['A'];
|
|
|
| - a.def = ['(', MANY(a, min:0), ')', (a) => a];
|
| + a.def = ['(', MANY(a, min: 0), ')', (a) => a];
|
|
|
| check(g, a, "", null);
|
| check(g, a, "()", '[]');
|
| @@ -19,20 +20,22 @@ testParens() {
|
| }
|
|
|
| testBlockComment() {
|
| -
|
| // Block comment in whitespace.
|
|
|
| Grammar g = new Grammar();
|
| Symbol blockComment = g['blockComment'];
|
|
|
| - blockComment.def =
|
| - ['/*',
|
| - MANY(OR([blockComment,
|
| - [NOT('*/'), CHAR()],
|
| - [END, ERROR('EOF in block comment')]
|
| - ]),
|
| - min: 0),
|
| - '*/'];
|
| + blockComment.def = [
|
| + '/*',
|
| + MANY(
|
| + OR([
|
| + blockComment,
|
| + [NOT('*/'), CHAR()],
|
| + [END, ERROR('EOF in block comment')]
|
| + ]),
|
| + min: 0),
|
| + '*/'
|
| + ];
|
| print(blockComment);
|
|
|
| var a = MANY(TEXT('x'));
|
| @@ -44,36 +47,36 @@ testBlockComment() {
|
| check(g, a, "x /*/***/ x", 'EOF in block comment');
|
| check(g, a, "x /*/*/x**/**/ x", '[x,x]');
|
|
|
| - check(g, a, r"""
|
| + check(
|
| + g,
|
| + a,
|
| + r"""
|
| /* Comment */
|
| /* Following comment with /* nested comment*/ */
|
| x
|
| /* x in comment */
|
| x /* outside comment */
|
| """,
|
| - '[x,x]');
|
| + '[x,x]');
|
| }
|
|
|
| testTEXT() {
|
| Grammar g = new Grammar();
|
|
|
| // TEXT grabs the parsed text,
|
| - check(g, TEXT(LEX(MANY(OR(['1','a'])))), ' 1a1 ', '1a1');
|
| + check(g, TEXT(LEX(MANY(OR(['1', 'a'])))), ' 1a1 ', '1a1');
|
|
|
| // Without the lexical context, TEXT will grab intervening whitespace.
|
| - check(g, TEXT(MANY(OR(['1','a']))), ' 1a1 ', '1a1');
|
| - check(g, TEXT(MANY(OR(['1','a']))), ' 1 a 1 ', '1 a 1');
|
| + check(g, TEXT(MANY(OR(['1', 'a']))), ' 1a1 ', '1a1');
|
| + check(g, TEXT(MANY(OR(['1', 'a']))), ' 1 a 1 ', '1 a 1');
|
|
|
| // Custom processing of the TEXT substring.
|
| - var binaryNumber =
|
| - TEXT(LEX(MANY(OR(['0','1']))),
|
| - (str, start, end) {
|
| - var r = 0;
|
| - var zero = '0'.codeUnitAt(0);
|
| - for (int i = start; i < end; i++)
|
| - r = r * 2 + (str.codeUnitAt(i) - zero);
|
| - return r;
|
| - });
|
| + var binaryNumber = TEXT(LEX(MANY(OR(['0', '1']))), (str, start, end) {
|
| + var r = 0;
|
| + var zero = '0'.codeUnitAt(0);
|
| + for (int i = start; i < end; i++) r = r * 2 + (str.codeUnitAt(i) - zero);
|
| + return r;
|
| + });
|
|
|
| check(g, binaryNumber, ' 10101 ', 21);
|
| check(g, binaryNumber, '1010111', 87);
|
| @@ -83,10 +86,15 @@ testTEXT() {
|
| testOR() {
|
| // OR matches the first match.
|
| Grammar g = new Grammar();
|
| - check(g, OR([['a', NOT(END), () => 1],
|
| - ['a', () => 2],
|
| - ['a', () => 3]]),
|
| - 'a', 2);
|
| + check(
|
| + g,
|
| + OR([
|
| + ['a', NOT(END), () => 1],
|
| + ['a', () => 2],
|
| + ['a', () => 3]
|
| + ]),
|
| + 'a',
|
| + 2);
|
| }
|
|
|
| testCODE() {
|
| @@ -96,8 +104,8 @@ testCODE() {
|
| check(g, a, 'bbb', 'bbb');
|
| check(g, a, 'ccc', 'ccc');
|
| check(g, a, 'ddd', 'ddd');
|
| - check(g, a, 'bad', null); // a is outside range.
|
| - check(g, a, 'bed', null); // e is outside range.
|
| + check(g, a, 'bad', null); // a is outside range.
|
| + check(g, a, 'bed', null); // e is outside range.
|
| }
|
|
|
| testC() {
|
| @@ -106,8 +114,7 @@ testC() {
|
| unary(operation) => () => (first) => [operation, first];
|
| reform(a, fns) {
|
| var r = a;
|
| - for (var fn in fns)
|
| - r = fn(r);
|
| + for (var fn in fns) r = fn(r);
|
| return r;
|
| }
|
|
|
| @@ -126,128 +133,177 @@ testC() {
|
| Symbol assignment_e = g['assignment_e'];
|
|
|
| // Lexical elements.
|
| - var idStartChar = CHAR(
|
| - r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
|
| - var idNextChar = CHAR(
|
| - r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_");
|
| + var idStartChar =
|
| + CHAR(r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
|
| + var idNextChar =
|
| + CHAR(r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$_");
|
|
|
| var id = TEXT(LEX('identifier', [idStartChar, MANY(idNextChar, min: 0)]));
|
|
|
| var lit = TEXT(LEX('literal', MANY(CHAR('0123456789'))));
|
|
|
| -
|
| var type_name = id;
|
|
|
| -
|
| // Expression grammar.
|
| - var primary_e = OR([id,
|
| - lit,
|
| - ['(', expression, ')', (e) => e]
|
| - ]);
|
| -
|
| - var postfixes = OR([['(', MANY(assignment_e, separator: ',', min: 0), ')', binary('apply')],
|
| - ['++', unary('postinc')],
|
| - ['--', unary('postdec')],
|
| - ['.', id, binary('field')],
|
| - ['->', id, binary('ptr')],
|
| - ]);
|
| -
|
| - postfix_e.def = [primary_e, MANY(postfixes, min:0), reform];
|
| -
|
| -
|
| - var unary_op = OR([['&', () => 'address'],
|
| - ['*', () => 'indir'],
|
| - ['!', () => 'not'],
|
| - ['~', () => 'not'],
|
| - ['-', () => 'negate'],
|
| - ['+', () => 'uplus'],
|
| - ]);
|
| + var primary_e = OR([
|
| + id,
|
| + lit,
|
| + ['(', expression, ')', (e) => e]
|
| + ]);
|
| +
|
| + var postfixes = OR([
|
| + ['(', MANY(assignment_e, separator: ',', min: 0), ')', binary('apply')],
|
| + ['++', unary('postinc')],
|
| + ['--', unary('postdec')],
|
| + ['.', id, binary('field')],
|
| + ['->', id, binary('ptr')],
|
| + ]);
|
| +
|
| + postfix_e.def = [primary_e, MANY(postfixes, min: 0), reform];
|
| +
|
| + var unary_op = OR([
|
| + ['&', () => 'address'],
|
| + ['*', () => 'indir'],
|
| + ['!', () => 'not'],
|
| + ['~', () => 'not'],
|
| + ['-', () => 'negate'],
|
| + ['+', () => 'uplus'],
|
| + ]);
|
| var sizeof = LEX('sizeof', ['sizeof', NOT(idNextChar)]);
|
|
|
| Symbol unary_e_plain = g['unary_e_plain'];
|
| - unary_e_plain.def =
|
| - OR([ ['++', unary_e, (e) => ['preinc', e]],
|
| - ['--', unary_e, (e) => ['predec', e]],
|
| - [unary_op, cast_e, (o, e) => [o, e]],
|
| - [sizeof, unary_e, (e) => ['sizeof-expr', e]],
|
| - [sizeof, '(', type_name , ')', (t) => ['sizeof-type', t]],
|
| - postfix_e
|
| - ]);
|
| + unary_e_plain.def = OR([
|
| + [
|
| + '++', unary_e, (e) => ['preinc', e] //
|
| + ],
|
| + [
|
| + '--', unary_e, (e) => ['predec', e] //
|
| + ],
|
| + [
|
| + unary_op, cast_e, (o, e) => [o, e] //
|
| + ],
|
| + [
|
| + sizeof, unary_e, (e) => ['sizeof-expr', e] //
|
| + ],
|
| + [
|
| + sizeof, '(', type_name, ')', (t) => ['sizeof-type', t] //
|
| + ],
|
| + postfix_e
|
| + ]);
|
|
|
| unary_e.def = MEMO(unary_e_plain);
|
| //unary_e.def = unary_e_plain;
|
|
|
| - cast_e.def = OR([ ['(', type_name, ')', cast_e, (t, e) => ['cast', t, e]],
|
| - unary_e,
|
| - ]);
|
| -
|
| - var mult_ops = OR([['*', cast_e, binary('mult')],
|
| - ['/', cast_e, binary('div')],
|
| - ['%', cast_e, binary('rem')],
|
| - ]);
|
| - mult_e.def = [cast_e, MANY(mult_ops, min:0), reform];
|
| -
|
| - var add_ops = OR([['+', mult_e, binary('add')],
|
| - ['-', mult_e, binary('sub')],
|
| - ]);
|
| - add_e.def = [mult_e, MANY(add_ops, min:0), reform];
|
| -
|
| - var shift_ops = OR([['>>', add_e, binary('shl')],
|
| - ['<<', add_e, binary('shr')],
|
| - ]);
|
| - shift_e.def = [add_e, MANY(shift_ops, min:0), reform];
|
| -
|
| - var relational_ops = OR([['<=', shift_e, binary('le')],
|
| - ['>=', shift_e, binary('ge')],
|
| - ['<', shift_e, binary('lt')],
|
| - ['>', shift_e, binary('gt')],
|
| - ]);
|
| - relational_e.def = [shift_e, MANY(relational_ops, min:0), reform];
|
| -
|
| -
|
| - var equality_ops = OR([['==', shift_e, binary('eq')],
|
| - ['!=', shift_e, binary('ne')],
|
| - ]);
|
| - equality_e.def = [relational_e, MANY(equality_ops, min:0), reform];
|
| -
|
| -
|
| - var bit_and_op = LEX('&', ['&', NOT('&')]); // Don't see '&&' and '&', '&'
|
| + cast_e.def = OR([
|
| + [
|
| + '(', type_name, ')', cast_e, (t, e) => ['cast', t, e] //
|
| + ],
|
| + unary_e,
|
| + ]);
|
| +
|
| + var mult_ops = OR([
|
| + ['*', cast_e, binary('mult')],
|
| + ['/', cast_e, binary('div')],
|
| + ['%', cast_e, binary('rem')],
|
| + ]);
|
| + mult_e.def = [cast_e, MANY(mult_ops, min: 0), reform];
|
| +
|
| + var add_ops = OR([
|
| + ['+', mult_e, binary('add')],
|
| + ['-', mult_e, binary('sub')],
|
| + ]);
|
| + add_e.def = [mult_e, MANY(add_ops, min: 0), reform];
|
| +
|
| + var shift_ops = OR([
|
| + ['>>', add_e, binary('shl')],
|
| + ['<<', add_e, binary('shr')],
|
| + ]);
|
| + shift_e.def = [add_e, MANY(shift_ops, min: 0), reform];
|
| +
|
| + var relational_ops = OR([
|
| + ['<=', shift_e, binary('le')],
|
| + ['>=', shift_e, binary('ge')],
|
| + ['<', shift_e, binary('lt')],
|
| + ['>', shift_e, binary('gt')],
|
| + ]);
|
| + relational_e.def = [shift_e, MANY(relational_ops, min: 0), reform];
|
| +
|
| + var equality_ops = OR([
|
| + ['==', shift_e, binary('eq')],
|
| + ['!=', shift_e, binary('ne')],
|
| + ]);
|
| + equality_e.def = [relational_e, MANY(equality_ops, min: 0), reform];
|
| +
|
| + var bit_and_op = LEX('&', ['&', NOT('&')]); // Don't see '&&' and '&', '&'
|
| var bit_or_op = LEX('|', ['|', NOT('|')]);
|
|
|
| - var and_e = [equality_e, MANY([bit_and_op, equality_e, binary('bitand')], min:0), reform];
|
| - var xor_e = [and_e, MANY(['^', and_e, binary('bitxor')], min:0), reform];
|
| - var or_e = [xor_e, MANY([bit_or_op, xor_e, binary('bitor')], min:0), reform];
|
| -
|
| - var log_and_e = [or_e, MANY(['&&', or_e, binary('and')], min:0), reform];
|
| -
|
| - var log_or_e = [log_and_e, MANY(['||', log_and_e, binary('or')], min:0), reform];
|
| + var and_e = [
|
| + equality_e,
|
| + MANY([bit_and_op, equality_e, binary('bitand')], min: 0),
|
| + reform
|
| + ];
|
| + var xor_e = [
|
| + and_e,
|
| + MANY(['^', and_e, binary('bitxor')], min: 0),
|
| + reform
|
| + ];
|
| + var or_e = [
|
| + xor_e,
|
| + MANY([bit_or_op, xor_e, binary('bitor')], min: 0),
|
| + reform
|
| + ];
|
| +
|
| + var log_and_e = [
|
| + or_e,
|
| + MANY(['&&', or_e, binary('and')], min: 0),
|
| + reform
|
| + ];
|
| +
|
| + var log_or_e = [
|
| + log_and_e,
|
| + MANY(['||', log_and_e, binary('or')], min: 0),
|
| + reform
|
| + ];
|
|
|
| //cond_e.def = OR([ [log_or_e, '?', expression, ':', cond_e,
|
| // (p,a,b) => ['cond', p, a, b]],
|
| // log_or_e]);
|
| // Alternate version avoids reparsing log_or_e.
|
| - cond_e.def = [log_or_e, MAYBE(['?', expression, ':', cond_e]),
|
| - (p, r) => r == null || r == false ? p : ['cond', p, r[0], r[1]]];
|
| + cond_e.def = [
|
| + log_or_e,
|
| + MAYBE(['?', expression, ':', cond_e]),
|
| + (p, r) => r == null || r == false ? p : ['cond', p, r[0], r[1]]
|
| + ];
|
|
|
| - var assign_op = OR([['*=', () => 'mulassign'],
|
| - ['=', () => 'assign']]);
|
| + var assign_op = OR([
|
| + ['*=', () => 'mulassign'],
|
| + ['=', () => 'assign']
|
| + ]);
|
|
|
| // TODO: Figure out how not to re-parse a unary_e.
|
| // Order matters - cond_e can't go first since cond_e will succeed on, e.g. 'a'.
|
| - assignment_e.def = OR([[unary_e, assign_op, assignment_e,
|
| - (u, op, a) => [op, u, a]],
|
| - cond_e]);
|
| -
|
| - expression.def = [assignment_e,
|
| - MANY([',', assignment_e, binary('comma')], min:0),
|
| - reform];
|
| + assignment_e.def = OR([
|
| + [
|
| + unary_e,
|
| + assign_op,
|
| + assignment_e,
|
| + (u, op, a) => [op, u, a]
|
| + ],
|
| + cond_e
|
| + ]);
|
| +
|
| + expression.def = [
|
| + assignment_e,
|
| + MANY([',', assignment_e, binary('comma')], min: 0),
|
| + reform
|
| + ];
|
|
|
| show(g, expression, 'a');
|
| check(g, expression, 'a', 'a');
|
| check(g, expression, '(a)', 'a');
|
| check(g, expression, ' ( ( a ) ) ', 'a');
|
|
|
| - check(g, expression, 'a(~1,2)', '[apply,a,[[not,1],2]]');
|
| + check(g, expression, 'a(~1,2)', '[apply,a,[[not,1],2]]');
|
| check(g, expression, 'a(1)(x,2)', '[apply,[apply,a,[1]],[x,2]]');
|
| check(g, expression, 'a(1,2())', '[apply,a,[1,[apply,2,[]]]]');
|
|
|
| @@ -271,22 +327,20 @@ testC() {
|
| check(g, expression, 'a<1&&b', '[and,[lt,a,1],b]');
|
|
|
| check(g, expression, 'a<1 & &b', '[bitand,[lt,a,1],[address,b]]');
|
| - check(g, expression,
|
| - 'a ? b ? c : d : e ? f : g',
|
| - '[cond,a,[cond,b,c,d],[cond,e,f,g]]');
|
| + check(g, expression, 'a ? b ? c : d : e ? f : g',
|
| + '[cond,a,[cond,b,c,d],[cond,e,f,g]]');
|
|
|
| check(g, expression, 'a,b,c', '[comma,[comma,a,b],c]');
|
| check(g, expression, 'a=1,b,c', '[comma,[comma,[assign,a,1],b],c]');
|
|
|
| - check(g, expression,
|
| - '((((((((((((a))))))))))))=1,b,c', '[comma,[comma,[assign,a,1],b],c]');
|
| + check(g, expression, '((((((((((((a))))))))))))=1,b,c',
|
| + '[comma,[comma,[assign,a,1],b],c]');
|
|
|
| check(g, expression, 'sizeof a', '[sizeof-expr,a]');
|
| check(g, expression, 'sizeofa', 'sizeofa');
|
| check(g, expression, 'sizeof (a)', '[sizeof-expr,a]');
|
| }
|
|
|
| -
|
| show(grammar, rule, input) {
|
| print('show: "$input"');
|
| var ast;
|
| @@ -313,13 +367,11 @@ void check(grammar, rule, input, expected) {
|
| }
|
|
|
| var formatted = ast;
|
| - if (expected is String)
|
| - formatted = printList(ast);
|
| + if (expected is String) formatted = printList(ast);
|
|
|
| //Expect.equals(expected, formatted, "parse: $input");
|
| if (expected != formatted) {
|
| - throw new ArgumentError(
|
| - "parse: $input"
|
| + throw new ArgumentError("parse: $input"
|
| "\n expected: $expected"
|
| "\n found: $formatted");
|
| }
|
| @@ -339,8 +391,7 @@ printList(item) {
|
| sb.write(']');
|
| return sb.toString();
|
| }
|
| - if (item == null)
|
| - return 'null';
|
| + if (item == null) return 'null';
|
| return item.toString();
|
| }
|
|
|
|
|