Skip to content

Commit dd4cc25

Browse files
authored
Reduce copying elements when parsing (#35)
1 parent b78001c commit dd4cc25

File tree

2 files changed

+31166
-45387
lines changed

2 files changed

+31166
-45387
lines changed

parser/src/python.lalrpop

Lines changed: 70 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ Statement: ast::Suite = {
4848
};
4949

5050
SimpleStatement: ast::Suite = {
51-
<s1:SmallStatement> <s2:(";" SmallStatement)*> ";"? "\n" => {
52-
let mut statements = vec![s1];
53-
statements.extend(s2.into_iter().map(|e| e.1));
51+
<mut statements:(<SmallStatement> ";")*> <last:SmallStatement> ";"? "\n" => {
52+
statements.push(last);
5453
statements
5554
}
5655
};
@@ -199,9 +198,9 @@ RaiseStatement: ast::Stmt = {
199198
ast::StmtRaise { exc: None, cause: None, range: (location..end_location).into() }
200199
)
201200
},
202-
<location:@L> "raise" <t:Test<"all">> <c:("from" Test<"all">)?> <end_location:@R> => {
201+
<location:@L> "raise" <t:Test<"all">> <c:("from" <Test<"all">>)?> <end_location:@R> => {
203202
ast::Stmt::Raise(
204-
ast::StmtRaise { exc: Some(Box::new(t)), cause: c.map(|x| Box::new(x.1)), range: (location..end_location).into() }
203+
ast::StmtRaise { exc: Some(Box::new(t)), cause: c.map(|x| Box::new(x)), range: (location..end_location).into() }
205204
)
206205
},
207206
};
@@ -251,7 +250,7 @@ ImportAsNames: Vec<ast::Alias> = {
251250

252251
#[inline]
253252
ImportAsAlias<I>: ast::Alias = {
254-
<location:@L> <name:I> <a: ("as" Identifier)?> <end_location:@R> => ast::Alias { name, asname: a.map(|a| a.1), range: (location..end_location).into() },
253+
<location:@L> <name:I> <a: ("as" <Identifier>)?> <end_location:@R> => ast::Alias { name, asname: a, range: (location..end_location).into() },
255254
}
256255

257256
// A name like abc or abc.def.ghi
@@ -284,11 +283,11 @@ NonlocalStatement: ast::Stmt = {
284283
};
285284

286285
AssertStatement: ast::Stmt = {
287-
<location:@L> "assert" <test:Test<"all">> <msg: ("," Test<"all">)?> <end_location:@R> => {
286+
<location:@L> "assert" <test:Test<"all">> <msg: ("," <Test<"all">>)?> <end_location:@R> => {
288287
ast::Stmt::Assert(
289288
ast::StmtAssert {
290289
test: Box::new(test),
291-
msg: msg.map(|e| Box::new(e.1)),
290+
msg: msg.map(|e| Box::new(e)),
292291
range: (location..end_location).into()
293292
}
294293
)
@@ -339,16 +338,14 @@ MatchStatement: ast::Stmt = {
339338
}
340339
)
341340
},
342-
<location:@L> "match" <subject:TestOrStarNamedExpr> "," <subjects:OneOrMore<TestOrStarNamedExpr>> ","? ":" "\n" Indent <cases:MatchCase+> Dedent => {
341+
<location:@L> "match" <subjects:TwoOrMore<TestOrStarNamedExpr, ",">> ","? ":" "\n" Indent <cases:MatchCase+> Dedent => {
343342
let end_location = cases
344343
.last()
345344
.unwrap()
346345
.body
347346
.last()
348347
.unwrap()
349348
.end();
350-
let mut subjects = subjects;
351-
subjects.insert(0, subject);
352349
ast::Stmt::Match(
353350
ast::StmtMatch {
354351
subject: Box::new(ast::Expr::Tuple(
@@ -389,9 +386,7 @@ Patterns: ast::Pattern = {
389386
range: (location..end_location).into()
390387
},
391388
),
392-
<location:@L> <pattern:Pattern> "," <patterns:OneOrMore<Pattern>> ","? <end_location:@R> => {
393-
let mut patterns = patterns;
394-
patterns.insert(0, pattern);
389+
<location:@L> <patterns:TwoOrMore<Pattern, ",">> ","? <end_location:@R> => {
395390
ast::Pattern::MatchSequence(
396391
ast::PatternMatchSequence {
397392
patterns,
@@ -428,9 +423,7 @@ AsPattern: ast::Pattern = {
428423

429424
OrPattern: ast::Pattern = {
430425
<pattern:ClosedPattern> => pattern,
431-
<location:@L> <pattern:ClosedPattern> <patterns:("|" <ClosedPattern>)+> <end_location:@R> => {
432-
let mut patterns = patterns;
433-
patterns.insert(0, pattern);
426+
<location:@L> <patterns:TwoOrMore<ClosedPattern, "|">> <end_location:@R> => {
434427
ast::Pattern::MatchOr(
435428
ast::PatternMatchOr { patterns, range: (location..end_location).into() }
436429
)
@@ -454,9 +447,15 @@ SequencePattern: ast::Pattern = {
454447
patterns: vec![],
455448
range: (location..end_location).into()
456449
}.into(),
457-
<location:@L> "(" <pattern:Pattern> "," <patterns:Comma<Pattern>> ")" <end_location:@R> => {
450+
<location:@L> "(" <pattern:Pattern> "," ")" <end_location:@R> => {
451+
ast::PatternMatchSequence {
452+
patterns: vec![pattern],
453+
range: (location..end_location).into()
454+
}.into()
455+
},
456+
<location:@L> "(" <patterns:(<Pattern> ",")+> <last:Pattern> ","? ")" <end_location:@R> => {
458457
let mut patterns = patterns;
459-
patterns.insert(0, pattern);
458+
patterns.push(last);
460459
ast::PatternMatchSequence {
461460
patterns,
462461
range: (location..end_location).into()
@@ -942,9 +941,9 @@ WithItem<Goal>: ast::Withitem = {
942941
};
943942

944943
FuncDef: ast::Stmt = {
945-
<decorator_list:Decorator*> <location:@L> <is_async:"async"?> "def" <name:Identifier> <args:Parameters> <r:("->" Test<"all">)?> ":" <body:Suite> => {
944+
<decorator_list:Decorator*> <location:@L> <is_async:"async"?> "def" <name:Identifier> <args:Parameters> <r:("->" <Test<"all">>)?> ":" <body:Suite> => {
946945
let args = Box::new(args);
947-
let returns = r.map(|x| Box::new(x.1));
946+
let returns = r.map(|x| Box::new(x));
948947
let end_location = body.last().unwrap().end();
949948
let type_comment = None;
950949
if is_async.is_some() {
@@ -977,11 +976,11 @@ Parameters: ast::Arguments = {
977976
// Note that this is a macro which is used once for function defs, and
978977
// once for lambda defs.
979978
ParameterList<ArgType, StarArgType>: ast::Arguments = {
980-
<location:@L> <param1:ParameterDefs<ArgType>> <args2:("," ParameterListStarArgs<ArgType, StarArgType>)?> ","? <end_location:@R> =>? {
979+
<location:@L> <param1:ParameterDefs<ArgType>> <args2:("," <ParameterListStarArgs<ArgType, StarArgType>>)?> ","? <end_location:@R> =>? {
981980
let (posonlyargs, args, defaults) = parse_params(param1)?;
982981

983982
// Now gather rest of parameters:
984-
let (vararg, kwonlyargs, kw_defaults, kwarg) = args2.map_or((None, vec![], vec![], None), |x| x.1);
983+
let (vararg, kwonlyargs, kw_defaults, kwarg) = args2.unwrap_or((None, vec![], vec![], None));
985984

986985
Ok(ast::Arguments {
987986
posonlyargs,
@@ -994,14 +993,14 @@ ParameterList<ArgType, StarArgType>: ast::Arguments = {
994993
range: optional_range(location, end_location)
995994
})
996995
},
997-
<location:@L> <param1:ParameterDefs<ArgType>> <kw:("," KwargParameter<ArgType>)> ","? <end_location:@R> =>? {
996+
<location:@L> <param1:ParameterDefs<ArgType>> <kw:("," <KwargParameter<ArgType>>)> ","? <end_location:@R> =>? {
998997
let (posonlyargs, args, defaults) = parse_params(param1)?;
999998

1000999
// Now gather rest of parameters:
10011000
let vararg = None;
10021001
let kwonlyargs = vec![];
10031002
let kw_defaults = vec![];
1004-
let kwarg = kw.1;
1003+
let kwarg = kw;
10051004

10061005
Ok(ast::Arguments {
10071006
posonlyargs,
@@ -1047,8 +1046,8 @@ ParameterDefs<ArgType>: (Vec<(ast::Arg, Option<ast::Expr>)>, Vec<(ast::Arg, Opti
10471046
<args:OneOrMore<ParameterDef<ArgType>>> => {
10481047
(vec![], args)
10491048
},
1050-
<pos_args:OneOrMore<ParameterDef<ArgType>>> "," "/" <args:("," ParameterDef<ArgType>)*> => {
1051-
(pos_args, args.into_iter().map(|e| e.1).collect())
1049+
<pos_args:OneOrMore<ParameterDef<ArgType>>> "," "/" <args:("," <ParameterDef<ArgType>>)*> => {
1050+
(pos_args, args)
10521051
},
10531052
};
10541053

@@ -1062,15 +1061,15 @@ UntypedParameter: ast::Arg = {
10621061
};
10631062

10641063
TypedParameter: ast::Arg = {
1065-
<location:@L> <arg:Identifier> <a:(":" Test<"all">)?> <end_location:@R> => {
1066-
let annotation = a.map(|x| Box::new(x.1));
1064+
<location:@L> <arg:Identifier> <a:(":" <Test<"all">>)?> <end_location:@R> => {
1065+
let annotation = a.map(|x| Box::new(x));
10671066
ast::Arg { arg, annotation, type_comment: None, range: (location..end_location).into() }
10681067
},
10691068
};
10701069

10711070
StarTypedParameter: ast::Arg = {
1072-
<location:@L> <arg:Identifier> <a:(":" TestOrStarExpr)?> <end_location:@R> => {
1073-
let annotation = a.map(|x| Box::new(x.1));
1071+
<location:@L> <arg:Identifier> <a:(":" <TestOrStarExpr>)?> <end_location:@R> => {
1072+
let annotation = a.map(|x| Box::new(x));
10741073
ast::Arg { arg, annotation, type_comment: None, range: (location..end_location).into() }
10751074
},
10761075
};
@@ -1079,12 +1078,12 @@ StarTypedParameter: ast::Arg = {
10791078
// TODO: figure out another grammar that makes this inline no longer required.
10801079
#[inline]
10811080
ParameterListStarArgs<ArgType, StarArgType>: (Option<Box<ast::Arg>>, Vec<ast::Arg>, Vec<ast::Expr>, Option<Box<ast::Arg>>) = {
1082-
<location:@L> "*" <va:StarArgType?> <kw:("," ParameterDef<ArgType>)*> <kwarg:("," KwargParameter<ArgType>)?> =>? {
1081+
<location:@L> "*" <va:StarArgType?> <kw:("," <ParameterDef<ArgType>>)*> <kwarg:("," <KwargParameter<ArgType>>)?> =>? {
10831082
// Extract keyword arguments:
10841083
let mut kwonlyargs = Vec::new();
10851084
let mut kw_defaults = Vec::new();
1086-
let mut kwargs = Vec::new();
1087-
for (name, value) in kw.into_iter().map(|x| x.1) {
1085+
let mut kwargs = Vec::with_capacity(kw.len());
1086+
for (name, value) in kw {
10881087
if let Some(value) = value {
10891088
kwonlyargs.push(name);
10901089
kw_defaults.push(value);
@@ -1101,7 +1100,7 @@ ParameterListStarArgs<ArgType, StarArgType>: (Option<Box<ast::Arg>>, Vec<ast::Ar
11011100
})?
11021101
}
11031102

1104-
let kwarg = kwarg.map(|n| n.1).flatten();
1103+
let kwarg = kwarg.flatten();
11051104
let va = va.map(Box::new);
11061105

11071106
Ok((va, kwargs, kw_defaults, kwarg))
@@ -1210,9 +1209,8 @@ LambdaDef: ast::Expr = {
12101209
}
12111210

12121211
OrTest<Goal>: ast::Expr = {
1213-
<location:@L> <e1:AndTest<"all">> <e2:("or" AndTest<"all">)+> <end_location:@R> => {
1214-
let mut values = vec![e1];
1215-
values.extend(e2.into_iter().map(|e| e.1));
1212+
<location:@L> <mut values:(<AndTest<"all">> "or")+> <last: AndTest<"all">> <end_location:@R> => {
1213+
values.push(last);
12161214
ast::Expr::BoolOp(
12171215
ast::ExprBoolOp { op: ast::Boolop::Or, values, range: (location..end_location).into() }
12181216
)
@@ -1221,9 +1219,8 @@ OrTest<Goal>: ast::Expr = {
12211219
};
12221220

12231221
AndTest<Goal>: ast::Expr = {
1224-
<location:@L> <e1:NotTest<"all">> <e2:("and" NotTest<"all">)+> <end_location:@R> => {
1225-
let mut values = vec![e1];
1226-
values.extend(e2.into_iter().map(|e| e.1));
1222+
<location:@L> <mut values:(<NotTest<"all">> "and")+> <last:NotTest<"all">> <end_location:@R> => {
1223+
values.push(last);
12271224
ast::Expr::BoolOp(
12281225
ast::ExprBoolOp { op: ast::Boolop::And, values, range: (location..end_location).into() }
12291226
)
@@ -1366,19 +1363,18 @@ AtomExpr2<Goal>: ast::Expr = {
13661363
};
13671364

13681365
SubscriptList: ast::Expr = {
1369-
<location:@L> <s1:Subscript> <s2:("," Subscript)*> <trailing_comma:","?> <end_location:@R> => {
1370-
if s2.is_empty() && trailing_comma.is_none() {
1371-
s1
1372-
} else {
1373-
let mut dims = vec![s1];
1374-
for x in s2 {
1375-
dims.push(x.1)
1376-
}
1377-
1378-
ast::Expr::Tuple(
1379-
ast::ExprTuple { elts: dims, ctx: ast::ExprContext::Load, range: (location..end_location).into() },
1380-
)
1381-
}
1366+
<location:@L> <s1:Subscript> <end_location:@R> => {
1367+
s1
1368+
},
1369+
<location:@L> <s1:Subscript> "," <end_location:@R> => {
1370+
ast::Expr::Tuple(
1371+
ast::ExprTuple { elts: vec![s1], ctx: ast::ExprContext::Load, range: (location..end_location).into() },
1372+
)
1373+
},
1374+
<location:@L> <elts:TwoOrMore<Subscript, ",">> ","? <end_location:@R> => {
1375+
ast::Expr::Tuple(
1376+
ast::ExprTuple { elts, ctx: ast::ExprContext::Load, range: (location..end_location).into() },
1377+
)
13821378
}
13831379
};
13841380

@@ -1603,21 +1599,32 @@ FunctionArgument: (Option<(TextSize, TextSize, Option<ast::Identifier>)>, ast::E
16031599
<location:@L> "**" <e:Test<"all">> <end_location:@R> => (Some((location, end_location, None)), e),
16041600
};
16051601

1602+
/// Comma separated sequence that allows an optional trailing comma.
16061603
#[inline]
16071604
Comma<T>: Vec<T> = {
1608-
<items: (<T> ",")*> <last: T?> => {
1609-
let mut items = items;
1610-
items.extend(last);
1611-
items
1605+
<mut v:(<T> ",")*> <last:T?> => {
1606+
if let Some(element) = last {
1607+
v.push(element);
1608+
}
1609+
v
16121610
}
16131611
};
16141612

1615-
#[inline]
1613+
/// One ore more items that are separated by a comma.
16161614
OneOrMore<T>: Vec<T> = {
1617-
<i1: T> <i2:("," T)*> => {
1618-
let mut items = vec![i1];
1619-
items.extend(i2.into_iter().map(|e| e.1));
1620-
items
1615+
<e:T> => vec![e],
1616+
<mut v: OneOrMore<T>> "," <e:T> => {
1617+
v.push(e);
1618+
v
1619+
}
1620+
};
1621+
1622+
/// Two or more items that are separted by `Sep`
1623+
TwoOrMore<T, Sep>: Vec<T> = {
1624+
<e1:T> Sep <e2:T> => vec![e1, e2],
1625+
<mut v: TwoOrMore<T, Sep>> Sep <e:T> => {
1626+
v.push(e);
1627+
v
16211628
}
16221629
};
16231630

0 commit comments

Comments
 (0)