@@ -2,47 +2,82 @@ import 'package:petitparser/definition.dart';
22import 'package:petitparser/expression.dart' ;
33import 'package:petitparser/parser.dart' ;
44
5+ import 'classes.dart' ;
56import 'node.dart' ;
67
7- final nodeParser = () {
8- final builder = ExpressionBuilder <Node >();
8+ class RegexpParserDefinition extends GrammarDefinition <Node > {
9+ Parser <Node > escape () => any ()
10+ .skip (before: char (r'\' ))
11+ .map ((char) => escapeClasses[char] ?? LiteralNode (char));
12+ Parser <Node > dot () => char ('.' ).map ((_) => DotNode ());
13+ Parser <Node > startAnchor () => char ('^' ).map ((_) => StartAnchorNode ());
14+ Parser <Node > endAnchor () => char (r'$' ).map ((_) => EndAnchorNode ());
15+ Parser <Node > other () => noneOf ('()!|&' ).map ((char) => LiteralNode (char));
916
10- const meta = r'\.()!*+?|&^$' ;
11- builder
12- ..primitive (noneOf (meta).map (LiteralNode .new ))
13- ..primitive (anyOf (meta).skip (before: char (r'\' )).map (LiteralNode .new ))
14- ..primitive (char ('.' ).map ((_) => DotNode ()))
15- ..primitive (char ('^' ).map ((_) => StartAnchorNode ()))
16- ..primitive (char (r'$' ).map ((_) => EndAnchorNode ()));
17+ Parser <Node > charClass () => seq2 (char ('^' ).optional (), ref0 (charClassItems))
18+ .map2 ((negate, items) => negate != null ? ComplementNode (items) : items)
19+ .skip (before: char ('[' ), after: char (']' ));
20+ Parser <Node > charClassItems () => ref0 (
21+ charClassItem,
22+ ).plus ().map ((items) => items.reduce (AlternationNode .new ));
23+ Parser <Node > charClassItem () => [
24+ ref0 (charClassRange),
25+ ref0 (escape),
26+ noneOf (']' ).map ((char) => LiteralNode (char)),
27+ ].toChoiceParser ();
28+ Parser <Node > charClassRange () => seq3 (
29+ any (),
30+ char ('-' ),
31+ any (),
32+ ).map3 ((start, _, end) => RangeNode (start, end));
1733
18- builder.group ().wrapper (char ('(' ), char (')' ), (_, value, _) => value);
19-
20- final integer = digit ().plusString ().trim ().map (int .parse);
21- final range =
22- seq3 (integer.optional (), char (',' ).trim ().optional (), integer.optional ())
34+ Parser <int > integer () => digit ().plusString ().trim ().map (int .parse);
35+ Parser <({int min, int ? max})> range () =>
36+ seq3 (
37+ ref0 (integer).optional (),
38+ char (',' ).trim ().optional (),
39+ ref0 (integer).optional (),
40+ )
2341 .skip (before: char ('{' ), after: char ('}' ))
2442 .map3 (
2543 (min, comma, max) =>
26- (min ?? 0 , max ?? (comma == null ? min ?? 0 : null )),
44+ (min: min ?? 0 , max : max ?? (comma == null ? min ?? 0 : null )),
2745 );
2846
29- builder.group ()
30- ..prefix (char ('!' ), (_, exp) => ComplementNode (exp))
31- ..postfix (char ('*' ), (exp, _) => QuantificationNode (exp, 0 ))
32- ..postfix (char ('+' ), (exp, _) => QuantificationNode (exp, 1 ))
33- ..postfix (char ('?' ), (exp, _) => QuantificationNode (exp, 0 , 1 ))
34- ..postfix (
35- range,
36- (exp, range) => QuantificationNode (exp, range.$1, range.$2),
37- );
38-
39- builder.group ()
40- ..left (epsilon (), (left, _, right) => ConcatenationNode (left, right))
41- ..optional (EmptyNode ());
42-
43- builder.group ()
44- ..left (char ('|' ), (left, _, right) => AlternationNode (left, right))
45- ..left (char ('&' ), (left, _, right) => IntersectionNode (left, right));
46-
47- return resolve (builder.build ()).end ();
48- }();
47+ @override
48+ Parser <Node > start () {
49+ final builder = ExpressionBuilder <Node >();
50+
51+ builder
52+ ..primitive (ref0 (dot))
53+ ..primitive (ref0 (startAnchor))
54+ ..primitive (ref0 (endAnchor))
55+ ..primitive (ref0 (charClass))
56+ ..primitive (ref0 (escape))
57+ ..primitive (ref0 (other));
58+
59+ builder.group ().wrapper (char ('(' ), char (')' ), (_, value, _) => value);
60+
61+ builder.group ()
62+ ..prefix (char ('!' ), (_, exp) => ComplementNode (exp))
63+ ..postfix (char ('*' ), (exp, _) => QuantificationNode (exp, 0 ))
64+ ..postfix (char ('+' ), (exp, _) => QuantificationNode (exp, 1 ))
65+ ..postfix (char ('?' ), (exp, _) => QuantificationNode (exp, 0 , 1 ))
66+ ..postfix (
67+ ref0 (range),
68+ (exp, range) => QuantificationNode (exp, range.min, range.max),
69+ );
70+
71+ builder.group ()
72+ ..left (epsilon (), (left, _, right) => ConcatenationNode (left, right))
73+ ..optional (EmptyNode ());
74+
75+ builder.group ()
76+ ..left (char ('|' ), (left, _, right) => AlternationNode (left, right))
77+ ..left (char ('&' ), (left, _, right) => IntersectionNode (left, right));
78+
79+ return resolve (builder.build ()).end ();
80+ }
81+ }
82+
83+ final nodeParser = RegexpParserDefinition ().build ();
0 commit comments