@@ -58,14 +58,14 @@ fn func0(func_name: &str, constructor: Expr, args: Vec<Expr>) -> Result<Expr, St
5858struct FuncContext < ' src > {
5959 func_name : & ' src str ,
6060 func_name_span : SimpleSpan ,
61- args : Vec < Option < ( Expr , & ' src str , SimpleSpan ) > > ,
61+ args : Vec < Option < ( FuncArgument , & ' src str , SimpleSpan ) > > ,
6262}
6363
6464impl < ' src > FuncContext < ' src > {
6565 fn new (
6666 func_name : & ' src str ,
6767 func_name_span : SimpleSpan ,
68- args : Vec < ( Expr , & ' src str , SimpleSpan ) > ,
68+ args : Vec < ( FuncArgument , & ' src str , SimpleSpan ) > ,
6969 ) -> Self {
7070 Self {
7171 func_name,
@@ -108,45 +108,103 @@ impl<'src> FuncContext<'src> {
108108 format ! ( "Unknown function `{}`" , self . func_name) ,
109109 ) )
110110 }
111- }
112111
113- trait GetArg < ' src , T > {
114- fn get ( & mut self , index : usize ) -> Result < T , Rich < ' src , char > > ;
115- }
116-
117- impl < ' src > GetArg < ' src , String > for FuncContext < ' src > {
118- fn get ( & mut self , index : usize ) -> Result < String , Rich < ' src , char > > {
112+ fn get_arg (
113+ & mut self ,
114+ index : usize ,
115+ ) -> Result < ( FuncArgument , & ' src str , SimpleSpan ) , Rich < ' src , char > > {
119116 if index >= self . args . len ( ) {
120117 return Err ( Rich :: custom (
121118 self . func_name_span ,
122119 format ! ( "function {} missing argumnt {}" , self . func_name, index + 1 ) ,
123120 ) ) ;
124121 }
125122
126- let arg = self . args [ index]
123+ Ok ( self . args [ index]
127124 . take ( )
128- . expect ( "arguments are used only once" ) ;
125+ . expect ( "arguments are used only once" ) )
126+ }
127+
128+ fn arg_type_err (
129+ & self ,
130+ src : & ' src str ,
131+ span : SimpleSpan ,
132+ arg_index : usize ,
133+ expected : & ' static str ,
134+ ) -> Rich < ' src , char > {
135+ Rich :: custom (
136+ span,
137+ format ! (
138+ "expected `{expected}` argument at position `{}` of function `{}`, but got `{src}`" ,
139+ arg_index + 1 ,
140+ self . func_name,
141+ ) ,
142+ )
143+ }
144+ }
129145
130- if let Expr :: Literal ( ExprValue :: String ( value) ) = arg. 0 {
146+ trait GetArg < ' src , T > {
147+ fn get ( & mut self , index : usize ) -> Result < T , Rich < ' src , char > > ;
148+ }
149+
150+ impl < ' src > GetArg < ' src , String > for FuncContext < ' src > {
151+ fn get ( & mut self , index : usize ) -> Result < String , Rich < ' src , char > > {
152+ let arg = self . get_arg ( index) ?;
153+ if let FuncArgument :: Expression ( Expr :: Literal ( ExprValue :: String ( value) ) ) = arg. 0 {
131154 Ok ( value)
132155 } else {
133- Err ( Rich :: custom (
134- arg. 2 ,
135- format ! (
136- "expected `String` argument at position `{}` of function `{}`, but got `{}`" ,
137- index + 1 ,
138- self . func_name,
139- arg. 1 ,
140- ) ,
141- ) )
156+ Err ( self . arg_type_err ( arg. 1 , arg. 2 , index, "String" ) )
142157 }
143158 }
144159}
145160
161+ impl < ' src > GetArg < ' src , Vec < Expr > > for FuncContext < ' src > {
162+ fn get ( & mut self , index : usize ) -> Result < Vec < Expr > , Rich < ' src , char > > {
163+ let arg = self . get_arg ( index) ?;
164+ if let FuncArgument :: Array ( arr) = arg. 0 {
165+ Ok ( arr)
166+ } else {
167+ dbg ! ( & arg. 0 ) ;
168+ Err ( self . arg_type_err ( arg. 1 , arg. 2 , index, "[Array]" ) )
169+ }
170+ }
171+ }
172+
173+ #[ derive( Debug ) ]
174+ enum FuncArgument {
175+ Expression ( Expr ) ,
176+ Array ( Vec < Expr > ) ,
177+ Tuple ( Vec < Expr > ) ,
178+ }
179+
180+ fn func_arg < ' src > (
181+ expr_parser : impl Parser < ' src , & ' src str , Expr , Error < ' src > > + Clone + ' src ,
182+ ) -> impl Parser < ' src , & ' src str , FuncArgument , Error < ' src > > {
183+ let expr = expr_parser. clone ( ) . map ( FuncArgument :: Expression ) ;
184+
185+ let array = expr_parser
186+ . clone ( )
187+ . separated_by ( just ( ',' ) )
188+ . allow_trailing ( )
189+ . collect :: < Vec < _ > > ( )
190+ . delimited_by ( just ( '[' ) , just ( ']' ) )
191+ . map ( FuncArgument :: Array ) ;
192+
193+ let tuple = expr_parser
194+ . separated_by ( just ( ',' ) )
195+ . at_least ( 2 )
196+ . allow_trailing ( )
197+ . collect :: < Vec < _ > > ( )
198+ . delimited_by ( just ( '(' ) , just ( ')' ) )
199+ . map ( FuncArgument :: Tuple ) ;
200+
201+ choice ( ( array, tuple, expr) ) . padded ( )
202+ }
203+
146204fn func_call < ' src > (
147205 expr_parser : impl Parser < ' src , & ' src str , Expr , Error < ' src > > + Clone + ' src ,
148206) -> impl Parser < ' src , & ' src str , Expr , Error < ' src > > {
149- let arg_list = expr_parser
207+ let arg_list = func_arg ( expr_parser)
150208 . map_with ( |expr, e| ( expr, e. slice ( ) , e. span ( ) ) )
151209 . separated_by ( just ( ',' ) )
152210 . allow_trailing ( )
@@ -156,9 +214,12 @@ fn func_call<'src>(
156214 ident ( )
157215 . map_with ( |func_name, e| ( func_name, e. span ( ) ) )
158216 . then ( arg_list)
217+ . padded ( )
159218 . validate ( |( ( func_name, func_name_span) , args) , e, emitter| {
160219 let mut c = FuncContext :: new ( func_name, func_name_span, args) ;
161220 let res = match func_name {
221+ "any" => c. args1 ( Expr :: Any ) ,
222+ "all" => c. args1 ( Expr :: All ) ,
162223 "zoom" => Ok ( Expr :: Zoom ) ,
163224 "get" => c. args1 ( Expr :: Get ) ,
164225 _ => c. unknown ( ) ,
@@ -180,6 +241,7 @@ fn func_call<'src>(
180241
181242fn property < ' src > ( ) -> impl Parser < ' src , & ' src str , Expr , Error < ' src > > {
182243 ident ( )
244+ . padded ( )
183245 . map ( |name| Expr :: Get ( name. to_string ( ) ) )
184246 . labelled ( "property name" )
185247}
@@ -311,13 +373,14 @@ fn literal<'src>() -> impl Parser<'src, &'src str, Expr, Error<'src>> {
311373 number_literal ( ) ,
312374 string_literal ( ) . map ( ExprValue :: from) ,
313375 ) )
376+ . padded ( )
314377 . map ( Expr :: Literal )
315378 . then_ignore ( atom_boundary ( ) . rewind ( ) )
316379 . labelled ( "literal" )
317380}
318381
319382fn atom_boundary < ' src > ( ) -> impl Parser < ' src , & ' src str , ( ) , Error < ' src > > {
320- choice ( ( operator ( ) . ignored ( ) , one_of ( "()" ) . ignored ( ) , end ( ) ) )
383+ choice ( ( operator ( ) . ignored ( ) , one_of ( "()[], " ) . ignored ( ) , end ( ) ) )
321384}
322385
323386#[ cfg( test) ]
@@ -342,12 +405,18 @@ mod tests {
342405 ( "0042" , 42.0 . into ( ) ) ,
343406 ( "1.25e2" , 125.0 . into ( ) ) ,
344407 ( "1.25e-2" , 0.0125 . into ( ) ) ,
408+ ( " 42" , 42.0 . into ( ) ) ,
409+ ( "\t 42" , 42.0 . into ( ) ) ,
410+ ( "42 " , 42.0 . into ( ) ) ,
411+ ( " 42 " , 42.0 . into ( ) ) ,
345412 ( "true" , true . into ( ) ) ,
346413 ( "false" , false . into ( ) ) ,
414+ ( " false " , false . into ( ) ) ,
347415 ( "#FFAA00" , Color :: from_hex ( "#FFAA00" ) . into ( ) ) ,
348416 ( "#FFAA00CC" , Color :: from_hex ( "#FFAA00CC" ) . into ( ) ) ,
349417 ( "#ffaa00" , Color :: from_hex ( "#FFAA00" ) . into ( ) ) ,
350418 ( "#fFaA00" , Color :: from_hex ( "#FFAA00" ) . into ( ) ) ,
419+ ( " #fFaA00 " , Color :: from_hex ( "#FFAA00" ) . into ( ) ) ,
351420 ( r#""text""# , "text" . to_string ( ) . into ( ) ) ,
352421 ( r#""Текст!ёё""# , "Текст!ёё" . to_string ( ) . into ( ) ) ,
353422 ( r#""택스트""# , "택스트" . to_string ( ) . into ( ) ) ,
@@ -360,11 +429,28 @@ mod tests {
360429 r#"'Escaped \' quotes'"# ,
361430 "Escaped ' quotes" . to_string ( ) . into ( ) ,
362431 ) ,
432+ ( r#" "text" "# , "text" . to_string ( ) . into ( ) ) ,
363433 ( "property" , Expr :: Get ( "property" . to_string ( ) ) ) ,
364434 ( "nullish" , Expr :: Get ( "nullish" . to_string ( ) ) ) ,
365435 ( "trueman" , Expr :: Get ( "trueman" . to_string ( ) ) ) ,
436+ ( " property " , Expr :: Get ( "property" . to_string ( ) ) ) ,
366437 ( "zoom()" , Expr :: Zoom ) ,
438+ ( " zoom() " , Expr :: Zoom ) ,
367439 ( "get('property')" , Expr :: Get ( "property" . to_string ( ) ) ) ,
440+ (
441+ "any([false, bool_prop])" ,
442+ Expr :: Any ( vec ! [ false . into( ) , Expr :: Get ( "bool_prop" . to_owned( ) ) ] ) ,
443+ ) ,
444+ (
445+ "all([string_prop == 'hi', bool_prop])" ,
446+ Expr :: All ( vec ! [
447+ Expr :: Eq (
448+ Box :: new( Expr :: Get ( "string_prop" . to_owned( ) ) ) ,
449+ Box :: new( "hi" . to_owned( ) . into( ) ) ,
450+ ) ,
451+ Expr :: Get ( "bool_prop" . to_owned( ) ) ,
452+ ] ) ,
453+ ) ,
368454 ] ;
369455
370456 for ( case, expected) in cases {
@@ -439,7 +525,7 @@ mod tests {
439525
440526 #[ test]
441527 fn parser_error_two_literals ( ) {
442- ass ! ( s( "property 'value'" ) , @r#""found ''\\''' at 9..10 expected ==, or > ""# )
528+ ass ! ( s( "property 'value'" ) , @r#""found ''\\''' at 9..10 expected ==, !=, >, >=, <, <=, or end of input ""# )
443529 }
444530
445531 #[ test]
@@ -453,7 +539,12 @@ mod tests {
453539 }
454540
455541 #[ test]
456- fn parser_error_invalid_argument_type ( ) {
542+ fn parser_error_invalid_argument_type_string ( ) {
457543 ass ! ( s( "get(42)" ) , @r#""expected `String` argument at position `1` of function `get`, but got `42` at 4..6""# ) ;
458544 }
545+
546+ #[ test]
547+ fn parser_error_invalid_argument_type_array ( ) {
548+ ass ! ( s( "any(true)" ) , @r#""expected `[Array]` argument at position `1` of function `any`, but got `true` at 4..8""# ) ;
549+ }
459550}
0 commit comments