textmate-grammar-python 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (19) hide show
  1. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/PKG-INFO +48 -18
  2. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/README.md +46 -17
  3. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/pyproject.toml +2 -1
  4. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/captures.py +1 -1
  5. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/grammars/matlab/grammar.yaml +31 -30
  6. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/handler.py +7 -6
  7. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/parser.py +26 -14
  8. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/LICENSE +0 -0
  9. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/__init__.py +0 -0
  10. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/elements.py +0 -0
  11. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/exceptions.py +0 -0
  12. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/grammars/__init__.py +0 -0
  13. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/grammars/markdown/LICENSE.txt +0 -0
  14. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/grammars/markdown/__init__.py +0 -0
  15. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/grammars/markdown/grammar.yaml +0 -0
  16. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/grammars/matlab/__init__.py +0 -0
  17. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/grammars/matlab/license.txt +0 -0
  18. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/language.py +0 -0
  19. {textmate_grammar_python-0.1.0 → textmate_grammar_python-0.1.2}/textmate_grammar/logging.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: textmate-grammar-python
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: An interpreter for grammar files as defined by TextMate and used in VSCode, implemented in Python. TextMate grammars use the oniguruma dialect (https://github.com/kkos/oniguruma). Supports loading grammar files from JSON, PLIST, or YAML format.
5
5
  Home-page: https://github.com/watermarkhu/textmate-grammar-python
6
6
  License: MIT
@@ -11,6 +11,7 @@ Requires-Python: >=3.11,<4.0
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
14
15
  Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
15
16
  Requires-Dist: onigurumacffi (>=1.3.0,<2.0.0)
16
17
  Project-URL: Repository, https://github.com/watermarkhu/textmate-grammar-python
@@ -20,14 +21,26 @@ Description-Content-Type: text/markdown
20
21
 
21
22
  An interpreter for grammar files as defined by TextMate and used in VSCode, implemented in Python. TextMate grammars use the oniguruma dialect (https://github.com/kkos/oniguruma). Supports loading grammar files from JSON, PLIST, or YAML format.
22
23
 
24
+
25
+ ## Usage
26
+ Install the module using `pip install textmate-grammar-python`.
27
+
28
+ Before tokenization is possible, a `LanguageParser` needs to be initialized using a loaded grammar.
29
+
23
30
  ```python
24
- >>> from textmate_grammar.language import LanguageParser
25
- >>> from textmate_grammar.grammars import matlab
31
+ from textmate_grammar.language import LanguageParser
32
+ from textmate_grammar.grammars import matlab
33
+ parser = LanguageParser(matlab.GRAMMAR)
34
+ ```
26
35
 
27
- >>> parser = LanguageParser(matlab.GRAMMAR)
28
- >>> element = parser.parse_string("value = num2str(10);")
36
+ After this, one can either choose to call `parser.parsing_string` to parse a input string directly, or call `parser.parse_file` with the path to the appropiate source file as the first argument, such as the the example `example.py`.
37
+
38
+ The parsed `element` object can be displayed directly by calling the `print` method. By default the element is printed as an element tree in a dictionary format.
29
39
 
40
+ ```python
41
+ >>> element = parser.parse_string("value = num2str(10);")
30
42
  >>> element.print()
43
+
31
44
  {'token': 'source.matlab',
32
45
  'children': [{'token': 'meta.assignment.variable.single.matlab',
33
46
  'children': [{'token': 'variable.other.readwrite.matlab', 'content': 'value'}]},
@@ -39,7 +52,12 @@ An interpreter for grammar files as defined by TextMate and used in VSCode, impl
39
52
  'children': [{'token': 'constant.numeric.decimal.matlab', 'content': '10'}]},
40
53
  {'token': 'punctuation.terminator.semicolon.matlab', 'content': ';'}]}
41
54
 
55
+ ```
56
+ Alternatively, with the keyword argument `flatten` the element is displayed as a list per unique token. Here the first item in the list is the starting position (line, column) of the unique tokenized element.
57
+
58
+ ```python
42
59
  >>> element.print(flatten=True)
60
+
43
61
  [[(0, 0), 'value', ['source.matlab', 'meta.assignment.variable.single.matlab', 'variable.other.readwrite.matlab']],
44
62
  [(0, 5), ' ', ['source.matlab']],
45
63
  [(0, 6), '=', ['source.matlab', 'keyword.operator.assignment.matlab']],
@@ -51,25 +69,37 @@ An interpreter for grammar files as defined by TextMate and used in VSCode, impl
51
69
  [(0, 19), ';', ['source.matlab', 'punctuation.terminator.semicolon.matlab']]]
52
70
  ```
53
71
 
72
+ ## Supported Languages
73
+ - [MATLAB](https://github.com/mathworks/MATLAB-Language-grammar)
74
+
75
+ ## TODO
76
+ - Implement Begin/While pattern, required for other grammars.
77
+
54
78
  ## Sources
55
79
  - [Textmate guide](https://www.apeth.com/nonblog/stories/textmatebundle.html)
56
80
  - [VSCode Syntax Highlighting guide](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide)
57
81
  - [vscode-textmate](https://github.com/microsoft/vscode-textmate)
58
82
  - [Macromates texmate](https://macromates.com/textmate/manual/)
59
83
 
60
- ## TODO
61
- - [x] Use yaml in stead of json
62
- - [x] Grammar initialization with *repository* at any level
63
- - [x] Proper line-by-line parsing
64
- - [x] `\G` anchoring
65
- - [x] Option to *disable* a grammar
66
- - [x] Option to *applyEndPatternLast*
67
- - [x] Implement *injections*
68
- - [ ] Implement Begin/While pattern
69
84
 
70
- ## Supported Languages
71
- - [MATLAB](https://github.com/mathworks/MATLAB-Language-grammar)
85
+ ## Development
86
+
87
+ Install the repository after cloning with [poetry](https://python-poetry.org/)
88
+
89
+ ```bash
90
+ > pip install poetry
91
+ > cd textmate-grammar-python
92
+ > poetry install
93
+ ```
94
+
95
+ Run unit tests
96
+ ```bash
97
+ > tox run
98
+ ```
99
+
100
+ Run regression testing against vscode-textmate (will install npm and required packages)
101
+ ```bash
102
+ > tox run -e regression
103
+ ```
72
104
 
73
- ## TextMate 2 features that are not used
74
- - [Format strings](https://macromates.com/blog/2011/format-strings/)
75
105
 
@@ -2,14 +2,26 @@
2
2
 
3
3
  An interpreter for grammar files as defined by TextMate and used in VSCode, implemented in Python. TextMate grammars use the oniguruma dialect (https://github.com/kkos/oniguruma). Supports loading grammar files from JSON, PLIST, or YAML format.
4
4
 
5
+
6
+ ## Usage
7
+ Install the module using `pip install textmate-grammar-python`.
8
+
9
+ Before tokenization is possible, a `LanguageParser` needs to be initialized using a loaded grammar.
10
+
5
11
  ```python
6
- >>> from textmate_grammar.language import LanguageParser
7
- >>> from textmate_grammar.grammars import matlab
12
+ from textmate_grammar.language import LanguageParser
13
+ from textmate_grammar.grammars import matlab
14
+ parser = LanguageParser(matlab.GRAMMAR)
15
+ ```
8
16
 
9
- >>> parser = LanguageParser(matlab.GRAMMAR)
10
- >>> element = parser.parse_string("value = num2str(10);")
17
+ After this, one can either choose to call `parser.parsing_string` to parse a input string directly, or call `parser.parse_file` with the path to the appropiate source file as the first argument, such as the the example `example.py`.
18
+
19
+ The parsed `element` object can be displayed directly by calling the `print` method. By default the element is printed as an element tree in a dictionary format.
11
20
 
21
+ ```python
22
+ >>> element = parser.parse_string("value = num2str(10);")
12
23
  >>> element.print()
24
+
13
25
  {'token': 'source.matlab',
14
26
  'children': [{'token': 'meta.assignment.variable.single.matlab',
15
27
  'children': [{'token': 'variable.other.readwrite.matlab', 'content': 'value'}]},
@@ -21,7 +33,12 @@ An interpreter for grammar files as defined by TextMate and used in VSCode, impl
21
33
  'children': [{'token': 'constant.numeric.decimal.matlab', 'content': '10'}]},
22
34
  {'token': 'punctuation.terminator.semicolon.matlab', 'content': ';'}]}
23
35
 
36
+ ```
37
+ Alternatively, with the keyword argument `flatten` the element is displayed as a list per unique token. Here the first item in the list is the starting position (line, column) of the unique tokenized element.
38
+
39
+ ```python
24
40
  >>> element.print(flatten=True)
41
+
25
42
  [[(0, 0), 'value', ['source.matlab', 'meta.assignment.variable.single.matlab', 'variable.other.readwrite.matlab']],
26
43
  [(0, 5), ' ', ['source.matlab']],
27
44
  [(0, 6), '=', ['source.matlab', 'keyword.operator.assignment.matlab']],
@@ -33,24 +50,36 @@ An interpreter for grammar files as defined by TextMate and used in VSCode, impl
33
50
  [(0, 19), ';', ['source.matlab', 'punctuation.terminator.semicolon.matlab']]]
34
51
  ```
35
52
 
53
+ ## Supported Languages
54
+ - [MATLAB](https://github.com/mathworks/MATLAB-Language-grammar)
55
+
56
+ ## TODO
57
+ - Implement Begin/While pattern, required for other grammars.
58
+
36
59
  ## Sources
37
60
  - [Textmate guide](https://www.apeth.com/nonblog/stories/textmatebundle.html)
38
61
  - [VSCode Syntax Highlighting guide](https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide)
39
62
  - [vscode-textmate](https://github.com/microsoft/vscode-textmate)
40
63
  - [Macromates texmate](https://macromates.com/textmate/manual/)
41
64
 
42
- ## TODO
43
- - [x] Use yaml in stead of json
44
- - [x] Grammar initialization with *repository* at any level
45
- - [x] Proper line-by-line parsing
46
- - [x] `\G` anchoring
47
- - [x] Option to *disable* a grammar
48
- - [x] Option to *applyEndPatternLast*
49
- - [x] Implement *injections*
50
- - [ ] Implement Begin/While pattern
51
65
 
52
- ## Supported Languages
53
- - [MATLAB](https://github.com/mathworks/MATLAB-Language-grammar)
66
+ ## Development
67
+
68
+ Install the repository after cloning with [poetry](https://python-poetry.org/)
69
+
70
+ ```bash
71
+ > pip install poetry
72
+ > cd textmate-grammar-python
73
+ > poetry install
74
+ ```
75
+
76
+ Run unit tests
77
+ ```bash
78
+ > tox run
79
+ ```
80
+
81
+ Run regression testing against vscode-textmate (will install npm and required packages)
82
+ ```bash
83
+ > tox run -e regression
84
+ ```
54
85
 
55
- ## TextMate 2 features that are not used
56
- - [Format strings](https://macromates.com/blog/2011/format-strings/)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "textmate-grammar-python"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "An interpreter for grammar files as defined by TextMate and used in VSCode, implemented in Python. TextMate grammars use the oniguruma dialect (https://github.com/kkos/oniguruma). Supports loading grammar files from JSON, PLIST, or YAML format."
5
5
  authors = ["Mark Shui Hu <watermarkhu@gmail.com>"]
6
6
  license = "MIT"
@@ -17,6 +17,7 @@ PyYAML = "^6.0.1"
17
17
  [tool.poetry.group.test.dependencies]
18
18
  pytest = "^7.3.1"
19
19
  pytest-icdiff = "^0.8"
20
+ tox = "^4.11.4"
20
21
 
21
22
  [build-system]
22
23
  requires = ["poetry-core"]
@@ -104,7 +104,7 @@ class Capture(object):
104
104
  continue
105
105
 
106
106
  # Dispatch the parse
107
- self.kwargs.pop("leading_chars", None)
107
+ self.kwargs.pop("greedy", None)
108
108
  parsed, captured_elements, _ = parser._parse(
109
109
  self.handler,
110
110
  starting=group_starting,
@@ -18,7 +18,7 @@ repository:
18
18
  beginCaptures:
19
19
  '1':
20
20
  name: punctuation.definition.function.anonymous.matlab
21
- end: (?=;|(?<!(?:\.\.\..*))\n|%)
21
+ end: (?=;|(?<!(?:\.{3}.*))\n|%)
22
22
  name: meta.function.anonymous.matlab
23
23
  patterns:
24
24
  - begin: \G(\()
@@ -40,7 +40,7 @@ repository:
40
40
  beginCaptures:
41
41
  '1':
42
42
  name: punctuation.section.group.begin.matlab
43
- end: (\))?[^\S\n]*(?=;|(?<!(?:\.\.\..*))\n|%)
43
+ end: (\))?[^\S\n]*(?=;|(?<!(?:\.{3}.*))\n|%)
44
44
  endCaptures:
45
45
  '1':
46
46
  name: punctuation.section.group.end.matlab
@@ -62,7 +62,7 @@ repository:
62
62
  name: meta.for.matlab
63
63
  patterns:
64
64
  - begin: \G(?!$)
65
- end: (?<!\.\.\.)(?:(?=([,;])(?![^(]*\)))|$)
65
+ end: (?<!\.{3})(?:(?=([,;])(?![^(]*\)))|$)
66
66
  name: meta.for.declaration.matlab
67
67
  patterns:
68
68
  - include: $self
@@ -81,7 +81,7 @@ repository:
81
81
  name: meta.if.matlab
82
82
  patterns:
83
83
  - begin: \G(?!$)
84
- end: (?<!\.\.\.)(?:(?=([,;])(?![^(]*\)))|$)
84
+ end: (?<!\.{3})(?:(?=([,;])(?![^(]*\)))|$)
85
85
  name: meta.if.declaration.matlab
86
86
  patterns:
87
87
  - include: $self
@@ -92,7 +92,7 @@ repository:
92
92
  name: meta.elseif.matlab
93
93
  patterns:
94
94
  - begin: \G(?!$)
95
- end: (?<!\.\.\.)(?:(?=([,;])(?![^(]*\)))|$)
95
+ end: (?<!\.{3})(?:(?=([,;])(?![^(]*\)))|$)
96
96
  name: meta.elseif.declaration.matlab
97
97
  patterns:
98
98
  - include: $self
@@ -114,7 +114,7 @@ repository:
114
114
  name: meta.for.parallel.matlab
115
115
  patterns:
116
116
  - begin: \G(?!$)
117
- end: (?<!\.\.\.)(?:(?=([,;])(?![^(]*\)))|$)
117
+ end: (?<!\.{3})(?:(?=([,;])(?![^(]*\)))|$)
118
118
  name: meta.for.parallel.declaration.matlab
119
119
  patterns:
120
120
  - include: $self
@@ -130,7 +130,7 @@ repository:
130
130
  name: meta.repeat.parallel.matlab
131
131
  patterns:
132
132
  - begin: \G(?!$)
133
- end: (?<!\.\.\.)(?:(?=([,;])(?![^(]*\)))|$)
133
+ end: (?<!\.{3})(?:(?=([,;])(?![^(]*\)))|$)
134
134
  name: meta.repeat.parallel.declaration.matlab
135
135
  patterns:
136
136
  - include: $self
@@ -152,11 +152,11 @@ repository:
152
152
  name: keyword.control.switch.case.matlab
153
153
  '3':
154
154
  begin: \G(?!$)
155
- end: (?<!\.\.\.)(?:(?=([,;])(?![^(]*\)))|$)
155
+ end: (?<!\.{3})(?:(?=([,;])(?![^(]*\)))|$)
156
156
  name: meta.case.declaration.matlab
157
157
  patterns:
158
158
  - include: $self
159
- match: (\s*)(?<=^|[\s,;])(case)\b(.*?)(?<!\.\.\.)(?:(?=([,;])(?![^(]*\)))|$)
159
+ match: (\s*)(?<=^|[\s,;])(case)\b(.*?)(?<!\.{3})(?:(?=([,;])(?![^(]*\)))|$)
160
160
  name: meta.case.matlab
161
161
  - captures:
162
162
  '2':
@@ -196,7 +196,7 @@ repository:
196
196
  name: meta.while.matlab
197
197
  patterns:
198
198
  - begin: \G
199
- end: (?<!\.\.\.)(?:(?=([,;])(?![^(]*\)))|$)
199
+ end: (?<!\.{3})(?:(?=([,;])(?![^(]*\)))|$)
200
200
  endCaptures:
201
201
  '1':
202
202
  include: $self
@@ -235,7 +235,7 @@ repository:
235
235
  name: meta.class.matlab
236
236
  patterns:
237
237
  - begin: \G
238
- end: (?<!\.\.\.)(?=\n)
238
+ end: (?<!\.{3})(?=\n)
239
239
  name: meta.class.declaration.matlab
240
240
  patterns:
241
241
  - begin: \G(\([^)]*\))?\s*
@@ -262,14 +262,14 @@ repository:
262
262
  - include: '#string'
263
263
  - include: '#comments'
264
264
  - include: '#line_continuation'
265
- end: (?<!\.\.\.)(?=\s*%|\n)
265
+ end: (?<!\.{3})(?=\s*%|\n)
266
266
  patterns:
267
267
  - begin: \G\s*([a-zA-Z][a-zA-Z0-9_]*)
268
268
  beginCaptures:
269
269
  '1':
270
270
  comment: Class name
271
271
  name: entity.name.type.class.matlab
272
- end: (?<!\.\.\.)(?=\n)
272
+ end: (?<!\.{3})(?=\n)
273
273
  patterns:
274
274
  - comment: Optional inheritance operator
275
275
  match: <
@@ -414,7 +414,7 @@ repository:
414
414
  - include: '#string_quoted_single'
415
415
  comment: "\t\t\t\t\t 1 \t\t\t\t 2\t\t3 \t\t\t\t 4\t\t\t\t\t\t\t\t\t\t\t\t\
416
416
  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t "
417
- match: (?<=^|[^.]\n|;|,|=)([^\S\n]*)(?# A> )(\b\w+\b)([^\S\n]+)(?# B> )((?!(\+|-|\*|\.\*|\/|\.\/|\\|\.\\|\^|\.\^|==|~=|&|&&|\||\|\||=|:|>|>=|<|<=|\.\.\.)[^\S\n]?)[^\s({=;%][^\n;%]*)
417
+ match: (?<=^|[^.]\n|;|,|=)([^\S\n]*)(?# A> )(\b\w+\b)([^\S\n]+)(?# B> )((?!(\+|-|\*|\.\*|\/|\.\/|\\|\.\\|\^|\.\^|==|~=|&|&&|\||\|\||=|:|>|>=|<|<=|\.{3})[^\S\n]?)[^\s({=;%][^\n;%]*)
418
418
  name: meta.function-call.command.matlab
419
419
  comment_block:
420
420
  begin: (^[\s]*)(%\{)[^\S\n]*+\n
@@ -525,10 +525,10 @@ repository:
525
525
  name: meta.function.matlab
526
526
  patterns:
527
527
  - begin: \G
528
- end: (?<=[\)\n])
528
+ end: (?<=\))|(?>(?<!\.{3}.*)\n)
529
529
  name: meta.function.declaration.matlab
530
530
  patterns:
531
- - begin: \G(?=.*?=)
531
+ - begin: \G(?=[^\(]*?(?:=|\[|\.{3}))
532
532
  comment: Function output
533
533
  contentName: meta.assignment.variable.output.matlab
534
534
  end: \s*(=)\s*
@@ -541,21 +541,21 @@ repository:
541
541
  - captures:
542
542
  '1':
543
543
  name: punctuation.section.assignment.group.end.matlab
544
- match: (\])\s*\z
544
+ match: (\])\s*
545
545
  - match: '[a-zA-Z][a-zA-Z0-9_]*'
546
546
  name: variable.parameter.output.matlab
547
547
  - match: ','
548
548
  name: punctuation.separator.parameter.comma.matlab
549
- - include: '#comments'
550
549
  - include: '#line_continuation'
550
+ - include: '#comments'
551
551
  - comment: Function name
552
- match: '[a-zA-Z][a-zA-Z0-9_.]*(?=[^a-zA-Z0-9_.])'
552
+ match: '[a-zA-Z][a-zA-Z0-9_]*(?>\.[a-zA-Z0-9_]+)*'
553
553
  name: entity.name.function.matlab
554
554
  patterns:
555
555
  - match: \.
556
556
  name: punctuation.accessor.dot.matlab
557
557
  - include: '#line_continuation'
558
- - begin: (?<=[a-zA-Z0-9_])\s*\(
558
+ - begin: \s*\(
559
559
  beginCaptures:
560
560
  '0':
561
561
  name: punctuation.definition.parameters.begin.matlab
@@ -574,6 +574,7 @@ repository:
574
574
  name: punctuation.separator.parameter.comma.matlab
575
575
  - include: '#comments'
576
576
  - include: '#line_continuation'
577
+ - include: '#line_continuation'
577
578
  - include: '#comments'
578
579
  - begin: "(?x)\n\t\t\t\t\t\t\t\t\t(^\\s*)\t\t\t\t\t\t\t\t# Leading whitespace\n\
579
580
  \t\t\t\t\t\t\t\t\t(arguments)\\b([^%]*)\n\t\t\t\t\t\t\t\t\t\\s*\n\t\t\t\t\
@@ -617,7 +618,7 @@ repository:
617
618
  comment: "\n\t\t\t\tFunction call; matrix or array index (subscript)\n\t\t\t\t\
618
619
  We don't include $self here to avoid matching command syntax inside (), [],\
619
620
  \ {}\n\t\t\t"
620
- end: (\)|(?<!\.\.\..*)\n)
621
+ end: (\)|(?<!\.{3}.*)\n)
621
622
  endCaptures:
622
623
  '0':
623
624
  name: punctuation.section.parens.end.matlab
@@ -658,7 +659,7 @@ repository:
658
659
  name: punctuation.section.parens.begin.matlab
659
660
  comment: Index array with expression evaluated to variable name or number
660
661
  contentName: meta.parens.matlab
661
- end: (\)|(?<!\.\.\..*)\n)
662
+ end: (\)|(?<!\.{3}.*)\n)
662
663
  endCaptures:
663
664
  '0':
664
665
  name: punctuation.section.parens.end.matlab
@@ -673,7 +674,7 @@ repository:
673
674
  - include: '#variables'
674
675
  comment: We don't include $self here to avoid matching command syntax inside (),
675
676
  [], {}
676
- end: (\}|(?<!\.\.\..*)\n)
677
+ end: (\}|(?<!\.{3}.*)\n)
677
678
  patterns:
678
679
  - include: '#end_in_parentheses'
679
680
  - include: '#rules_before_command_dual'
@@ -685,7 +686,7 @@ repository:
685
686
  '2':
686
687
  name: comment.continuation.line.matlab
687
688
  comment: Line continuations
688
- match: (\.\.\.)(.*)$
689
+ match: (\.{3})(.*)$
689
690
  name: meta.continuation.line.matlab
690
691
  multiple_assignment:
691
692
  begin: \[(?=[^\]]+\]\s*=[a-zA-Z0-9_\s(])
@@ -740,19 +741,19 @@ repository:
740
741
  match: (?<!\w)\?(?=\w)
741
742
  name: keyword.operator.other.question.matlab
742
743
  - comment: Arithmetic operator symbols
743
- match: (?<=[a-zA-Z0-9\s])(\+|-|\*|\.\*|/|\./|\\|\.\\|\^|\.\^)(?=[a-zA-Z0-9\s]|(?:\.\.\.))
744
+ match: (?<=[a-zA-Z0-9\s])(\+|-|\*|\.\*|/|\./|\\|\.\\|\^|\.\^)(?=[a-zA-Z0-9\s]|(?:\.{3}))
744
745
  name: keyword.operator.arithmetic.matlab
745
746
  - comment: Operator symbols
746
- match: (?<=[a-zA-Z0-9\s])(==|~=|&|&&|\||\|\|)(?=[a-zA-Z0-9\s]|(?:\.\.\.))
747
+ match: (?<=[a-zA-Z0-9\s])(==|~=|&|&&|\||\|\|)(?=[a-zA-Z0-9\s]|(?:\.{3}))
747
748
  name: keyword.operator.logical.matlab
748
749
  - comment: Assignment operator
749
750
  match: (?<=[a-zA-Z0-9\s])(=)(?!=)
750
751
  name: keyword.operator.assignment.matlab
751
752
  - comment: Colon operator for vector creation/indexing
752
- match: (?<=[a-zA-Z0-9_\s(){,]|^):(?=[a-zA-Z0-9_\s()},]|$||(?:\.\.\.))
753
+ match: (?<=[a-zA-Z0-9_\s(){,]|^):(?=[a-zA-Z0-9_\s()},]|$||(?:\.{3}))
753
754
  name: keyword.operator.vector.colon.matlab
754
755
  - comment: Comparative operators
755
- match: (?<=[a-zA-Z0-9\s])(>|>=|<|<=)(?=[a-zA-Z0-9\s]|(?:\.\.\.))
756
+ match: (?<=[a-zA-Z0-9\s])(>|>=|<|<=)(?=[a-zA-Z0-9\s]|(?:\.{3}))
756
757
  name: keyword.operator.relational.matlab
757
758
  parentheses:
758
759
  begin: \(
@@ -762,7 +763,7 @@ repository:
762
763
  comment: "\n\t\t\t\tOperator precedence in expressions\n\t\t\t\tWe don't include\
763
764
  \ $self here to avoid matching command syntax inside (), [], {}\n\t\t\t"
764
765
  contentName: meta.parens.matlab
765
- end: (\)|(?<!\.\.\..*)\n)
766
+ end: (\)|(?<!\.{3}.*)\n)
766
767
  endCaptures:
767
768
  '0':
768
769
  name: punctuation.section.parens.end.matlab
@@ -935,7 +936,7 @@ repository:
935
936
  comment: "\n\t\t\t\tSuperclass method call; matrix or array index (subscript)\n\
936
937
  \t\t\t\tWe don't include $self here to avoid matching command syntax inside\
937
938
  \ (), [], {}\n\t\t\t"
938
- end: (\)|(?<!\.\.\..*)\n)
939
+ end: (\)|(?<!\.{3}.*)\n)
939
940
  endCaptures:
940
941
  '0':
941
942
  name: punctuation.section.parens.end.matlab
@@ -1,4 +1,4 @@
1
- from onigurumacffi import _Pattern as Pattern, _Match as Match
1
+ from onigurumacffi import _Pattern as Pattern, _Match as Match, compile
2
2
 
3
3
  from .logging import LOGGER
4
4
  from .exceptions import FileNotFound, ImpossibleSpan
@@ -16,6 +16,7 @@ class ContentHandler(object):
16
16
  are index by a tuple (line_number, line_position). Additionally, the handler contains the
17
17
  search method to match a search span against a input oniguruma regex pattern.
18
18
  """
19
+ notLookForwardEOL = compile("(?<!\(\?=[^\(]*)\$")
19
20
 
20
21
  def __init__(self, source: str) -> None:
21
22
  self.source = source
@@ -150,7 +151,7 @@ class ContentHandler(object):
150
151
  pattern: Pattern,
151
152
  starting: POS,
152
153
  boundary: POS | None = None,
153
- leading_chars: int = 0,
154
+ greedy: bool = False,
154
155
  **kwargs,
155
156
  ) -> (Match | None, tuple[POS, POS] | None):
156
157
  """Matches the stream against a capture group.
@@ -167,7 +168,7 @@ class ContentHandler(object):
167
168
  """
168
169
 
169
170
  if pattern._pattern in ["\\z", "\\Z"]:
170
- leading_chars = 2
171
+ greedy = True
171
172
 
172
173
  # Get line from starting (and boundary) positions
173
174
  if boundary and starting[0] == boundary[0]:
@@ -184,7 +185,7 @@ class ContentHandler(object):
184
185
  # Check that no charaters are skipped in case ws-only is enabled
185
186
  if matching:
186
187
  leading_string = line[init_pos : matching.start()]
187
- if leading_string and not (leading_chars == 2 or (leading_chars == 1 and leading_string.isspace())):
188
+ if leading_string and not (greedy or (not greedy and leading_string.isspace())):
188
189
  return None, None
189
190
  else:
190
191
  return None, None
@@ -197,11 +198,11 @@ class ContentHandler(object):
197
198
  if boundary and close_pos > boundary:
198
199
  return None, None
199
200
 
200
- if leading_string and not leading_string.isspace() and leading_chars == 2:
201
+ if leading_string and not leading_string.isspace() and greedy:
201
202
  LOGGER.warning(f"skipping < {leading_string} >", position=start_pos, depth=kwargs.get("depth", 0))
202
203
 
203
204
  # Include \n in match span if pattern matches on end of line $
204
- if "$" in pattern._pattern and matching.end() + 1 == self.line_lengths[starting[0]]:
205
+ if self.notLookForwardEOL.search(pattern._pattern) and matching.end() + 1 == self.line_lengths[starting[0]]:
205
206
  newline_matching = pattern.search(line[:-1])
206
207
  if newline_matching and newline_matching.span() == matching.span():
207
208
  close_pos = (starting[0], matching.end() + 1)
@@ -285,7 +285,7 @@ class PatternsParser(ParserHasPatterns):
285
285
  handler: ContentHandler,
286
286
  starting: POS,
287
287
  boundary: POS | None = None,
288
- leading_chars: int = 1,
288
+ greedy: bool = False,
289
289
  find_one: bool = True,
290
290
  **kwargs,
291
291
  ) -> tuple[bool, list[ContentElement], tuple[int, int]]:
@@ -306,7 +306,7 @@ class PatternsParser(ParserHasPatterns):
306
306
  handler,
307
307
  current,
308
308
  boundary=boundary,
309
- leading_chars=leading_chars,
309
+ greedy=greedy,
310
310
  **kwargs,
311
311
  )
312
312
  if parsed:
@@ -322,7 +322,7 @@ class PatternsParser(ParserHasPatterns):
322
322
  if find_one:
323
323
  break
324
324
 
325
- if not parsed and leading_chars != 2:
325
+ if not parsed and not greedy:
326
326
  # Try again if previously allowed no leading white space charaters, only when multple patterns are to be found
327
327
  options_span, options_elements = {}, {}
328
328
  for parser in patterns:
@@ -330,7 +330,7 @@ class PatternsParser(ParserHasPatterns):
330
330
  handler,
331
331
  current,
332
332
  boundary=boundary,
333
- leading_chars=2,
333
+ greedy=True,
334
334
  **kwargs,
335
335
  )
336
336
  if parsed:
@@ -349,8 +349,21 @@ class PatternsParser(ParserHasPatterns):
349
349
  LOGGER.info(
350
350
  f"{self.__class__.__name__} chosen pattern of {parser}", self, current, kwargs.get("depth", 0)
351
351
  )
352
- else:
352
+ elif self != self.language:
353
353
  break
354
+ else:
355
+ remainder = handler.read_line(current)
356
+ if not remainder.isspace():
357
+ LOGGER.warning(
358
+ f"{self.__class__.__name__} remainder of line not parsed: {remainder}", self, current, kwargs.get("depth", 0)
359
+ )
360
+ if current[0] + 1 <= len(handler.lines):
361
+ current = (current[0] + 1, 0)
362
+ else:
363
+ LOGGER.debug(
364
+ f"{self.__class__.__name__} EOF encountered", self, current, kwargs.get("depth", 0)
365
+ )
366
+ break
354
367
 
355
368
  if current == starting:
356
369
  LOGGER.warning(
@@ -370,13 +383,12 @@ class PatternsParser(ParserHasPatterns):
370
383
  break
371
384
 
372
385
  if self.token:
373
- closing = boundary if starting == current else current
374
386
  elements = [
375
387
  ContentElement(
376
388
  token=self.token,
377
389
  grammar=self.grammar,
378
- content=handler.read_pos(starting, closing),
379
- characters=handler.chars(starting, closing),
390
+ content=handler.read_pos(starting, boundary),
391
+ characters=handler.chars(starting, boundary),
380
392
  children=elements,
381
393
  )
382
394
  ]
@@ -433,7 +445,7 @@ class BeginEndParser(ParserHasPatterns):
433
445
  handler: ContentHandler,
434
446
  starting: POS,
435
447
  boundary: POS | None = None,
436
- leading_chars: int = 1,
448
+ greedy: bool = False,
437
449
  **kwargs,
438
450
  ) -> (bool, list[ContentElement], tuple[POS, POS] | None):
439
451
  """The parse method for grammars for which a begin/end pattern is provided."""
@@ -444,7 +456,7 @@ class BeginEndParser(ParserHasPatterns):
444
456
  starting,
445
457
  boundary=boundary,
446
458
  parsers=self.parsers_begin,
447
- leading_chars=leading_chars,
459
+ greedy=greedy,
448
460
  **kwargs
449
461
  )
450
462
 
@@ -473,7 +485,7 @@ class BeginEndParser(ParserHasPatterns):
473
485
  # Try to find patterns first with no leading whitespace charaters allowed
474
486
  for parser in patterns:
475
487
  parsed, capture_elements, capture_span = parser._parse(
476
- handler, current, boundary=boundary, leading_chars=1, **kwargs
488
+ handler, current, boundary=boundary, greedy=False, **kwargs
477
489
  )
478
490
  if parsed:
479
491
  if parser == self:
@@ -490,7 +502,7 @@ class BeginEndParser(ParserHasPatterns):
490
502
  current,
491
503
  boundary=boundary,
492
504
  parsers=self.parsers_end,
493
- leading_chars=1,
505
+ greedy=False,
494
506
  **kwargs
495
507
  )
496
508
 
@@ -507,7 +519,7 @@ class BeginEndParser(ParserHasPatterns):
507
519
  handler,
508
520
  current,
509
521
  boundary=boundary,
510
- leading_chars=2,
522
+ greedy=True,
511
523
  **kwargs,
512
524
  )
513
525
  if parsed:
@@ -538,7 +550,7 @@ class BeginEndParser(ParserHasPatterns):
538
550
  current,
539
551
  boundary=boundary,
540
552
  parsers=self.parsers_end,
541
- leading_chars=2,
553
+ greedy=True,
542
554
  **kwargs
543
555
  )
544
556