11use nom:: {
2- IResult ,
32 branch:: alt,
43 bytes:: complete:: { tag, take_while} ,
5- character:: complete:: { digit1, multispace0, alpha1, char} ,
6- combinator:: { map_res, recognize, value, map, opt, not, peek, verify} ,
7- sequence:: { pair, delimited, terminated, preceded} ,
8- multi:: { many0, fold_many0, separated_list0}
4+ character:: complete:: { char, digit1, multispace0} ,
5+ combinator:: { map, map_res, opt, value, verify} ,
6+ multi:: { fold_many0, separated_list0} ,
7+ sequence:: { delimited, pair, preceded, tuple} ,
8+ IResult ,
9+ error:: Error ,
910} ;
11+
1012use std:: str:: FromStr ;
1113
14+ use crate :: ir:: ast:: Expression ;
15+ use crate :: parser:: parser_common:: { identifier, keyword, is_string_char} ;
16+
1217use crate :: ir:: ast:: Function ;
1318use crate :: ir:: ast:: Type ;
14- use crate :: ir:: ast:: { Expression , Name , Statement , ValueConstructor } ;
19+ use crate :: ir:: ast:: { Name , Statement , ValueConstructor } ;
1520
1621use crate :: parser:: keywords:: KEYWORDS ;
1722
@@ -39,7 +44,9 @@ fn parse_and(input: &str) -> IResult<&str, Expression> {
3944
4045fn parse_not ( input : & str ) -> IResult < & str , Expression > {
4146 alt ( (
42- map ( preceded ( keyword ( "not" ) , parse_not) , |e| Expression :: Not ( Box :: new ( e) ) ) ,
47+ map ( preceded ( keyword ( "not" ) , parse_not) , |e| {
48+ Expression :: Not ( Box :: new ( e) )
49+ } ) ,
4350 parse_relational,
4451 ) ) ( input)
4552}
@@ -48,7 +55,14 @@ fn parse_relational(input: &str) -> IResult<&str, Expression> {
4855 let ( input, init) = parse_add_sub ( input) ?;
4956 fold_many0 (
5057 pair (
51- alt ( ( operator ( "<=" ) , operator ( "<" ) , operator ( ">=" ) , operator ( ">" ) , operator ( "==" ) , operator ( "!=" ) ) ) ,
58+ alt ( (
59+ operator ( "<=" ) ,
60+ operator ( "<" ) ,
61+ operator ( ">=" ) ,
62+ operator ( ">" ) ,
63+ operator ( "==" ) ,
64+ operator ( "!=" ) ,
65+ ) ) ,
5266 parse_add_sub,
5367 ) ,
5468 move || init. clone ( ) ,
@@ -69,7 +83,7 @@ fn parse_add_sub(input: &str) -> IResult<&str, Expression> {
6983 fold_many0 (
7084 pair (
7185 alt ( ( operator ( "+" ) , operator ( "-" ) ) ) ,
72- parse_term,
86+ parse_term
7387 ) ,
7488 move || init. clone ( ) ,
7589 |acc, ( op, val) | match op {
@@ -85,7 +99,7 @@ fn parse_term(input: &str) -> IResult<&str, Expression> {
8599 fold_many0 (
86100 pair (
87101 alt ( ( operator ( "*" ) , operator ( "/" ) ) ) ,
88- parse_factor,
102+ parse_factor
89103 ) ,
90104 move || init. clone ( ) ,
91105 |acc, ( op, val) | match op {
@@ -100,27 +114,53 @@ fn parse_factor(input: &str) -> IResult<&str, Expression> {
100114 alt ( (
101115 parse_bool,
102116 parse_number,
103- parse_string,
104- parse_var ,
105- parse_function_call ,
106- delimited ( tag ( "(" ) , parse_expression, tag ( ")" ) ) ,
117+ parse_string,
118+ parse_function_call ,
119+ parse_var ,
120+ delimited ( char :: < & str , Error < & str>> ( '(' ) , parse_expression, char :: < & str , Error < & str>> ( ')' ) ) ,
107121 ) ) ( input)
108122}
109123
110124fn parse_bool ( input : & str ) -> IResult < & str , Expression > {
111- alt ( ( value ( Expression :: CTrue , keyword ( "True" ) ) , value ( Expression :: CFalse , keyword ( "False" ) ) ) ) ( input)
125+ alt ( (
126+ value ( Expression :: CTrue , keyword ( "True" ) ) ,
127+ value ( Expression :: CFalse , keyword ( "False" ) ) ,
128+ ) ) ( input)
112129}
113-
130+
114131fn parse_number ( input : & str ) -> IResult < & str , Expression > {
115132 let float_parser = map_res (
116- recognize ( pair (
117- digit1,
118- opt ( pair ( tag ( "." ) , digit1) )
119- ) ) ,
120- |s : & str | f64:: from_str ( s)
133+ verify (
134+ tuple ( (
135+ opt ( char:: <& str, Error <& str>>( '-' ) ) ,
136+ digit1,
137+ char:: <& str, Error <& str>>( '.' ) ,
138+ digit1
139+ ) ) ,
140+ |( _, _, _, _) | true ,
141+ ) ,
142+ |( sign, d1, _, d2) | {
143+ let s = match sign {
144+ Some ( _) => format ! ( "-{}.{}" , d1, d2) ,
145+ None => format ! ( "{}.{}" , d1, d2) ,
146+ } ;
147+ f64:: from_str ( & s)
148+ } ,
121149 ) ;
122150
123- let int_parser = map_res ( digit1, |s : & str | i32:: from_str ( s) ) ;
151+ let int_parser = map_res (
152+ tuple ( (
153+ opt ( char:: <& str, Error <& str>>( '-' ) ) ,
154+ digit1
155+ ) ) ,
156+ |( sign, digits) | {
157+ let s = match sign {
158+ Some ( _) => format ! ( "-{}" , digits) ,
159+ None => digits. to_string ( ) ,
160+ } ;
161+ i32:: from_str ( & s)
162+ }
163+ ) ;
124164
125165 alt ( (
126166 map ( float_parser, Expression :: CReal ) ,
@@ -129,91 +169,51 @@ fn parse_number(input: &str) -> IResult<&str, Expression> {
129169}
130170
131171fn parse_string ( input : & str ) -> IResult < & str , Expression > {
132- map ( delimited (
133- multispace0,
172+ map (
134173 delimited (
135- tag ( "\" " ) ,
136- map ( take_while ( is_string_char) , |s : & str | s. to_string ( ) ) ,
137- tag ( "\" " ) ,
174+ multispace0,
175+ delimited (
176+ char:: <& str, Error <& str>>( '"' ) ,
177+ map ( take_while ( is_string_char) , |s : & str | s. to_string ( ) ) ,
178+ char:: <& str, Error <& str>>( '"' ) ,
179+ ) ,
180+ multispace0,
138181 ) ,
139- multispace0 ,
140- ) , |s| Expression :: CString ( s ) ) ( input)
182+ |s| Expression :: CString ( s ) ,
183+ ) ( input)
141184}
142185
143186fn parse_var ( input : & str ) -> IResult < & str , Expression > {
144- map ( parse_identifier , |v| Expression :: Var ( v. into ( ) ) ) ( input)
187+ map ( identifier , |v| Expression :: Var ( v. into ( ) ) ) ( input)
145188}
146- fn parse_function_call ( input : & str ) -> IResult < & str , Expression > {
147- let ( input, name) = parse_identifier ( input) ?;
148- let ( input, _) = multispace0 ( input) ?;
149- let ( input, _) = char ( '(' ) ( input) ?;
150- let ( input, args) = separated_list0 ( separator ( "," ) , parse_expression) ( input) ?;
151- let ( input, _) = multispace0 ( input) ?;
152- let ( input, _) = char ( '(' ) ( input) ?;
153189
190+ fn parse_function_call ( input : & str ) -> IResult < & str , Expression > {
191+ let ( input, name) = identifier ( input) ?;
192+ let ( input, args) = parse_actual_arguments ( input) ?;
154193 Ok ( ( input, Expression :: FuncCall ( name. to_string ( ) , args) ) )
155194}
156195
157-
158- fn separator < ' a > ( sep : & ' static str ) -> impl FnMut ( & ' a str ) -> IResult < & ' a str , & ' a str > {
159- delimited ( multispace0, tag ( sep) , multispace0)
160- }
161-
162-
163-
164- /// Parses a reserved keyword (e.g., "if") surrounded by optional spaces
165- /// Fails if followed by an identifier character
166- fn keyword < ' a > ( kw : & ' static str ) -> impl FnMut ( & ' a str ) -> IResult < & ' a str , & ' a str > {
167- terminated (
168- delimited ( multispace0, tag ( kw) , multispace0) ,
169- not ( peek ( identifier_start_or_continue) ) ,
170- )
171- }
172-
173- /// Parsers for identifiers.
174- fn parse_identifier ( input : & str ) -> IResult < & str , & str > {
175- let ( input, _) = multispace0 ( input) ?;
176-
177- let ( input, first_char) = identifier_start ( input) ?;
178- let ( input, rest) = identifier_continue ( input) ?;
179-
180- let ident = format ! ( "{}{}" , first_char, rest) ;
181-
182- if KEYWORDS . contains ( & ident. as_str ( ) ) {
183- Err ( nom:: Err :: Error ( nom:: error:: Error :: new ( input, nom:: error:: ErrorKind :: Tag ) ) )
184- } else {
185- Ok ( ( input, Box :: leak ( ident. into_boxed_str ( ) ) ) )
186- }
187- }
188-
189- /// First character of an identifier: [a-zA-Z_]
190- fn identifier_start ( input : & str ) -> IResult < & str , & str > {
191- alt ( ( alpha1, tag ( "_" ) ) ) ( input)
192- }
193-
194- /// Remaining characters: [a-zA-Z0-9_]*
195- fn identifier_continue ( input : & str ) -> IResult < & str , & str > {
196- recognize ( many0 ( identifier_start_or_continue) ) ( input)
197- }
198-
199- /// A single identifier character: alphanumeric or underscore
200- fn identifier_start_or_continue ( input : & str ) -> IResult < & str , & str > {
201- recognize ( alt ( ( alpha1, tag ( "_" ) , nom:: character:: complete:: digit1) ) ) ( input)
196+ pub fn parse_actual_arguments ( input : & str ) -> IResult < & str , Vec < Expression > > {
197+ map (
198+ tuple ( (
199+ multispace0,
200+ char:: <& str, Error <& str>>( '(' ) ,
201+ separated_list0 (
202+ tuple ( ( multispace0, char:: <& str, Error <& str>>( ',' ) , multispace0) ) ,
203+ parse_expression
204+ ) ,
205+ multispace0,
206+ char:: <& str, Error <& str>>( ')' )
207+ ) ) ,
208+ |( _, _, args, _, _) | args
209+ ) ( input)
202210}
203211
204-
205212/// Parses an operator.
206213fn operator < ' a > ( op : & ' static str ) -> impl FnMut ( & ' a str ) -> IResult < & ' a str , & ' a str > {
207214 delimited ( multispace0, tag ( op) , multispace0)
208215}
209216
210-
211- /// Accepts any character except '"' and control characters (like \n, \t)
212- fn is_string_char ( c : char ) -> bool {
213- c != '"' && !c. is_control ( )
214- }
215-
216-
217217#[ cfg( test) ]
218218mod tests {
219219 use super :: * ;
@@ -243,11 +243,6 @@ mod tests {
243243 parse_expression( "-0.001rest" ) ,
244244 Ok ( ( "rest" , Expression :: CReal ( -0.001 ) ) )
245245 ) ;
246-
247- assert_eq ! (
248- parse_expression( "2e3more" ) ,
249- Ok ( ( "more" , Expression :: CReal ( 2000.0 ) ) )
250- ) ;
251246 }
252247
253248 #[ test]
@@ -264,23 +259,21 @@ mod tests {
264259 fn test_keywords ( ) {
265260 let cases = [
266261 ( "if" , "if" ) ,
267- ( " else " , "else" ) ,
268- ( "while rest " , "while" ) ,
269- ( " and " , "and" ) ,
270- ( "or) " , "or" ) ,
271- ( "not x " , "not" ) ,
272- ( " for ( " , "for" ) ,
273- ( "def " , "def" ) ,
262+ ( "else" , "else" ) ,
263+ ( "while" , "while" ) ,
264+ ( "and" , "and" ) ,
265+ ( "or" , "or" ) ,
266+ ( "not" , "not" ) ,
267+ ( "for" , "for" ) ,
268+ ( "def" , "def" ) ,
274269 ] ;
275270
276271 for ( input, expected) in cases {
277- let mut parser = keyword ( expected) ;
278- let result = parser ( input) ;
279- assert_eq ! (
280- result,
281- Ok ( ( input[ expected. len( ) ..] . trim_start( ) , expected) ) ,
282- "Failed to parse keyword '{}'" , expected
283- ) ;
272+ let result = keyword ( expected) ( input) ;
273+ assert ! ( result. is_ok( ) , "Failed to parse keyword '{}'" , expected) ;
274+ let ( rest, parsed) = result. unwrap ( ) ;
275+ assert_eq ! ( parsed, expected) ;
276+ assert ! ( rest. is_empty( ) || rest. starts_with( ' ' ) ) ;
284277 }
285278 }
286279
@@ -296,4 +289,3 @@ mod tests {
296289 assert ! ( parser( "origin" ) . is_err( ) ) ;
297290 }
298291}
299-
0 commit comments