IncludeCPP 3.7.9__py3-none-any.whl → 3.7.25__py3-none-any.whl
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.
- includecpp/__init__.py +1 -1
- includecpp/__init__.pyi +2 -2
- includecpp/cli/commands.py +107 -65
- includecpp/core/cssl/__init__.py +7 -2
- includecpp/core/cssl/cssl_builtins.py +201 -9
- includecpp/core/cssl/cssl_builtins.pyi +3682 -401
- includecpp/core/cssl/cssl_parser.py +117 -29
- includecpp/core/cssl/cssl_runtime.py +446 -25
- includecpp/core/cssl/cssl_syntax.py +7 -7
- includecpp/core/cssl/cssl_types.py +75 -2
- includecpp/core/cssl_bridge.py +64 -6
- includecpp/vscode/cssl/extension.js +133 -0
- includecpp/vscode/cssl/images/cssl.png +0 -0
- includecpp/vscode/cssl/images/cssl_pl.png +0 -0
- includecpp/vscode/cssl/package.json +117 -11
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +38 -15
- {includecpp-3.7.9.dist-info → includecpp-3.7.25.dist-info}/METADATA +2 -2
- {includecpp-3.7.9.dist-info → includecpp-3.7.25.dist-info}/RECORD +22 -19
- {includecpp-3.7.9.dist-info → includecpp-3.7.25.dist-info}/WHEEL +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.7.25.dist-info}/entry_points.txt +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.7.25.dist-info}/licenses/LICENSE +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.7.25.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
CSSL Parser - Lexer and Parser for
|
|
2
|
+
CSSL Parser - Lexer and Parser for CSSL Language
|
|
3
3
|
|
|
4
4
|
Features:
|
|
5
5
|
- Complete tokenization of CSSL syntax
|
|
@@ -252,8 +252,15 @@ class CSSLLexer:
|
|
|
252
252
|
# $<name> shared object reference
|
|
253
253
|
self._read_shared_ref()
|
|
254
254
|
elif char == '%':
|
|
255
|
-
# %<name> captured reference
|
|
256
|
-
self.
|
|
255
|
+
# Check if this is %<name> captured reference or % modulo operator
|
|
256
|
+
next_char = self._peek(1)
|
|
257
|
+
if next_char and (next_char.isalpha() or next_char == '_'):
|
|
258
|
+
# %<name> captured reference (for infusion)
|
|
259
|
+
self._read_captured_ref()
|
|
260
|
+
else:
|
|
261
|
+
# % modulo operator
|
|
262
|
+
self._add_token(TokenType.MODULO, '%')
|
|
263
|
+
self._advance()
|
|
257
264
|
elif char == '&':
|
|
258
265
|
# & for references
|
|
259
266
|
if self._peek(1) == '&':
|
|
@@ -321,9 +328,6 @@ class CSSLLexer:
|
|
|
321
328
|
else:
|
|
322
329
|
# Already handled by // comment check above, but just in case
|
|
323
330
|
self._skip_comment()
|
|
324
|
-
elif char == '%':
|
|
325
|
-
self._add_token(TokenType.MODULO, '%')
|
|
326
|
-
self._advance()
|
|
327
331
|
elif char == '<':
|
|
328
332
|
self._read_less_than()
|
|
329
333
|
elif char == '>':
|
|
@@ -848,7 +852,7 @@ class CSSLParser:
|
|
|
848
852
|
if self._match_keyword('open'):
|
|
849
853
|
param_info['open'] = True
|
|
850
854
|
|
|
851
|
-
# Handle type annotations
|
|
855
|
+
# Handle type annotations (builtin types like int, string, etc.)
|
|
852
856
|
if self._check(TokenType.KEYWORD) and self._is_type_keyword(self._current().value):
|
|
853
857
|
param_info['type'] = self._advance().value
|
|
854
858
|
|
|
@@ -872,6 +876,39 @@ class CSSLParser:
|
|
|
872
876
|
self._advance()
|
|
873
877
|
param_info['generic'] = ''.join(generic_parts)
|
|
874
878
|
|
|
879
|
+
# Handle custom class types (identifier followed by another identifier = type + name)
|
|
880
|
+
elif self._check(TokenType.IDENTIFIER):
|
|
881
|
+
# Look ahead: if next token is also an identifier, current is the type
|
|
882
|
+
saved_pos = self.pos
|
|
883
|
+
potential_type = self._advance().value
|
|
884
|
+
|
|
885
|
+
# Check for generic type parameter <T> on custom type
|
|
886
|
+
if self._check(TokenType.COMPARE_LT):
|
|
887
|
+
self._advance()
|
|
888
|
+
generic_parts = []
|
|
889
|
+
depth = 1
|
|
890
|
+
while depth > 0 and not self._is_at_end():
|
|
891
|
+
if self._check(TokenType.COMPARE_LT):
|
|
892
|
+
depth += 1
|
|
893
|
+
generic_parts.append('<')
|
|
894
|
+
elif self._check(TokenType.COMPARE_GT):
|
|
895
|
+
depth -= 1
|
|
896
|
+
if depth > 0:
|
|
897
|
+
generic_parts.append('>')
|
|
898
|
+
elif self._check(TokenType.COMMA):
|
|
899
|
+
generic_parts.append(',')
|
|
900
|
+
else:
|
|
901
|
+
generic_parts.append(self._current().value)
|
|
902
|
+
self._advance()
|
|
903
|
+
param_info['generic'] = ''.join(generic_parts)
|
|
904
|
+
|
|
905
|
+
# If followed by identifier, this is "Type name" pattern
|
|
906
|
+
if self._check(TokenType.IDENTIFIER):
|
|
907
|
+
param_info['type'] = potential_type
|
|
908
|
+
else:
|
|
909
|
+
# Not a type, restore position - this is just a param name
|
|
910
|
+
self.pos = saved_pos
|
|
911
|
+
|
|
875
912
|
# Handle reference operator &
|
|
876
913
|
if self._match(TokenType.AMPERSAND):
|
|
877
914
|
param_info['ref'] = True
|
|
@@ -914,6 +951,27 @@ class CSSLParser:
|
|
|
914
951
|
self._expect(TokenType.BLOCK_END)
|
|
915
952
|
return node
|
|
916
953
|
|
|
954
|
+
def _looks_like_namespace_call(self) -> bool:
|
|
955
|
+
"""Check if current position looks like a namespace function call.
|
|
956
|
+
|
|
957
|
+
Pattern: keyword::identifier(...) like json::write(), string::cut()
|
|
958
|
+
This allows type keywords to be used as namespace prefixes for function calls.
|
|
959
|
+
"""
|
|
960
|
+
if not self._check(TokenType.KEYWORD):
|
|
961
|
+
return False
|
|
962
|
+
|
|
963
|
+
# Save position
|
|
964
|
+
saved_pos = self.pos
|
|
965
|
+
|
|
966
|
+
self._advance() # Skip keyword
|
|
967
|
+
|
|
968
|
+
# Must be followed by ::
|
|
969
|
+
result = self._check(TokenType.DOUBLE_COLON)
|
|
970
|
+
|
|
971
|
+
# Restore position
|
|
972
|
+
self.pos = saved_pos
|
|
973
|
+
return result
|
|
974
|
+
|
|
917
975
|
def _looks_like_typed_variable(self) -> bool:
|
|
918
976
|
"""Check if current position looks like a typed variable declaration:
|
|
919
977
|
type_name varName; or type_name<T> varName; or type_name varName = value;
|
|
@@ -1415,7 +1473,8 @@ class CSSLParser:
|
|
|
1415
1473
|
elif (self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or
|
|
1416
1474
|
self._check(TokenType.CAPTURED_REF) or self._check(TokenType.SHARED_REF) or
|
|
1417
1475
|
self._check(TokenType.GLOBAL_REF) or self._check(TokenType.SELF_REF) or
|
|
1418
|
-
(self._check(TokenType.KEYWORD) and self._current().value in ('this', 'new'))
|
|
1476
|
+
(self._check(TokenType.KEYWORD) and self._current().value in ('this', 'new')) or
|
|
1477
|
+
self._looks_like_namespace_call()):
|
|
1419
1478
|
return self._parse_expression_statement()
|
|
1420
1479
|
else:
|
|
1421
1480
|
self._advance()
|
|
@@ -1882,32 +1941,42 @@ class CSSLParser:
|
|
|
1882
1941
|
self._expect(TokenType.BLOCK_END)
|
|
1883
1942
|
return node
|
|
1884
1943
|
|
|
1885
|
-
def _parse_injection_filter(self) -> Optional[
|
|
1886
|
-
"""Parse injection filter: [type::helper=value]
|
|
1887
|
-
|
|
1944
|
+
def _parse_injection_filter(self) -> Optional[list]:
|
|
1945
|
+
"""Parse injection filter(s): [type::helper=value] or [f1][f2][f3]...
|
|
1946
|
+
|
|
1947
|
+
Returns a list of filter dictionaries to support chained filters.
|
|
1948
|
+
"""
|
|
1949
|
+
if not self._check(TokenType.BRACKET_START):
|
|
1888
1950
|
return None
|
|
1889
1951
|
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1952
|
+
filters = []
|
|
1953
|
+
|
|
1954
|
+
# Parse multiple consecutive filter brackets
|
|
1955
|
+
while self._match(TokenType.BRACKET_START):
|
|
1956
|
+
filter_info = {}
|
|
1957
|
+
# Parse type::helper=value patterns within this bracket
|
|
1958
|
+
while not self._check(TokenType.BRACKET_END) and not self._is_at_end():
|
|
1959
|
+
if self._check(TokenType.IDENTIFIER) or self._check(TokenType.KEYWORD):
|
|
1960
|
+
filter_type = self._advance().value
|
|
1961
|
+
if self._match(TokenType.DOUBLE_COLON):
|
|
1962
|
+
helper = self._advance().value
|
|
1963
|
+
if self._match(TokenType.EQUALS):
|
|
1964
|
+
value = self._parse_expression()
|
|
1965
|
+
filter_info[f'{filter_type}::{helper}'] = value
|
|
1966
|
+
else:
|
|
1967
|
+
filter_info[f'{filter_type}::{helper}'] = True
|
|
1900
1968
|
else:
|
|
1901
|
-
filter_info[
|
|
1969
|
+
filter_info['type'] = filter_type
|
|
1970
|
+
elif self._check(TokenType.COMMA):
|
|
1971
|
+
self._advance()
|
|
1902
1972
|
else:
|
|
1903
|
-
|
|
1904
|
-
elif self._check(TokenType.COMMA):
|
|
1905
|
-
self._advance()
|
|
1906
|
-
else:
|
|
1907
|
-
break
|
|
1973
|
+
break
|
|
1908
1974
|
|
|
1909
|
-
|
|
1910
|
-
|
|
1975
|
+
self._expect(TokenType.BRACKET_END)
|
|
1976
|
+
if filter_info:
|
|
1977
|
+
filters.append(filter_info)
|
|
1978
|
+
|
|
1979
|
+
return filters if filters else None
|
|
1911
1980
|
|
|
1912
1981
|
def _parse_expression_statement(self) -> Optional[ASTNode]:
|
|
1913
1982
|
expr = self._parse_expression()
|
|
@@ -2118,6 +2187,11 @@ class CSSLParser:
|
|
|
2118
2187
|
elif self._match(TokenType.COMPARE_GE):
|
|
2119
2188
|
right = self._parse_term()
|
|
2120
2189
|
left = ASTNode('binary', value={'op': '>=', 'left': left, 'right': right})
|
|
2190
|
+
elif self._check(TokenType.KEYWORD) and self._peek().value == 'in':
|
|
2191
|
+
# 'in' operator for containment: item in list
|
|
2192
|
+
self._advance() # consume 'in'
|
|
2193
|
+
right = self._parse_term()
|
|
2194
|
+
left = ASTNode('binary', value={'op': 'in', 'left': left, 'right': right})
|
|
2121
2195
|
else:
|
|
2122
2196
|
break
|
|
2123
2197
|
|
|
@@ -2504,6 +2578,20 @@ class CSSLParser:
|
|
|
2504
2578
|
|
|
2505
2579
|
self._expect(TokenType.BLOCK_END) # consume }
|
|
2506
2580
|
|
|
2581
|
+
# Check for array-style initialization: vector<int>[1, 2, 3], array<string>["a", "b"]
|
|
2582
|
+
elif self._check(TokenType.BRACKET_START):
|
|
2583
|
+
self._advance() # consume [
|
|
2584
|
+
init_values = []
|
|
2585
|
+
|
|
2586
|
+
while not self._check(TokenType.BRACKET_END) and not self._is_at_end():
|
|
2587
|
+
init_values.append(self._parse_expression())
|
|
2588
|
+
|
|
2589
|
+
# Optional comma
|
|
2590
|
+
if self._check(TokenType.COMMA):
|
|
2591
|
+
self._advance()
|
|
2592
|
+
|
|
2593
|
+
self._expect(TokenType.BRACKET_END) # consume ]
|
|
2594
|
+
|
|
2507
2595
|
return ASTNode('type_instantiation', value={
|
|
2508
2596
|
'type': name,
|
|
2509
2597
|
'element_type': element_type,
|