1
1
use nom:: {
2
- IResult ,
3
2
branch:: alt,
4
3
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 ,
9
10
} ;
11
+
10
12
use std:: str:: FromStr ;
11
13
14
+ use crate :: ir:: ast:: Expression ;
15
+ use crate :: parser:: parser_common:: { identifier, keyword, is_string_char} ;
16
+
12
17
use crate :: ir:: ast:: Function ;
13
18
use crate :: ir:: ast:: Type ;
14
- use crate :: ir:: ast:: { Expression , Name , Statement , ValueConstructor } ;
19
+ use crate :: ir:: ast:: { Name , Statement , ValueConstructor } ;
15
20
16
21
use crate :: parser:: keywords:: KEYWORDS ;
17
22
@@ -39,7 +44,9 @@ fn parse_and(input: &str) -> IResult<&str, Expression> {
39
44
40
45
fn parse_not ( input : & str ) -> IResult < & str , Expression > {
41
46
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
+ } ) ,
43
50
parse_relational,
44
51
) ) ( input)
45
52
}
@@ -48,7 +55,14 @@ fn parse_relational(input: &str) -> IResult<&str, Expression> {
48
55
let ( input, init) = parse_add_sub ( input) ?;
49
56
fold_many0 (
50
57
pair (
51
- alt ( ( operator ( "<=" ) , operator ( "<" ) , operator ( ">=" ) , operator ( ">" ) , operator ( "==" ) , operator ( "!=" ) ) ) ,
58
+ alt ( (
59
+ operator ( "<=" ) ,
60
+ operator ( "<" ) ,
61
+ operator ( ">=" ) ,
62
+ operator ( ">" ) ,
63
+ operator ( "==" ) ,
64
+ operator ( "!=" ) ,
65
+ ) ) ,
52
66
parse_add_sub,
53
67
) ,
54
68
move || init. clone ( ) ,<
A3E2
/span>
@@ -69,7 +83,7 @@ fn parse_add_sub(input: &str) -> IResult<&str, Expression> {
69
83
fold_many0 (
70
84
pair (
71
85
alt ( ( operator ( "+" ) , operator ( "-" ) ) ) ,
72
- parse_term,
86
+ parse_term
73
87
) ,
74
88
move || init. clone ( ) ,
75
89
|acc, ( op, val) | match op {
@@ -85,7 +99,7 @@ fn parse_term(input: &str) -> IResult<&str, Expression> {
85
99
fold_many0 (
86
100
pair (
87
101
alt ( ( operator ( "*" ) , operator ( "/" ) ) ) ,
88
- parse_factor,
102
+ parse_factor
89
103
) ,
90
104
move || init. clone ( ) ,
91
105
|acc, ( op, val) | match op {
@@ -100,27 +114,53 @@ fn parse_factor(input: &str) -> IResult<&str, Expression> {
100
114
alt ( (
101
115
parse_bool,
102
116
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>> ( ')' ) ) ,
107
121
) ) ( input)
108
122
}
109
123
110
124
fn 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)
112
129
}
113
-
130
+
114
131
fn parse_number ( input : & str ) -> IResult < & str , Expression > {
115
132
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
+ } ,
121
149
) ;
122
150
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
+ ) ;
124
164
125
165
alt ( (
126
166
map ( float_parser, Expression :: CReal ) ,
@@ -129,91 +169,51 @@ fn parse_number(input: &str) -> IResult<&str, Expression> {
129
169
}
130
170
131
171
fn parse_string ( input : & str ) -> IResult < & str , Expression > {
132
- map ( delimited (
133
- multispace0,
172
+ map (
134
173
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,
138
181
) ,
139
- multispace0 ,
140
- ) , |s| Expression :: CString ( s ) ) ( input)
182
+ |s| Expression :: CString ( s ) ,
183
+ ) ( input)
141
184
}
142
185
143
186
fn 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)
145
188
}
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) ?;
153
189
190
+ fn parse_function_call ( input : & str ) -> IResult < & str , Expression > {
191
+ let ( input, name) = identifier ( input) ?;
192
+ let ( input, args) = parse_actual_arguments ( input) ?;
154
193
Ok ( ( input, Expression :: FuncCall ( name. to_string ( ) , args) ) )
155
194
}
156
195
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)
202
210
}
203
211
204
-
205
212
/// Parses an operator.
206
213
fn operator < ' a > ( op : & ' static str ) -> impl FnMut ( & ' a str ) -> IResult < & ' a str , & ' a str > {
207
214
delimited ( multispace0, tag ( op) , multispace0)
208
215
}
209
216
210
<
10000
td data-grid-cell-id="diff-975b3fbdc29dba034845cfe0ac50c8aff6e3238015a5faab6d347ac0e3c687dd-210-216-1" data-selected="false" role="gridcell" style="background-color:var(--diffBlob-deletionNum-bgColor, var(--diffBlob-deletion-bgColor-num));text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative left-side">
-
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
-
217
217
#[ cfg( test) ]
218
218
mod tests {
219
219
use super :: * ;
@@ -243,11 +243,6 @@ mod tests {
243
243
parse_expression( "-0.001rest" ) ,
244
244
Ok ( ( "rest" , Expression :: CReal ( -0.001 ) ) )
245
245
) ;
246
-
247
- assert_eq ! (
248
- parse_expression( "2e3more" ) ,
249
- Ok ( ( "more" , Expression :: CReal ( 2000.0 ) ) )
250
- ) ;
251
246
}
252
247
253
248
#[ test]
@@ -264,23 +259,21 @@ mod tests {
264
259
fn test_keywords ( ) {
265
260
let cases = [
266
261
( "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" ) ,
274
269
] ;
275
270
276
271
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( ' ' ) ) ;
284
277
}
285
278
}
286
279
@@ -296,4 +289,3 @@ mod tests {
296
289
assert ! ( parser( "origin" ) . is_err( ) ) ;
297
290
}
298
291
}
299
-
0 commit comments