1
1
//This file will likely change a lot! Very experimental!
2
+ /*global StringReader*/
2
3
var ValidationTypes ;
3
4
4
5
/**
@@ -34,6 +35,87 @@ Matcher.prec = {
34
35
ALT : 1
35
36
} ;
36
37
38
+ /** Simple recursive-descent grammar to build matchers from strings. */
39
+ Matcher . parse = function ( str ) {
40
+ var reader , eat , expr , oror , andand , seq , mod , term , result ;
41
+ reader = new StringReader ( str ) ;
42
+ eat = function ( matcher ) {
43
+ var result = reader . readMatch ( matcher ) ;
44
+ if ( result === null ) {
45
+ throw new SyntaxError (
46
+ "Expected " + matcher , reader . getLine ( ) , reader . getCol ( ) ) ;
47
+ }
48
+ return result ;
49
+ } ;
50
+ expr = function ( ) {
51
+ // expr = oror (" | " oror)*
52
+ var m = [ oror ( ) ] ;
53
+ while ( reader . readMatch ( " | " ) !== null ) {
54
+ m . push ( oror ( ) ) ;
55
+ }
56
+ return m . length === 1 ? m [ 0 ] : Matcher . alt . apply ( Matcher , m ) ;
57
+ } ;
58
+ oror = function ( ) {
59
+ // oror = andand ( " || " andand)*
60
+ var m = [ andand ( ) ] ;
61
+ while ( reader . readMatch ( " || " ) !== null ) {
62
+ m . push ( andand ( ) ) ;
63
+ }
64
+ return m . length === 1 ? m [ 0 ] : Matcher . oror . apply ( Matcher , m ) ;
65
+ } ;
66
+ andand = function ( ) {
67
+ // andand = seq ( " && " seq)*
68
+ var m = [ seq ( ) ] ;
69
+ while ( reader . readMatch ( " && " ) !== null ) {
70
+ m . push ( seq ( ) ) ;
71
+ }
72
+ return m . length === 1 ? m [ 0 ] : Matcher . andand . apply ( Matcher , m ) ;
73
+ } ;
74
+ seq = function ( ) {
75
+ // seq = mod ( " " mod)*
76
+ var m = [ mod ( ) ] ;
77
+ while ( reader . readMatch ( / ^ (? ! [ & | \] ] ) / ) !== null ) {
78
+ m . push ( mod ( ) ) ;
79
+ }
80
+ return m . length === 1 ? m [ 0 ] : Matcher . seq . apply ( Matcher , m ) ;
81
+ } ;
82
+ mod = function ( ) {
83
+ // mod = term ( "?" | "*" | "+" | "#" | "{<num>,<num>}" )?
84
+ var m = term ( ) ;
85
+ if ( reader . readMatch ( "?" ) !== null ) {
86
+ return m . question ( ) ;
87
+ } else if ( reader . readMatch ( "*" ) !== null ) {
88
+ return m . star ( ) ;
89
+ } else if ( reader . readMatch ( "+" ) !== null ) {
90
+ return m . plus ( ) ;
91
+ } else if ( reader . readMatch ( "#" ) !== null ) {
92
+ return m . hash ( ) ;
93
+ } else if ( reader . readMatch ( / ^ \{ \s * / ) !== null ) {
94
+ var min = eat ( / ^ \d + / ) ;
95
+ eat ( / ^ \s * , \s * / ) ;
96
+ var max = eat ( / ^ \d + / ) ;
97
+ eat ( / ^ \s * \} / ) ;
98
+ return m . braces ( + min , + max ) ;
99
+ }
100
+ return m ;
101
+ } ;
102
+ term = function ( ) {
103
+ // term = <nt> | literal | "[ " expression " ]"
104
+ if ( reader . readMatch ( "[ " ) !== null ) {
105
+ var m = expr ( ) ;
106
+ eat ( " ]" ) ;
107
+ return m ;
108
+ }
109
+ return Matcher . fromType ( eat ( / ^ [ ^ ? * + # { ] + / ) ) ;
110
+ } ;
111
+ result = expr ( ) ;
112
+ if ( ! reader . eof ( ) ) {
113
+ throw new SyntaxError (
114
+ "Expected end of string" , reader . getLine ( ) , reader . getCol ( ) ) ;
115
+ }
116
+ return result ;
117
+ } ;
118
+
37
119
/**
38
120
* Convert a string to a matcher (parsing simple alternations),
39
121
* or do nothing if the argument is already a matcher.
@@ -42,10 +124,7 @@ Matcher.cast = function(m) {
42
124
if ( m instanceof Matcher ) {
43
125
return m ;
44
126
}
45
- if ( / \| / . test ( m ) ) {
46
- return Matcher . alt . apply ( Matcher , m . split ( " | " ) ) ;
47
- }
48
- return Matcher . fromType ( m ) ;
127
+ return Matcher . parse ( m ) ;
49
128
} ;
50
129
51
130
/**
0 commit comments