11//This file will likely change a lot! Very experimental!
2+ /*global StringReader*/
23var ValidationTypes ;
34
45/**
@@ -34,6 +35,87 @@ Matcher.prec = {
3435 ALT : 1
3536} ;
3637
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+
37119/**
38120 * Convert a string to a matcher (parsing simple alternations),
39121 * or do nothing if the argument is already a matcher.
@@ -42,10 +124,7 @@ Matcher.cast = function(m) {
42124 if ( m instanceof Matcher ) {
43125 return m ;
44126 }
45- if ( / \| / . test ( m ) ) {
46- return Matcher . alt . apply ( Matcher , m . split ( " | " ) ) ;
47- }
48- return Matcher . fromType ( m ) ;
127+ return Matcher . parse ( m ) ;
49128} ;
50129
51130/**
0 commit comments