Merge pull request #329 from karroffel/master

added documentation for pattern matching
This commit is contained in:
Rémi Verschelde 2017-01-16 19:24:21 +01:00 committed by GitHub
commit 4ec17c5f3e
2 changed files with 130 additions and 1 deletions

View File

@ -90,7 +90,7 @@ class GDScriptLexer(RegexLexer):
'do', 'var', 'const', 'extends', 'export', 'onready', 'tool',
'static', 'setget', 'signal', 'breakpoint', 'switch', 'case',
'assert', 'break', 'continue', 'elif', 'else', 'for', 'if',
'pass', 'return', 'while'), suffix=r'\b'),
'pass', 'return', 'while', 'match'), suffix=r'\b'),
Keyword),
],
'builtins': [

View File

@ -159,6 +159,8 @@ keywords are reserved words (tokens), they can't be used as identifiers.
+------------+---------------------------------------------------------------------------------------------------------------+
| while | See while_. |
+------------+---------------------------------------------------------------------------------------------------------------+
| match | See match_. |
+------------+---------------------------------------------------------------------------------------------------------------+
| switch | Reserved for future implementation. |
+------------+---------------------------------------------------------------------------------------------------------------+
| case | Reserved for future implementation. |
@ -694,6 +696,133 @@ in the loop variable.
for i in range(2,8,2):
statement # similar to [2, 4, 6] but does not allocate an array
match
^^^^^
A ``match`` statement is used to branch execution of a program.
It's the equivalent of the ``switch`` statement found in many other languages but offers some additional features.
Basic syntax:
::
match [expression]:
[pattern](s): [block]
[pattern](s): [block]
[pattern](s): [block]
**Crash-course for people who are familiar to switch statements**:
1) replace ``switch`` by ``match``
2) remove ``case``
3) remove any ``break`` s. If you don't want to ``break`` by default you can use ``continue`` to get a fallthrough.
4) change ``default`` to a single underscore.
**Control flow**:
The patterns get matched from top to bottom.
If a pattern matches the corresponding block gets executed. After that the execution will continue after the ``match`` statement.
If you want to have a fallthrough you can use ``continue`` to stop execution in the current block and check the next one.
There are 6 pattern types:
- constant pattern
constant primitives like numbers and strings ::
match x:
1: print("I'm number one!")
2: print("Two are better than one!")
"test": print("Oh snap! It's a string!")
- variable pattern
matching on the contents of a variable/enum ::
match typeof(x):
TYPE_FLOAT: print("float")
TYPE_STRING: print("text")
TYPE_ARRAY: print("array")
- wilcard pattern
This pattern matches everything. It's written as a single underscore.
It can be used as the equivalent of the ``default`` in a ``switch`` statement in other languages. ::
match x:
1: print("it's one!")
2: print("it's one times two!")
_: print("it's not 1 or 2. I don't care tbh")
- binding pattern
A binding pattern introduces a new variable. It's like the wildcard pattern: it matches everything - but it also gives that value a name.
Especially useful in array and dictionary patterns. ::
match x:
1: print("it's one!")
2: print("it's one times two!")
var new_var: print("it's not 1 or 2, it's ", new_var)
- array pattern
matches an array. Every single element of the array pattern is a pattern itself so you can nest them.
First the length of the array is tested. It has to be the same like the pattern, otherwise the pattern doesn't match.
**Open-ended array**: An array can be bigger than the pattern by making the last subpattern ``..``
Every subpattern has to be comma seperated. ::
match x:
[]:
print("emtpy array")
[1, 3, "test", null]:
print("very specific array")
[var start, _, "test"]:
print("first element is ", start, " ande the last is \"test\"")
[42, ..]:
print("open ended array")
- dictionary pattern
works similar to the array pattern. Every key has to be a constant pattern.
First the size of the dictionary is tested. It has to be the same like the pattern, otherwise the pattern doesn't match.
**Open-ended dictionary**: A dictionary can be bigger than the pattern by making the last subpattern ``..``
Every subpattern has to be comma seperated.
If you don't specify a value then only the existance of the key is checked (treating the dictionary like a set).
A value pattern is seperated from the key pattern with a ``:`` ::
match x:
{}:
print("empty dict")
{"name": "dennis"}:
print("the name is dennis")
{"name": "dennis", "age": var age}:
print("dennis is ", age, " years old.")
{"name", "age"}:
print("has a name and an age, but it's not dennis :(")
{"key": "godotisawesome", ..}:
print("I only checked for one entry and ignored the rest")
Multipatterns:
You can also specify multiple patterns which are seperated by a comma. Those patterns aren't allowed to have any bindings in them. ::
match x:
1, 2, 3:
print("it's 1 - 3")
"sword", "splashpotion", "fist":
print("yep, you've taken damage")
Classes
~~~~~~~