10000 Add support for PEP 634 match statements · geddski/python@d370cbb · GitHub
[go: up one dir, main page]

Skip to content

Commit d370cbb

Browse files
committed
Add support for PEP 634 match statements
See https://peps.python.org/pep-0634/ FEATURE: Parse Python 3.10 match statements (PEP 634). Closes lezer-parser#10
1 parent 74c6b6d commit d370cbb

File tree

3 files changed

+81
-5
lines changed

3 files changed

+81
-5
lines changed

src/python.grammar

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
xor @left,
1111
bitor @left,
1212
compare @left,
13+
as @left,
1314
and @left,
1415
or @left
1516
}
@@ -29,6 +30,41 @@ FunctionDefinition {
2930

3031
ParamList { "(" commaSep<param>? ")" }
3132

33+
MatchStatement {
34+
skw<"match"> "*"? expression MatchBody { ":" newline indent MatchClause+ (dedent | eof) }
35+
}
36+
37+
MatchClause {
38+
skw<"case"> commaSep<pattern> Guard { kw<"if"> expression }? Body
39+
}
40+
41+
pattern[@isGroup=Pattern] {
42+
CapturePattern { VariableName } |
43+
LiteralPattern |
44+
AsPattern { pattern !as kw<"as"> VariableName } |
45+
OrPattern { pattern (!or LogicOp{"|"} pattern)+ } |
46+
AttributePattern |
47+
SequencePattern |
48+
MappingPattern |
49+
StarPattern { "*" !prefix pattern } |
50+
ClassPattern { (VariableName | AttributePattern) PatternArgList }
51+
}
52+
53+
AttributePattern { VariableName ("." PropertyName)+ }
54+
55+
LiteralPattern {
56+
ArithOp{"-"}? Number (ArithOp{"+"|"-"} Number)? |
57+
String |
58+
kw<"None"> |
59+
@specialize[@name=Boolean]<identifier, "True" | "False">
60+
}
61+
62+
PatternArgList { "(" commaSep<pattern | KeywordPattern { VariableName "=" pattern }> ")" }
63+
64+
SequencePattern { "[" commaSep<pattern> "]" | "(" commaSep<pattern> ")" }
65+
66+
MappingPattern { "{" commaSep<"**" pattern | (VariableName | LiteralPattern) ":" pattern> "}" }
67+
3268
ClassDefinition { kw<"class"> VariableName ArgList? Body }
3369

3470
param { VariableName TypeDef? (AssignOp{"="} test)? | "*" VariableName? | "**" VariableName | "/" }
@@ -78,7 +114,8 @@ compoundStatement {
78114
WithStatement { kw<"async">? kw<"with"> commaSep<test (kw<"as"> VariableName)?> Body } |
79115
FunctionDefinition |
80116
ClassDefinition |
81-
DecoratedStatement { Decorator+ (ClassDefinition | FunctionDefinition) }
117+
DecoratedStatement { Decorator+ (ClassDefinition | FunctionDefinition) } |
118+
MatchStatement
82119
}
83120

84121
elseClause { kw<"else"> Body }
@@ -205,6 +242,8 @@ dottedName { VariableName ("." VariableName)* }
205242

206243
kw<term> { @specialize[@name={term}]<identifier, term> }
207244

245+
skw<term> { @extend[@name={term}]<identifier, term> }
246+
208247
@skip {} {
209248
String {
210249
shortString |

src/tokens.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,21 @@ import {ExternalTokenizer, ContextTracker} from "@lezer/lr"
22
import {
33
newline as newlineToken, eof, newlineEmpty, newlineBracketed, indent, dedent, printKeyword,
44
ParenthesizedExpression, TupleExpression, ComprehensionExpression,
5+
PatternArgList, SequencePattern, MappingPattern,
56
ArrayExpression, ArrayComprehensionExpression, ArgList, ParamList, importList, subscript,
67
DictionaryExpression, DictionaryComprehensionExpression, SetExpression, SetComprehensionExpression, FormatReplacement,
78
ParenL, BraceL, BracketL
89
} from "./parser.terms.js"
910

1011
const newline = 10, carriageReturn = 13, space = 32, tab = 9, hash = 35, parenOpen = 40, dot = 46
1112

12-
const bracketed = [
13+
const bracketed = new Set([
1314
ParenthesizedExpression, TupleExpression, ComprehensionExpression, importList, ArgList, ParamList,
1415
ArrayExpression, ArrayComprehensionExpression, subscript,
1516
SetExpression, SetComprehensionExpression,
16-
DictionaryExpression, DictionaryComprehensionExpression, FormatReplacement
17-
]
17+
DictionaryExpression, DictionaryComprehensionExpression, FormatReplacement,
18+
SequencePattern, MappingPattern, PatternArgList
19+
])
1820

1921
export const newlines = new ExternalTokenizer((input, stack) => {
2022
if (input.next < 0) {
@@ -71,7 +73,7 @@ function countIndent(space) {
7173
export const trackIndent = new ContextTracker({
7274
start: topIndent,
7375
reduce(context, term) {
74-
return context.depth < 0 && bracketed.indexOf(term) > -1 ? context.parent : context
76+
return context.depth < 0 && bracketed.has(term) ? context.parent : context
7577
},
7678
shift(context, term, stack, input) {
7779
if (term == indent) return new IndentLevel(context, countIndent(input.read(input.pos, stack.pos)))

test/statement.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,38 @@ Script(ClassDefinition(class,VariableName,Body(
348348
FunctionDefinition(def,VariableName,ParamList(VariableName,VariableName),Body(
349349
AssignStatement(MemberExpression(VariableName,PropertyName),AssignOp,VariableName),
350350
AssignStatement(MemberExpression(VariableName,PropertyName),AssignOp,VariableName))))))
351+
352+
# Parses match statements
353+
354+
match foo:
355+
case 1:
356+
pass
357+
case Point("a", True) as z | a.b | {x: None, **y}:
358+
pass
359+
case [a, b, *rest] | (p, q):
360+
pass
361+
362+
==>
363+
364+
Script(MatchStatement(match,VariableName,MatchBody(
365+
MatchClause(case,
366+
LiteralPattern(Number),
367+
Body(PassStatement(pass))),
368+
MatchClause(case,
369+
OrPattern(
370+
AsPattern(
371+
ClassPattern(VariableName,PatternArgList(LiteralPattern(String),LiteralPattern(Boolean))),
372+
as,VariableName),
373+
LogicOp,
374+
AttributePattern(VariableName,PropertyName),
375+
LogicOp,
376+
MappingPattern(VariableName,LiteralPattern(None),CapturePattern(VariableName))),
377+
Body(PassStatement(pass))),
378+
MatchClause(case,
379+
OrPattern(SequencePattern(
380+
CapturePattern(VariableName),
381+
CapturePattern(VariableName),
382+
StarPattern(CapturePattern(VariableName))),
383+
LogicOp,
384+
SequencePattern(CapturePattern(VariableName),CapturePattern(VariableName))),
385+
Body(PassStatement(pass))))))

0 commit comments

Comments
 (0)
0