Permalink
Browse files

- fixed the package structure

- moved all tests to test/
- created AllTests.dart to run all tests
- cleaned up the naming of tests
- split parser and grammars into separate files
  • Loading branch information...
1 parent 29194ca commit 628a9cc89084d1ce91cc2fa3fb5d5624abbe2167 @renggli renggli committed Jun 10, 2012
View
19 grammar/json/Json.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2012, Lukas Renggli <renggli@gmail.com>
+
+#library('Json');
+
+#import('../../lib/PetitParser.dart');
+
+#source('JsonGrammar.dart');
+#source('JsonParser.dart');
+
+final ESCAPE_TABLE = const {
+ '\\': '\\',
+ '/': '/',
+ '"': '"',
+ 'b': '\b',
+ 'f': '\f',
+ 'n': '\n',
+ 'r': '\r',
+ 't': '\t'
+};
View
62 grammars/json/Json.dart → grammar/json/JsonGrammar.dart
@@ -1,9 +1,5 @@
// Copyright (c) 2012, Lukas Renggli <renggli@gmail.com>
-#library('Json');
-
-#import('../../lib/PetitParser.dart');
-
/**
* JSON grammar definition.
*/
@@ -64,60 +60,4 @@ class JsonGrammar extends CompositeParser {
.seq(char('"')));
}
-}
-
-/**
- * JSON parser definition.
- */
-class JsonParser extends JsonGrammar {
-
- void initialize() {
- super.initialize();
-
- action('array', (each) => each[1] != null ? each[1] : new List());
- redefine('elements', (parser) => parser.withoutSeparators());
- redefine('members', (parser) => parser.withoutSeparators());
- action('object', (each) {
- var result = new LinkedHashMap();
- if (each[1] != null) {
- for (List element in each[1]) {
- result[element[0]] = element[2];
- }
- }
- return result;
- });
-
- action('trueToken', (each) => true);
- action('falseToken', (each) => false);
- action('nullToken', (each) => null);
- redefine('stringToken', (parser) => ref('stringPrimitive').trim());
- action('numberToken', (each) {
- var floating = Math.parseDouble(each);
- var integral = floating.toInt();
- if (floating == integral && each.indexOf('.') == -1) {
- return integral;
- } else {
- return floating;
- }
- });
-
- action('stringPrimitive', (each) => Strings.join(each[1], ''));
- action('characterEscape', (each) => ESCAPE_TABLE[each[1]]);
- action('characterOctal', (each) {
- throw new UnsupportedOperationException('Octal characters not supported yet');
- });
-
- }
-
-}
-
-final ESCAPE_TABLE = const {
- '\\': '\\',
- '/': '/',
- '"': '"',
- 'b': '\b',
- 'f': '\f',
- 'n': '\n',
- 'r': '\r',
- 't': '\t'
-};
+}
View
46 grammar/json/JsonParser.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2012, Lukas Renggli <renggli@gmail.com>
+
+/**
+ * JSON parser definition.
+ */
+class JsonParser extends JsonGrammar {
+
+ void initialize() {
+ super.initialize();
+
+ action('array', (each) => each[1] != null ? each[1] : new List());
+ redefine('elements', (parser) => parser.withoutSeparators());
+ redefine('members', (parser) => parser.withoutSeparators());
+ action('object', (each) {
+ var result = new LinkedHashMap();
+ if (each[1] != null) {
+ for (List element in each[1]) {
+ result[element[0]] = element[2];
+ }
+ }
+ return result;
+ });
+
+ action('trueToken', (each) => true);
+ action('falseToken', (each) => false);
+ action('nullToken', (each) => null);
+ redefine('stringToken', (parser) => ref('stringPrimitive').trim());
+ action('numberToken', (each) {
+ var floating = Math.parseDouble(each);
+ var integral = floating.toInt();
+ if (floating == integral && each.indexOf('.') == -1) {
+ return integral;
+ } else {
+ return floating;
+ }
+ });
+
+ action('stringPrimitive', (each) => Strings.join(each[1], ''));
+ action('characterEscape', (each) => ESCAPE_TABLE[each[1]]);
+ action('characterOctal', (each) {
+ throw new UnsupportedOperationException('Octal characters not supported yet');
+ });
+
+ }
+
+}
View
9 grammar/xml/Xml.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2012, Lukas Renggli <renggli@gmail.com>
+
+#library('Xml');
+
+#import('../../lib/PetitParser.dart');
+
+#source('XmlGrammar.dart');
+#source('XmlParser.dart');
+#source('XmlNodes.dart');
View
26 grammars/xml/Xml.dart → grammar/xml/XmlGrammar.dart
@@ -1,11 +1,5 @@
// Copyright (c) 2012, Lukas Renggli <renggli@gmail.com>
-#library('Xml');
-
-#import('../../lib/PetitParser.dart');
-
-#source('XmlNodes.dart');
-
/**
* XML grammar definition.
*/
@@ -110,24 +104,4 @@ class XmlGrammar extends CompositeParser {
define('nameChar', pattern(NAME_CHARS));
}
-}
-
-/**
- * XML parser definition.
- */
-class XmlParser extends XmlGrammar {
-
- void initialize() {
- super.initialize();
-
- action('attribute', (each) => new XmlAttribute(each[0], each[1]));
- action('comment', (each) => new XmlComment(each));
- action('doctype', (each) => new XmlDoctype(each));
- action('document', (each) => new XmlDocument(each));
- action('element', (each) => new XmlElement(each[0], each[1], each[2]));
- action('processing', (each) => new XmlProcessing(each[0], each[1]));
- action('qualified', (each) => new XmlName(each));
- action('characterData', (each) => new XmlText(each));
- }
-
}
View
0 grammars/xml/XmlNodes.dart → grammar/xml/XmlNodes.dart
File renamed without changes.
View
21 grammar/xml/XmlParser.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2012, Lukas Renggli <renggli@gmail.com>
+
+/**
+ * XML parser definition.
+ */
+class XmlParser extends XmlGrammar {
+
+ void initialize() {
+ super.initialize();
+
+ action('attribute', (each) => new XmlAttribute(each[0], each[1]));
+ action('comment', (each) => new XmlComment(each));
+ action('doctype', (each) => new XmlDoctype(each));
+ action('document', (each) => new XmlDocument(each));
+ action('element', (each) => new XmlElement(each[0], each[1], each[2]));
+ action('processing', (each) => new XmlProcessing(each[0], each[1]));
+ action('qualified', (each) => new XmlName(each));
+ action('characterData', (each) => new XmlText(each));
+ }
+
+}
View
5 lib/Composite.dart
@@ -24,6 +24,7 @@ abstract class CompositeParser extends DelegateParser {
}
parser._delegate = _defined[name];
});
+ // TODO(renggli): remove the delegates as soon as dart allows object copying
replace(children[0], ref('start'));
}
@@ -52,8 +53,8 @@ abstract class CompositeParser extends DelegateParser {
}
}
- /** Attaches an action to an existing production. */
- void action(String name, Function function) {
+ /** Attaches an action [function] to an existing production [name]. */
+ void action(String name, Dynamic function(Dynamic)) {
redefine(name, (parser) => parser.map(function));
}
View
16 lib/Parser.dart
@@ -53,9 +53,9 @@ abstract class Parser {
Parser wrapper() => new WrapperParser(this);
Parser flatten() => new FlattenParser(this);
- Parser trim([Parser trimmer]) => new TrimmingParser(this, trimmer);
+ Parser trim([Parser trimmer]) => new TrimmingParser(this, trimmer == null ? whitespace() : trimmer);
Parser map(Function function) => new ActionParser(this, function);
- Parser end([String message]) => new EndOfInputParser(this, message);
+ Parser end([String message]) => new EndOfInputParser(this, message == null ? 'end of input expected' : message);
Parser separatedBy(Parser separator) {
return new SequenceParser([this, new SequenceParser([separator, this]).star()]).map((List list) {
@@ -196,7 +196,7 @@ class NotParser extends DelegateParser {
final String _message;
- NotParser(parser, [this._message])
+ NotParser(parser, this._message)
: super(parser);
Result _parse(Context context) {
@@ -217,9 +217,8 @@ class EndOfInputParser extends DelegateParser {
final String _message;
- EndOfInputParser(parser, [String message])
- : super(parser),
- _message = message != null ? message : "end of input expected";
+ EndOfInputParser(parser, this._message)
+ : super(parser);
Result _parse(Context context) {
var result = super._parse(context);
@@ -258,9 +257,8 @@ class TrimmingParser extends DelegateParser {
Parser _trimmer;
- TrimmingParser(parser, [Parser trimmer])
- : super(parser),
- _trimmer = trimmer != null ? trimmer : whitespace();
+ TrimmingParser(parser, this._trimmer)
+ : super(parser);
Result _parse(Context context) {
var current = context;
View
425 test/AllTests.dart
@@ -2,425 +2,14 @@
#library('AllTests');
-#import('dart:core');
#import('/Applications/Dart/dart-sdk/lib/unittest/unittest.dart');
-#import('../lib/PetitParser.dart');
-
-void expectSuccess(Parser parser, Dynamic input, Dynamic expected, [int position]) {
- Result result = parser.parse(input);
- expect(result.isSuccess()).isTrue();
- expect(result.isFailure()).isFalse();
- // TODO(renggli): compare actual objects when expect() is fixed
- expect(result.getResult().toString()).equals(expected.toString());
- expect(result.position).equals(position != null ? position : input.length);
-}
-
-void expectFailure(Parser parser, Dynamic input, [int position = 0, String message]) {
- Result result = parser.parse(input);
- expect(result.isFailure()).isTrue();
- expect(result.isSuccess()).isFalse();
- expect(result.position).equals(position);
- if (message != null) {
- expect(result.getMessage()).equals(message);
- }
-}
-
-main() {
-
- group('Parser', () {
- test('and', () {
- Parser parser = char('a').and();
- expectSuccess(parser, 'a', 'a', 0);
- expectFailure(parser, 'b', message: 'a expected');
- expectFailure(parser, '');
- });
- test('choice of two', () {
- Parser parser = char('a').or(char('b'));
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, 'b', 'b');
- expectFailure(parser, 'c');
- expectFailure(parser, '');
- });
- test('choice of three', () {
- Parser parser = char('a').or(char('b')).or(char('c'));
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, 'b', 'b');
- expectSuccess(parser, 'c', 'c');
- expectFailure(parser, 'd');
- expectFailure(parser, '');
- });
- test('end of input', () {
- Parser parser = char('a').end();
- expectFailure(parser, '', 0, 'a expected');
- expectSuccess(parser, 'a', 'a');
- expectFailure(parser, 'aa', 1, 'end of input expected');
- });
- test('flatten', () {
- Parser parser = digit().plus().flatten();
- expectFailure(parser, '');
- expectFailure(parser, 'a');
- expectSuccess(parser, '1', '1');
- expectSuccess(parser, '12', '12');
- expectSuccess(parser, '123', '123');
- expectSuccess(parser, '1234', '1234');
- });
- test('action', () {
- Parser parser = digit().map((String each) {
- return each.charCodeAt(0) - '0'.charCodeAt(0);
- });
- expectSuccess(parser, '1', 1);
- expectSuccess(parser, '4', 4);
- expectSuccess(parser, '9', 9);
- expectFailure(parser, '');
- expectFailure(parser, 'a');
- });
- test('not', () {
- Parser parser = char('a').not('not a expected');
- expectFailure(parser, 'a', message: 'not a expected');
- expectSuccess(parser, 'b', null, 0);
- expectSuccess(parser, '', null);
- });
- test('optional', () {
- Parser parser = char('a').optional();
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, 'b', null, 0);
- expectSuccess(parser, '', null);
- });
- test('plus', () {
- Parser parser = char('a').plus();
- expectFailure(parser, '', message: 'a expected');
- expectSuccess(parser, 'a', ['a']);
- expectSuccess(parser, 'aa', ['a', 'a']);
- expectSuccess(parser, 'aaa', ['a', 'a', 'a']);
- });
- test('times', () {
- Parser parser = char('a').times(2);
- expectFailure(parser, '', 0, 'a expected');
- expectFailure(parser, 'a', 1, 'a expected');
- expectSuccess(parser, 'aa', ['a', 'a']);
- expectSuccess(parser, 'aaa', ['a', 'a'], 2);
- });
- test('repeat', () {
- Parser parser = char('a').repeat(2, 3);
- expectFailure(parser, '', 0, 'a expected');
- expectFailure(parser, 'a', 1, 'a expected');
- expectSuccess(parser, 'aa', ['a', 'a']);
- expectSuccess(parser, 'aaa', ['a', 'a', 'a']);
- expectSuccess(parser, 'aaaa', ['a', 'a', 'a'], 3);
- });
- test('separated by', () {
- Parser parser = char('a').separatedBy(char('b'));
- expectFailure(parser, '', 0, 'a expected');
- expectSuccess(parser, 'a', ['a']);
- expectSuccess(parser, 'ab', ['a'], 1);
- expectSuccess(parser, 'aba', ['a', 'b', 'a']);
- expectSuccess(parser, 'abab', ['a', 'b', 'a'], 3);
- expectSuccess(parser, 'ababa', ['a', 'b', 'a', 'b', 'a']);
- expectSuccess(parser, 'ababab', ['a', 'b', 'a', 'b', 'a'], 5);
- });
- test('sequence of two', () {
- Parser parser = char('a').seq(char('b'));
- expectSuccess(parser, 'ab', ['a', 'b']);
- expectFailure(parser, '');
- expectFailure(parser, 'x');
- expectFailure(parser, 'a', 1);
- expectFailure(parser, 'ax', 1);
- });
- test('sequence of three', () {
- Parser parser = char('a').seq(char('b')).seq(char('c'));
- expectSuccess(parser, 'abc', ['a', 'b', 'c']);
- expectFailure(parser, '');
- expectFailure(parser, 'x');
- expectFailure(parser, 'a', 1);
- expectFailure(parser, 'ax', 1);
- expectFailure(parser, 'ab', 2);
- expectFailure(parser, 'abx', 2);
- });
- test('star', () {
- Parser parser = char('a').star();
- expectSuccess(parser, '', []);
- expectSuccess(parser, 'a', ['a']);
- expectSuccess(parser, 'aa', ['a', 'a']);
- expectSuccess(parser, 'aaa', ['a', 'a', 'a']);
- });
- test('trim', () {
- Parser parser = char('a').trim();
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, ' a', 'a');
- expectSuccess(parser, 'a ', 'a');
- expectSuccess(parser, ' a ', 'a');
- expectSuccess(parser, ' a', 'a');
- expectSuccess(parser, 'a ', 'a');
- expectSuccess(parser, ' a ', 'a');
- expectFailure(parser, '', message: 'a expected');
- expectFailure(parser, 'b', message: 'a expected');
- expectFailure(parser, ' b', 1, 'a expected');
- expectFailure(parser, ' b', 2, 'a expected');
- });
- test('trim custom', () {
- Parser parser = char('a').trim(char('*'));
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, '*a', 'a');
- expectSuccess(parser, 'a*', 'a');
- expectSuccess(parser, '*a*', 'a');
- expectSuccess(parser, '**a', 'a');
- expectSuccess(parser, 'a**', 'a');
- expectSuccess(parser, '**a**', 'a');
- expectFailure(parser, '', message: 'a expected');
- expectFailure(parser, 'b', message: 'a expected');
- expectFailure(parser, '*b', 1, 'a expected');
- expectFailure(parser, '**b', 2, 'a expected');
- });
- test('wrapped', () {
- Parser parser = char('a').wrapper();
- expectSuccess(parser, 'a', 'a');
- expectFailure(parser, 'b', message: 'a expected');
- expectFailure(parser, '');
- });
- test('epsilon', () {
- Parser parser = new EpsilonParser();
- expectSuccess(parser, '', null);
- expectSuccess(parser, 'a', null, 0);
- });
- test('failure', () {
- Parser parser = new FailureParser('failure');
- expectFailure(parser, '', 0, 'failure');
- expectFailure(parser, 'a', 0, 'failure');
- });
- test('negate', () {
- Parser parser = digit().neg('no digit expected');
- expectFailure(parser, '1', 0, 'no digit expected');
- expectFailure(parser, '9', 0, 'no digit expected');
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, ' ', ' ');
- expectFailure(parser, '', 0, 'input expected');
- });
- });
-
- group('Predicate', () {
- test('any', () {
- Parser parser = any();
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, 'b', 'b');
- expectFailure(parser, '', message: 'input expected');
- });
- test('char', () {
- Parser parser = char('a');
- expectSuccess(parser, 'a', 'a');
- expectFailure(parser, 'b');
- expectFailure(parser, '');
- });
- test('string', () {
- Parser parser = string('foo');
- expectSuccess(parser, 'foo', 'foo');
- expectFailure(parser, '');
- expectFailure(parser, 'f');
- expectFailure(parser, 'fo');
- expectFailure(parser, 'Foo');
- });
- test('string ignore case', () {
- Parser parser = stringIgnoreCase('foo');
- expectSuccess(parser, 'foo', 'foo');
- expectSuccess(parser, 'FOO', 'FOO');
- expectSuccess(parser, 'fOo', 'fOo');
- expectFailure(parser, '');
- expectFailure(parser, 'f');
- expectFailure(parser, 'Fo');
- });
- test('pattern with characters', () {
- Parser parser = pattern('abc');
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, 'b', 'b');
- expectSuccess(parser, 'c', 'c');
- expectFailure(parser, 'd');
- });
- test('pattern with range of characters', () {
- Parser parser = pattern('a-c');
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, 'b', 'b');
- expectSuccess(parser, 'c', 'c');
- expectFailure(parser, 'd');
- });
- test('pattern with negation', () {
- Parser parser = pattern('^a-cd');
- expectFailure(parser, 'a');
- expectFailure(parser, 'b');
- expectFailure(parser, 'c');
- expectFailure(parser, 'd');
- expectSuccess(parser, 'e', 'e');
- });
- test('digit', () {
- Parser parser = digit();
- expectSuccess(parser, '1', '1');
- expectSuccess(parser, '9', '9');
- expectFailure(parser, 'a', message: 'digit expected');
- expectFailure(parser, '');
- });
- test('letter', () {
- Parser parser = letter();
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, 'X', 'X');
- expectFailure(parser, '0', message: 'letter expected');
- expectFailure(parser, '');
- });
- test('lowercase', () {
- Parser parser = lowercase();
- expectSuccess(parser, 'a', 'a');
- expectFailure(parser, 'A', message: 'lowercase letter expected');
- expectFailure(parser, '0', message: 'lowercase letter expected');
- expectFailure(parser, '');
- });
- test('range', () {
- Parser parser = range('e', 'o');
- expectFailure(parser, 'd', message: 'e..o expected');
- expectSuccess(parser, 'e', 'e');
- expectSuccess(parser, 'i', 'i');
- expectSuccess(parser, 'o', 'o');
- expectFailure(parser, 'p', message: 'e..o expected');
- });
- test('uppercase', () {
- Parser parser = uppercase();
- expectSuccess(parser, 'Z', 'Z');
- expectFailure(parser, 'z', message: 'uppercase letter expected');
- expectFailure(parser, '0', message: 'uppercase letter expected');
- expectFailure(parser, '');
- });
- test('whitespace', () {
- Parser parser = whitespace();
- expectSuccess(parser, ' ', ' ');
- expectFailure(parser, 'z', message: 'whitespace expected');
- expectFailure(parser, '-', message: 'whitespace expected');
- expectFailure(parser, '');
- });
- test('word', () {
- Parser parser = word();
- expectSuccess(parser, 'a', 'a');
- expectSuccess(parser, '0', '0');
- expectFailure(parser, '-', message: 'letter or digit expected');
- expectFailure(parser, '');
- });
- });
-
- group('Parsing', () {
- test('parse', () {
- Parser parser = char('a');
- expect(parser.parse('a').isSuccess()).isTrue();
- expect(parser.parse('b').isSuccess()).isFalse();
- });
- test('accept', () {
- Parser parser = char('a');
- expect(parser.accept('a')).isTrue();
- expect(parser.accept('b')).isFalse();
- });
- test('matches', () {
- Parser parser = digit().seq(digit()).flatten();
- // TODO(renggli): compare actual objects when expect() is fixed
- expect(['12', '23', '45'].toString()).equals(parser.matches('a123b45').toString());
- });
- test('matches skipping', () {
- Parser parser = digit().seq(digit()).flatten();
- // TODO(renggli): compare actual objects when expect() is fixed
- expect(['12', '45'].toString()).equals(parser.matchesSkipping('a123b45').toString());
- });
- });
-
- group('Example', () {
- final Parser IDENTIFIER = letter().seq(word().star()).flatten();
- final Parser NUMBER = char('-').optional().seq(digit().plus())
- .seq(char('.').seq(digit().plus()).optional()).flatten();
- final Parser STRING = char('"')
- .seq(char('"').neg().star()).seq(char('"')).flatten();
- final Parser RETURN = string('return')
- .seq(whitespace().plus().flatten()).seq(IDENTIFIER.or(NUMBER).or(STRING))
- .map((list) => list.last());
- final Parser JAVADOC = string('/**')
- .seq(string('*/').neg().star())
- .seq(string('*/'))
- .flatten();
- test('valid identifier', () {
- expectSuccess(IDENTIFIER, 'a', 'a');
- expectSuccess(IDENTIFIER, 'a1', 'a1');
- expectSuccess(IDENTIFIER, 'a12', 'a12');
- expectSuccess(IDENTIFIER, 'ab', 'ab');
- expectSuccess(IDENTIFIER, 'a1b', 'a1b');
- });
- test('incomplete identifier', () {
- expectSuccess(IDENTIFIER, 'a=', 'a', 1);
- expectSuccess(IDENTIFIER, 'a1-', 'a1', 2);
- expectSuccess(IDENTIFIER, 'a12+', 'a12', 3);
- expectSuccess(IDENTIFIER, 'ab ', 'ab', 2);
- });
- test('invalid identifier', () {
- expectFailure(IDENTIFIER, '', 0, 'letter expected');
- expectFailure(IDENTIFIER, '1', 0, 'letter expected');
- expectFailure(IDENTIFIER, '1a', 0, 'letter expected');
- });
- test('positive number', () {
- expectSuccess(NUMBER, '1', '1');
- expectSuccess(NUMBER, '12', '12');
- expectSuccess(NUMBER, '12.3', '12.3');
- expectSuccess(NUMBER, '12.34', '12.34');
- });
- test('negative number', () {
- expectSuccess(NUMBER, '-1', '-1');
- expectSuccess(NUMBER, '-12', '-12');
- expectSuccess(NUMBER, '-12.3', '-12.3');
- expectSuccess(NUMBER, '-12.34', '-12.34');
- });
- test('incomplete number', () {
- expectSuccess(NUMBER, '1..', '1', 1);
- expectSuccess(NUMBER, '12-', '12', 2);
- expectSuccess(NUMBER, '12.3.', '12.3', 4);
- expectSuccess(NUMBER, '12.34.', '12.34', 5);
- });
- test('invalid number', () {
- expectFailure(NUMBER, '', 0, 'digit expected');
- expectFailure(NUMBER, '-', 1, 'digit expected');
- expectFailure(NUMBER, '-x', 1, 'digit expected');
- expectFailure(NUMBER, '.', 0, 'digit expected');
- expectFailure(NUMBER, '.1', 0, 'digit expected');
- });
- test('valid string', () {
- expectSuccess(STRING, '""', '""');
- expectSuccess(STRING, '"a"', '"a"');
- expectSuccess(STRING, '"ab"', '"ab"');
- expectSuccess(STRING, '"abc"', '"abc"');
- });
- test('incomplete string', () {
- expectSuccess(STRING, '""x', '""', 2);
- expectSuccess(STRING, '"a"x', '"a"', 3);
- expectSuccess(STRING, '"ab"x', '"ab"', 4);
- expectSuccess(STRING, '"abc"x', '"abc"', 5);
- });
- test('invalid string', () {
- expectFailure(STRING, '"', 1, '" expected');
- expectFailure(STRING, '"a', 2, '" expected');
- expectFailure(STRING, '"ab', 3, '" expected');
- expectFailure(STRING, 'a"', 0, '" expected');
- expectFailure(STRING, 'ab"', 0, '" expected');
- });
- test('return statement', () {
- expectSuccess(RETURN, 'return f', 'f');
- expectSuccess(RETURN, 'return f', 'f');
- expectSuccess(RETURN, 'return foo', 'foo');
- expectSuccess(RETURN, 'return foo', 'foo');
- expectSuccess(RETURN, 'return 1', '1');
- expectSuccess(RETURN, 'return 1', '1');
- expectSuccess(RETURN, 'return -2.3', '-2.3');
- expectSuccess(RETURN, 'return -2.3', '-2.3');
- expectSuccess(RETURN, 'return "a"', '"a"');
- expectSuccess(RETURN, 'return "a"', '"a"');
- });
- test('invalid statement', () {
- expectFailure(RETURN, 'retur f', 0, 'return expected');
- expectFailure(RETURN, 'return1', 6, 'whitespace expected');
- expectFailure(RETURN, 'return _', 8, '" expected');
- });
- test('javadoc', () {
- expectSuccess(JAVADOC, '/** foo */', '/** foo */');
- expectSuccess(JAVADOC, '/** * * */', '/** * * */');
- });
- });
+#import('PetitParserTests.dart', prefix: 'petitparser');
+#import('JsonTests.dart', prefix: 'json');
+#import('XmlTests.dart', prefix: 'xml');
+void main() {
+ group('PetitParser -', petitparser.main);
+ group('JSON -', json.main);
+ group('XML -', xml.main);
}
View
72 grammars/json/JsonTests.dart → test/JsonTests.dart
@@ -4,30 +4,30 @@
#import('/Applications/Dart/dart-sdk/lib/unittest/unittest.dart');
-#import('../../lib/PetitParser.dart');
-#import('Json.dart');
+#import('../lib/PetitParser.dart');
+#import('../grammar/json/Json.dart');
void main() {
final Parser json = new JsonParser();
- group('arrays', () {
- test('empty', () {
+ group('Arrays -', () {
+ test('Empty', () {
// TODO(renggli): compare actual objects when expect() is fixed
expect(json.parse('[]').getResult().toString()).equals([].toString());
});
- test('small', () {
+ test('Small', () {
// TODO(renggli): compare actual objects when expect() is fixed
expect(json.parse('["a"]').getResult().toString()).equals(['a'].toString());
});
- test('large', () {
+ test('Large', () {
// TODO(renggli): compare actual objects when expect() is fixed
expect(json.parse('["a", "b", "c"]').getResult().toString()).equals(['a', 'b', 'c'].toString());
});
- test('nested', () {
+ test('Nested', () {
// TODO(renggli): compare actual objects when expect() is fixed
expect(json.parse('[["a"]]').getResult().toString()).equals([['a']].toString());
});
- test('invalid', () {
+ test('Invalid', () {
expect(json.parse('[').isFailure()).isTrue();
expect(json.parse('[1').isFailure()).isTrue();
expect(json.parse('[1,').isFailure()).isTrue();
@@ -37,21 +37,21 @@ void main() {
});
});
- group('objects', () {
- test('empty', () {
+ group('Objects -', () {
+ test('Empty', () {
expect(json.parse('{}').getResult()).equals({});
});
- test('small', () {
+ test('Small', () {
expect(json.parse('{"a": 1}').getResult()).equals({'a': 1});
});
- test('large', () {
+ test('Large', () {
expect(json.parse('{"a": 1, "b": 2, "c": 3}').getResult()).equals({'a': 1, 'b': 2, 'c': 3});
});
- test('nested', () {
+ test('Nested', () {
// TODO(renggli): compare actual objects when expect() is fixed
expect(json.parse('{"obj": {"a": 1}}').getResult().toString()).equals({'obj': {"a": 1}}.toString());
});
- test('invalid', () {
+ test('Invalid', () {
expect(json.parse('{').isFailure()).isTrue();
expect(json.parse('{\'a\'').isFailure()).isTrue();
expect(json.parse('{\'a\':').isFailure()).isTrue();
@@ -64,32 +64,32 @@ void main() {
});
});
- group('literals', () {
- test('true', () {
+ group('Literals -', () {
+ test('Valid true', () {
expect(json.parse('true').getResult()).equals(true);
});
- test('invalid true', () {
+ test('Invalid true', () {
expect(json.parse('tr').isFailure()).isTrue();
expect(json.parse('trace').isFailure()).isTrue();
expect(json.parse('truest').isFailure()).isTrue();
});
- test('false', () {
+ test('Valid false', () {
expect(json.parse('false').getResult()).equals(false);
});
- test('invalid false', () {
+ test('Invalid false', () {
expect(json.parse('fa').isFailure()).isTrue();
expect(json.parse('falsely').isFailure()).isTrue();
expect(json.parse('fabulous').isFailure()).isTrue();
});
- test('null', () {
+ test('Valid null', () {
expect(json.parse('null').getResult()).equals(null);
});
- test('invalid null', () {
+ test('Invalid null', () {
expect(json.parse('nu').isFailure()).isTrue();
expect(json.parse('nuclear').isFailure()).isTrue();
expect(json.parse('nullified').isFailure()).isTrue();
});
- test('integer', () {
+ test('Valid integer', () {
expect(json.parse('0').getResult()).equals(0);
expect(json.parse('1').getResult()).equals(1);
expect(json.parse('-1').getResult()).equals(-1);
@@ -98,7 +98,11 @@ void main() {
expect(json.parse('1e2').getResult()).equals(100);
expect(json.parse('1e+2').getResult()).equals(100);
});
- test('float', () {
+ test('Invalid integer', () {
+ expect(json.parse('00').isFailure()).isTrue();
+ expect(json.parse('01').isFailure()).isTrue();
+ });
+ test('Valid float', () {
expect(json.parse('0.0').getResult()).equals(0.0);
expect(json.parse('0.12').getResult()).equals(0.12);
expect(json.parse('-0.12').getResult()).equals(-0.12);
@@ -107,18 +111,16 @@ void main() {
expect(json.parse('1.2e-1').getResult()).equals(1.2e-1);
expect(json.parse('1.2E-1').getResult()).equals(1.2e-1);
});
-
- test('invalid number', () {
- expect(json.parse('00').isFailure()).isTrue();
- expect(json.parse('01').isFailure()).isTrue();
- expect(json.parse('00.1').isFailure()).isTrue();
+ test('Invalid float', () {
+ expect(json.parse('.1').isFailure()).isTrue();
+ expect(json.parse('0.1.1').isFailure()).isTrue();
});
- test('string', () {
+ test('Plain string', () {
expect(json.parse('""').getResult()).equals('');
expect(json.parse('"foo"').getResult()).equals('foo');
expect(json.parse('"foo bar"').getResult()).equals('foo bar');
});
- test('escaped string', () {
+ test('Escaped string', () {
expect(json.parse(@'"\""').getResult()).equals('"');
expect(json.parse(@'"\\"').getResult()).equals('\\');
expect(json.parse(@'"\b"').getResult()).equals('\b');
@@ -127,23 +129,23 @@ void main() {
expect(json.parse(@'"\r"').getResult()).equals('\r');
expect(json.parse(@'"\t"').getResult()).equals('\t');
});
- test('invalid string', () {
+ test('Invalid string', () {
expect(json.parse('"').isFailure()).isTrue();
expect(json.parse('"a').isFailure()).isTrue();
expect(json.parse('"a\\\"').isFailure()).isTrue();
});
});
- group('browser', () {
- test('explorer', () {
+ group('Browser -', () {
+ test('Internet Explorer', () {
var input = '{"recordset": null, "type": "change", "fromElement": null, "toElement": null, "altLeft": false, "keyCode": 0, "repeat": false, "reason": 0, "behaviorCookie": 0, "contentOverflow": false, "behaviorPart": 0, "dataTransfer": null, "ctrlKey": false, "shiftLeft": false, "dataFld": "", "qualifier": "", "wheelDelta": 0, "bookmarks": null, "button": 0, "srcFilter": null, "nextPage": "", "cancelBubble": false, "x": 89, "y": 502, "screenX": 231, "screenY": 1694, "srcUrn": "", "boundElements": {"length": 0}, "clientX": 89, "clientY": 502, "propertyName": "", "shiftKey": false, "ctrlLeft": false, "offsetX": 25, "offsetY": 2, "altKey": false}';
expect(json.parse(input).isSuccess()).isTrue();
});
- test('firefox', () {
+ test('FireFox', () {
var input = '{"type": "change", "eventPhase": 2, "bubbles": true, "cancelable": true, "timeStamp": 0, "CAPTURING_PHASE": 1, "AT_TARGET": 2, "BUBBLING_PHASE": 3, "isTrusted": true, "MOUSEDOWN": 1, "MOUSEUP": 2, "MOUSEOVER": 4, "MOUSEOUT": 8, "MOUSEMOVE": 16, "MOUSEDRAG": 32, "CLICK": 64, "DBLCLICK": 128, "KEYDOWN": 256, "KEYUP": 512, "KEYPRESS": 1024, "DRAGDROP": 2048, "FOCUS": 4096, "BLUR": 8192, "SELECT": 16384, "CHANGE": 32768, "RESET": 65536, "SUBMIT": 131072, "SCROLL": 262144, "LOAD": 524288, "UNLOAD": 1048576, "XFER_DONE": 2097152, "ABORT": 4194304, "ERROR": 8388608, "LOCATE": 16777216, "MOVE": 33554432, "RESIZE": 67108864, "FORWARD": 134217728, "HELP": 268435456, "BACK": 536870912, "TEXT": 1073741824, "ALT_MASK": 1, "CONTROL_MASK": 2, "SHIFT_MASK": 4, "META_MASK": 8}';
expect(json.parse(input).isSuccess()).isTrue();
});
- test('webkit', () {
+ test('WebKit', () {
var input = '{"returnValue": true, "timeStamp": 1226697417289, "eventPhase": 2, "type": "change", "cancelable": false, "bubbles": true, "cancelBubble": false, "MOUSEOUT": 8, "FOCUS": 4096, "CHANGE": 32768, "MOUSEMOVE": 16, "AT_TARGET": 2, "SELECT": 16384, "BLUR": 8192, "KEYUP": 512, "MOUSEDOWN": 1, "MOUSEDRAG": 32, "BUBBLING_PHASE": 3, "MOUSEUP": 2, "CAPTURING_PHASE": 1, "MOUSEOVER": 4, "CLICK": 64, "DBLCLICK": 128, "KEYDOWN": 256, "KEYPRESS": 1024, "DRAGDROP": 2048}';
expect(json.parse(input).isSuccess()).isTrue();
});
View
426 test/PetitParserTests.dart
@@ -0,0 +1,426 @@
+// Copyright (c) 2012, Lukas Renggli <renggli@gmail.com>
+
+#library('PetitParserTests');
+
+#import('dart:core');
+#import('/Applications/Dart/dart-sdk/lib/unittest/unittest.dart');
+
+#import('../lib/PetitParser.dart');
+
+void expectSuccess(Parser parser, Dynamic input, Dynamic expected, [int position]) {
+ Result result = parser.parse(input);
+ expect(result.isSuccess()).isTrue();
+ expect(result.isFailure()).isFalse();
+ // TODO(renggli): compare actual objects when expect() is fixed
+ expect(result.getResult().toString()).equals(expected.toString());
+ expect(result.position).equals(position != null ? position : input.length);
+}
+
+void expectFailure(Parser parser, Dynamic input, [int position = 0, String message]) {
+ Result result = parser.parse(input);
+ expect(result.isFailure()).isTrue();
+ expect(result.isSuccess()).isFalse();
+ expect(result.position).equals(position);
+ if (message != null) {
+ expect(result.getMessage()).equals(message);
+ }
+}
+
+main() {
+
+ group('Parser -', () {
+ test('And', () {
+ Parser parser = char('a').and();
+ expectSuccess(parser, 'a', 'a', 0);
+ expectFailure(parser, 'b', message: 'a expected');
+ expectFailure(parser, '');
+ });
+ test('Choice of two', () {
+ Parser parser = char('a').or(char('b'));
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, 'b', 'b');
+ expectFailure(parser, 'c');
+ expectFailure(parser, '');
+ });
+ test('Choice of three', () {
+ Parser parser = char('a').or(char('b')).or(char('c'));
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, 'b', 'b');
+ expectSuccess(parser, 'c', 'c');
+ expectFailure(parser, 'd');
+ expectFailure(parser, '');
+ });
+ test('End of input', () {
+ Parser parser = char('a').end();
+ expectFailure(parser, '', 0, 'a expected');
+ expectSuccess(parser, 'a', 'a');
+ expectFailure(parser, 'aa', 1, 'end of input expected');
+ });
+ test('Epsilon', () {
+ Parser parser = new EpsilonParser();
+ expectSuccess(parser, '', null);
+ expectSuccess(parser, 'a', null, 0);
+ });
+ test('Failure', () {
+ Parser parser = new FailureParser('failure');
+ expectFailure(parser, '', 0, 'failure');
+ expectFailure(parser, 'a', 0, 'failure');
+ });
+ test('Flatten', () {
+ Parser parser = digit().plus().flatten();
+ expectFailure(parser, '');
+ expectFailure(parser, 'a');
+ expectSuccess(parser, '1', '1');
+ expectSuccess(parser, '12', '12');
+ expectSuccess(parser, '123', '123');
+ expectSuccess(parser, '1234', '1234');
+ });
+ test('Action', () {
+ Parser parser = digit().map((String each) {
+ return each.charCodeAt(0) - '0'.charCodeAt(0);
+ });
+ expectSuccess(parser, '1', 1);
+ expectSuccess(parser, '4', 4);
+ expectSuccess(parser, '9', 9);
+ expectFailure(parser, '');
+ expectFailure(parser, 'a');
+ });
+ test('Not', () {
+ Parser parser = char('a').not('not a expected');
+ expectFailure(parser, 'a', message: 'not a expected');
+ expectSuccess(parser, 'b', null, 0);
+ expectSuccess(parser, '', null);
+ });
+ test('Neg', () {
+ Parser parser = digit().neg('no digit expected');
+ expectFailure(parser, '1', 0, 'no digit expected');
+ expectFailure(parser, '9', 0, 'no digit expected');
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, ' ', ' ');
+ expectFailure(parser, '', 0, 'input expected');
+ });
+ test('Optional', () {
+ Parser parser = char('a').optional();
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, 'b', null, 0);
+ expectSuccess(parser, '', null);
+ });
+ test('Plus', () {
+ Parser parser = char('a').plus();
+ expectFailure(parser, '', message: 'a expected');
+ expectSuccess(parser, 'a', ['a']);
+ expectSuccess(parser, 'aa', ['a', 'a']);
+ expectSuccess(parser, 'aaa', ['a', 'a', 'a']);
+ });
+ test('Times', () {
+ Parser parser = char('a').times(2);
+ expectFailure(parser, '', 0, 'a expected');
+ expectFailure(parser, 'a', 1, 'a expected');
+ expectSuccess(parser, 'aa', ['a', 'a']);
+ expectSuccess(parser, 'aaa', ['a', 'a'], 2);
+ });
+ test('Repeat', () {
+ Parser parser = char('a').repeat(2, 3);
+ expectFailure(parser, '', 0, 'a expected');
+ expectFailure(parser, 'a', 1, 'a expected');
+ expectSuccess(parser, 'aa', ['a', 'a']);
+ expectSuccess(parser, 'aaa', ['a', 'a', 'a']);
+ expectSuccess(parser, 'aaaa', ['a', 'a', 'a'], 3);
+ });
+ test('Separated by', () {
+ Parser parser = char('a').separatedBy(char('b'));
+ expectFailure(parser, '', 0, 'a expected');
+ expectSuccess(parser, 'a', ['a']);
+ expectSuccess(parser, 'ab', ['a'], 1);
+ expectSuccess(parser, 'aba', ['a', 'b', 'a']);
+ expectSuccess(parser, 'abab', ['a', 'b', 'a'], 3);
+ expectSuccess(parser, 'ababa', ['a', 'b', 'a', 'b', 'a']);
+ expectSuccess(parser, 'ababab', ['a', 'b', 'a', 'b', 'a'], 5);
+ });
+ test('Sequence of two', () {
+ Parser parser = char('a').seq(char('b'));
+ expectSuccess(parser, 'ab', ['a', 'b']);
+ expectFailure(parser, '');
+ expectFailure(parser, 'x');
+ expectFailure(parser, 'a', 1);
+ expectFailure(parser, 'ax', 1);
+ });
+ test('Sequence of three', () {
+ Parser parser = char('a').seq(char('b')).seq(char('c'));
+ expectSuccess(parser, 'abc', ['a', 'b', 'c']);
+ expectFailure(parser, '');
+ expectFailure(parser, 'x');
+ expectFailure(parser, 'a', 1);
+ expectFailure(parser, 'ax', 1);
+ expectFailure(parser, 'ab', 2);
+ expectFailure(parser, 'abx', 2);
+ });
+ test('Star', () {
+ Parser parser = char('a').star();
+ expectSuccess(parser, '', []);
+ expectSuccess(parser, 'a', ['a']);
+ expectSuccess(parser, 'aa', ['a', 'a']);
+ expectSuccess(parser, 'aaa', ['a', 'a', 'a']);
+ });
+ test('Trim', () {
+ Parser parser = char('a').trim();
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, ' a', 'a');
+ expectSuccess(parser, 'a ', 'a');
+ expectSuccess(parser, ' a ', 'a');
+ expectSuccess(parser, ' a', 'a');
+ expectSuccess(parser, 'a ', 'a');
+ expectSuccess(parser, ' a ', 'a');
+ expectFailure(parser, '', message: 'a expected');
+ expectFailure(parser, 'b', message: 'a expected');
+ expectFailure(parser, ' b', 1, 'a expected');
+ expectFailure(parser, ' b', 2, 'a expected');
+ });
+ test('Trim custom', () {
+ Parser parser = char('a').trim(char('*'));
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, '*a', 'a');
+ expectSuccess(parser, 'a*', 'a');
+ expectSuccess(parser, '*a*', 'a');
+ expectSuccess(parser, '**a', 'a');
+ expectSuccess(parser, 'a**', 'a');
+ expectSuccess(parser, '**a**', 'a');
+ expectFailure(parser, '', message: 'a expected');
+ expectFailure(parser, 'b', message: 'a expected');
+ expectFailure(parser, '*b', 1, 'a expected');
+ expectFailure(parser, '**b', 2, 'a expected');
+ });
+ test('Wrapped', () {
+ Parser parser = char('a').wrapper();
+ expectSuccess(parser, 'a', 'a');
+ expectFailure(parser, 'b', message: 'a expected');
+ expectFailure(parser, '');
+ });
+ });
+
+ group('Predicate -', () {
+ test('Any', () {
+ Parser parser = any();
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, 'b', 'b');
+ expectFailure(parser, '', message: 'input expected');
+ });
+ test('Char', () {
+ Parser parser = char('a');
+ expectSuccess(parser, 'a', 'a');
+ expectFailure(parser, 'b');
+ expectFailure(parser, '');
+ });
+ test('String', () {
+ Parser parser = string('foo');
+ expectSuccess(parser, 'foo', 'foo');
+ expectFailure(parser, '');
+ expectFailure(parser, 'f');
+ expectFailure(parser, 'fo');
+ expectFailure(parser, 'Foo');
+ });
+ test('String ignore case', () {
+ Parser parser = stringIgnoreCase('foo');
+ expectSuccess(parser, 'foo', 'foo');
+ expectSuccess(parser, 'FOO', 'FOO');
+ expectSuccess(parser, 'fOo', 'fOo');
+ expectFailure(parser, '');
+ expectFailure(parser, 'f');
+ expectFailure(parser, 'Fo');
+ });
+ test('Pattern with characters', () {
+ Parser parser = pattern('abc');
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, 'b', 'b');
+ expectSuccess(parser, 'c', 'c');
+ expectFailure(parser, 'd');
+ });
+ test('Pattern with range of characters', () {
+ Parser parser = pattern('a-c');
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, 'b', 'b');
+ expectSuccess(parser, 'c', 'c');
+ expectFailure(parser, 'd');
+ });
+ test('Pattern with negation', () {
+ Parser parser = pattern('^a-cd');
+ expectFailure(parser, 'a');
+ expectFailure(parser, 'b');
+ expectFailure(parser, 'c');
+ expectFailure(parser, 'd');
+ expectSuccess(parser, 'e', 'e');
+ });
+ test('Digit', () {
+ Parser parser = digit();
+ expectSuccess(parser, '1', '1');
+ expectSuccess(parser, '9', '9');
+ expectFailure(parser, 'a', message: 'digit expected');
+ expectFailure(parser, '');
+ });
+ test('Letter', () {
+ Parser parser = letter();
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, 'X', 'X');
+ expectFailure(parser, '0', message: 'letter expected');
+ expectFailure(parser, '');
+ });
+ test('Lowercase', () {
+ Parser parser = lowercase();
+ expectSuccess(parser, 'a', 'a');
+ expectFailure(parser, 'A', message: 'lowercase letter expected');
+ expectFailure(parser, '0', message: 'lowercase letter expected');
+ expectFailure(parser, '');
+ });
+ test('Range', () {
+ Parser parser = range('e', 'o');
+ expectFailure(parser, 'd', message: 'e..o expected');
+ expectSuccess(parser, 'e', 'e');
+ expectSuccess(parser, 'i', 'i');
+ expectSuccess(parser, 'o', 'o');
+ expectFailure(parser, 'p', message: 'e..o expected');
+ });
+ test('Uppercase', () {
+ Parser parser = uppercase();
+ expectSuccess(parser, 'Z', 'Z');
+ expectFailure(parser, 'z', message: 'uppercase letter expected');
+ expectFailure(parser, '0', message: 'uppercase letter expected');
+ expectFailure(parser, '');
+ });
+ test('Whitespace', () {
+ Parser parser = whitespace();
+ expectSuccess(parser, ' ', ' ');
+ expectFailure(parser, 'z', message: 'whitespace expected');
+ expectFailure(parser, '-', message: 'whitespace expected');
+ expectFailure(parser, '');
+ });
+ test('Word', () {
+ Parser parser = word();
+ expectSuccess(parser, 'a', 'a');
+ expectSuccess(parser, '0', '0');
+ expectFailure(parser, '-', message: 'letter or digit expected');
+ expectFailure(parser, '');
+ });
+ });
+
+ group('Parsing -', () {
+ test('Parse', () {
+ Parser parser = char('a');
+ expect(parser.parse('a').isSuccess()).isTrue();
+ expect(parser.parse('b').isSuccess()).isFalse();
+ });
+ test('Accept', () {
+ Parser parser = char('a');
+ expect(parser.accept('a')).isTrue();
+ expect(parser.accept('b')).isFalse();
+ });
+ test('Matches', () {
+ Parser parser = digit().seq(digit()).flatten();
+ // TODO(renggli): compare actual objects when expect() is fixed
+ expect(['12', '23', '45'].toString()).equals(parser.matches('a123b45').toString());
+ });
+ test('Matches skipping', () {
+ Parser parser = digit().seq(digit()).flatten();
+ // TODO(renggli): compare actual objects when expect() is fixed
+ expect(['12', '45'].toString()).equals(parser.matchesSkipping('a123b45').toString());
+ });
+ });
+
+ group('Examples -', () {
+ final Parser IDENTIFIER = letter().seq(word().star()).flatten();
+ final Parser NUMBER = char('-').optional().seq(digit().plus())
+ .seq(char('.').seq(digit().plus()).optional()).flatten();
+ final Parser STRING = char('"')
+ .seq(char('"').neg().star()).seq(char('"')).flatten();
+ final Parser RETURN = string('return')
+ .seq(whitespace().plus().flatten()).seq(IDENTIFIER.or(NUMBER).or(STRING))
+ .map((list) => list.last());
+ final Parser JAVADOC = string('/**')
+ .seq(string('*/').neg().star())
+ .seq(string('*/'))
+ .flatten();
+ test('Valid identifier', () {
+ expectSuccess(IDENTIFIER, 'a', 'a');
+ expectSuccess(IDENTIFIER, 'a1', 'a1');
+ expectSuccess(IDENTIFIER, 'a12', 'a12');
+ expectSuccess(IDENTIFIER, 'ab', 'ab');
+ expectSuccess(IDENTIFIER, 'a1b', 'a1b');
+ });
+ test('Incomplete identifier', () {
+ expectSuccess(IDENTIFIER, 'a=', 'a', 1);
+ expectSuccess(IDENTIFIER, 'a1-', 'a1', 2);
+ expectSuccess(IDENTIFIER, 'a12+', 'a12', 3);
+ expectSuccess(IDENTIFIER, 'ab ', 'ab', 2);
+ });
+ test('Invalid identifier', () {
+ expectFailure(IDENTIFIER, '', 0, 'letter expected');
+ expectFailure(IDENTIFIER, '1', 0, 'letter expected');
+ expectFailure(IDENTIFIER, '1a', 0, 'letter expected');
+ });
+ test('Positive number', () {
+ expectSuccess(NUMBER, '1', '1');
+ expectSuccess(NUMBER, '12', '12');
+ expectSuccess(NUMBER, '12.3', '12.3');
+ expectSuccess(NUMBER, '12.34', '12.34');
+ });
+ test('Negative number', () {
+ expectSuccess(NUMBER, '-1', '-1');
+ expectSuccess(NUMBER, '-12', '-12');
+ expectSuccess(NUMBER, '-12.3', '-12.3');
+ expectSuccess(NUMBER, '-12.34', '-12.34');
+ });
+ test('Incomplete number', () {
+ expectSuccess(NUMBER, '1..', '1', 1);
+ expectSuccess(NUMBER, '12-', '12', 2);
+ expectSuccess(NUMBER, '12.3.', '12.3', 4);
+ expectSuccess(NUMBER, '12.34.', '12.34', 5);
+ });
+ test('Invalid number', () {
+ expectFailure(NUMBER, '', 0, 'digit expected');
+ expectFailure(NUMBER, '-', 1, 'digit expected');
+ expectFailure(NUMBER, '-x', 1, 'digit expected');
+ expectFailure(NUMBER, '.', 0, 'digit expected');
+ expectFailure(NUMBER, '.1', 0, 'digit expected');
+ });
+ test('Valid string', () {
+ expectSuccess(STRING, '""', '""');
+ expectSuccess(STRING, '"a"', '"a"');
+ expectSuccess(STRING, '"ab"', '"ab"');
+ expectSuccess(STRING, '"abc"', '"abc"');
+ });
+ test('Incomplete string', () {
+ expectSuccess(STRING, '""x', '""', 2);
+ expectSuccess(STRING, '"a"x', '"a"', 3);
+ expectSuccess(STRING, '"ab"x', '"ab"', 4);
+ expectSuccess(STRING, '"abc"x', '"abc"', 5);
+ });
+ test('Invalid string', () {
+ expectFailure(STRING, '"', 1, '" expected');
+ expectFailure(STRING, '"a', 2, '" expected');
+ expectFailure(STRING, '"ab', 3, '" expected');
+ expectFailure(STRING, 'a"', 0, '" expected');
+ expectFailure(STRING, 'ab"', 0, '" expected');
+ });
+ test('Return statement', () {
+ expectSuccess(RETURN, 'return f', 'f');
+ expectSuccess(RETURN, 'return f', 'f');
+ expectSuccess(RETURN, 'return foo', 'foo');
+ expectSuccess(RETURN, 'return foo', 'foo');
+ expectSuccess(RETURN, 'return 1', '1');
+ expectSuccess(RETURN, 'return 1', '1');
+ expectSuccess(RETURN, 'return -2.3', '-2.3');
+ expectSuccess(RETURN, 'return -2.3', '-2.3');
+ expectSuccess(RETURN, 'return "a"', '"a"');
+ expectSuccess(RETURN, 'return "a"', '"a"');
+ });
+ test('Invalid statement', () {
+ expectFailure(RETURN, 'retur f', 0, 'return expected');
+ expectFailure(RETURN, 'return1', 6, 'whitespace expected');
+ expectFailure(RETURN, 'return _', 8, '" expected');
+ });
+ test('Javadoc', () {
+ expectSuccess(JAVADOC, '/** foo */', '/** foo */');
+ expectSuccess(JAVADOC, '/** * * */', '/** * * */');
+ });
+ });
+
+}
View
28 grammars/xml/XmlTests.dart → test/XmlTests.dart
@@ -4,8 +4,8 @@
#import('/Applications/Dart/dart-sdk/lib/unittest/unittest.dart');
-#import('../../lib/PetitParser.dart');
-#import('Xml.dart');
+#import('../lib/PetitParser.dart');
+#import('../grammar/xml/Xml.dart');
void validate(Parser parser, String input) {
XmlNode tree = parser.parse(input).getResult();
@@ -113,13 +113,13 @@ void assertAttributeInvariant(XmlNode xml) {
void main() {
final Parser parser = new XmlParser();
- test('comment', () {
+ test('Comment', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?><schema><!-- comment --></schema>');
});
- test('comment with xml', () {
+ test('Comment with xml', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?><schema><!-- <foo></foo> --></schema>');
});
- test('complicated', () {
+ test('Complicated', () {
validate(parser, '<?xml foo?>\n'
'<foo>\n'
' <bar a="fasdfasdf">\n'
@@ -129,31 +129,31 @@ void main() {
' <!-- with comment -->\n'
'</foo>');
});
- test('doctype', () {
+ test('Doctype', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?>\n'
' <!DOCTYPE freaking <schema> [ <!-- schema --> ] >\n'
' <schema></schema>');
});
- test('empty element', () {
+ test('Empty element', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?><schema/>');
});
- test('namespace', () {
+ test('Namespace', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?><xs:schema></xs:schema>');
});
- test('simple', () {
+ test('Simple', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?><schema></schema>');
});
- test('simple attribute', () {
+ test('Simple attribute', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?><schema foo="bar"></schema>');
});
- test('simple single quote attribute', () {
+ test('Simple single quote attribute', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?><schema foo=\'bar\'></schema>');
});
- test('whitespace after prolog', () {
+ test('Whitespace after prolog', () {
validate(parser, '<?xml version="1.0" encoding="UTF-8"?>\n'
' <schema></schema>\n');
});
- test('bookstore', () {
+ test('Bookstore', () {
validate(parser, '<?xml version="1.0" encoding="ISO-8859-1"?>\n'
'<bookstore>\n'
' <book>\n'
@@ -166,7 +166,7 @@ void main() {
' </book>\n'
'</bookstore>');
});
- test('shiporder', () {
+ test('Shiporder', () {
validate(parser, '<?xml version="1.0"?>\n'
'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">\n'
'\n'

0 comments on commit 628a9cc

Please sign in to comment.