IncludeCPP 3.7.9__py3-none-any.whl → 3.8.0__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 +129 -67
- includecpp/core/cssl/__init__.py +7 -2
- includecpp/core/cssl/cssl_builtins.py +411 -9
- includecpp/core/cssl/cssl_builtins.pyi +3682 -401
- includecpp/core/cssl/cssl_parser.py +130 -31
- includecpp/core/cssl/cssl_runtime.py +462 -26
- 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/snippets/cssl.snippets.json +126 -0
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +46 -15
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/METADATA +56 -225
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/RECORD +23 -20
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/WHEEL +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/entry_points.txt +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/licenses/LICENSE +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.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 == '>':
|
|
@@ -712,7 +716,7 @@ class CSSLParser:
|
|
|
712
716
|
def _is_type_keyword(self, value: str) -> bool:
|
|
713
717
|
"""Check if a keyword is a type declaration"""
|
|
714
718
|
return value in ('int', 'string', 'float', 'bool', 'void', 'json', 'array', 'vector', 'stack',
|
|
715
|
-
'list', 'dictionary', 'dict', 'instance', 'map',
|
|
719
|
+
'list', 'dictionary', 'dict', 'instance', 'map', 'openquote', 'parameter',
|
|
716
720
|
'dynamic', 'datastruct', 'dataspace', 'shuffled', 'iterator', 'combo', 'structure')
|
|
717
721
|
|
|
718
722
|
def _looks_like_function_declaration(self) -> bool:
|
|
@@ -723,14 +727,17 @@ class CSSLParser:
|
|
|
723
727
|
- undefined int funcName(...)
|
|
724
728
|
- vector<string> funcName(...)
|
|
725
729
|
- undefined void funcName(...)
|
|
730
|
+
- private super virtual meta FuncName(...) <- modifiers without return type
|
|
726
731
|
"""
|
|
727
732
|
saved_pos = self.pos
|
|
733
|
+
has_modifiers = False
|
|
728
734
|
|
|
729
735
|
# Skip modifiers (undefined, open, meta, super, closed, private, virtual)
|
|
730
736
|
while self._check(TokenType.KEYWORD) and self._is_function_modifier(self._current().value):
|
|
731
737
|
self._advance()
|
|
738
|
+
has_modifiers = True
|
|
732
739
|
|
|
733
|
-
# Check for type keyword
|
|
740
|
+
# Check for type keyword (optional if modifiers present)
|
|
734
741
|
if self._check(TokenType.KEYWORD) and self._is_type_keyword(self._current().value):
|
|
735
742
|
self._advance()
|
|
736
743
|
|
|
@@ -752,6 +759,14 @@ class CSSLParser:
|
|
|
752
759
|
self.pos = saved_pos
|
|
753
760
|
return is_func
|
|
754
761
|
|
|
762
|
+
# If we have modifiers and the next token is an identifier followed by (
|
|
763
|
+
# This handles: private super virtual meta FuncName()
|
|
764
|
+
elif has_modifiers and self._check(TokenType.IDENTIFIER):
|
|
765
|
+
self._advance()
|
|
766
|
+
is_func = self._check(TokenType.PAREN_START)
|
|
767
|
+
self.pos = saved_pos
|
|
768
|
+
return is_func
|
|
769
|
+
|
|
755
770
|
self.pos = saved_pos
|
|
756
771
|
return False
|
|
757
772
|
|
|
@@ -848,7 +863,7 @@ class CSSLParser:
|
|
|
848
863
|
if self._match_keyword('open'):
|
|
849
864
|
param_info['open'] = True
|
|
850
865
|
|
|
851
|
-
# Handle type annotations
|
|
866
|
+
# Handle type annotations (builtin types like int, string, etc.)
|
|
852
867
|
if self._check(TokenType.KEYWORD) and self._is_type_keyword(self._current().value):
|
|
853
868
|
param_info['type'] = self._advance().value
|
|
854
869
|
|
|
@@ -872,6 +887,39 @@ class CSSLParser:
|
|
|
872
887
|
self._advance()
|
|
873
888
|
param_info['generic'] = ''.join(generic_parts)
|
|
874
889
|
|
|
890
|
+
# Handle custom class types (identifier followed by another identifier = type + name)
|
|
891
|
+
elif self._check(TokenType.IDENTIFIER):
|
|
892
|
+
# Look ahead: if next token is also an identifier, current is the type
|
|
893
|
+
saved_pos = self.pos
|
|
894
|
+
potential_type = self._advance().value
|
|
895
|
+
|
|
896
|
+
# Check for generic type parameter <T> on custom type
|
|
897
|
+
if self._check(TokenType.COMPARE_LT):
|
|
898
|
+
self._advance()
|
|
899
|
+
generic_parts = []
|
|
900
|
+
depth = 1
|
|
901
|
+
while depth > 0 and not self._is_at_end():
|
|
902
|
+
if self._check(TokenType.COMPARE_LT):
|
|
903
|
+
depth += 1
|
|
904
|
+
generic_parts.append('<')
|
|
905
|
+
elif self._check(TokenType.COMPARE_GT):
|
|
906
|
+
depth -= 1
|
|
907
|
+
if depth > 0:
|
|
908
|
+
generic_parts.append('>')
|
|
909
|
+
elif self._check(TokenType.COMMA):
|
|
910
|
+
generic_parts.append(',')
|
|
911
|
+
else:
|
|
912
|
+
generic_parts.append(self._current().value)
|
|
913
|
+
self._advance()
|
|
914
|
+
param_info['generic'] = ''.join(generic_parts)
|
|
915
|
+
|
|
916
|
+
# If followed by identifier, this is "Type name" pattern
|
|
917
|
+
if self._check(TokenType.IDENTIFIER):
|
|
918
|
+
param_info['type'] = potential_type
|
|
919
|
+
else:
|
|
920
|
+
# Not a type, restore position - this is just a param name
|
|
921
|
+
self.pos = saved_pos
|
|
922
|
+
|
|
875
923
|
# Handle reference operator &
|
|
876
924
|
if self._match(TokenType.AMPERSAND):
|
|
877
925
|
param_info['ref'] = True
|
|
@@ -914,6 +962,27 @@ class CSSLParser:
|
|
|
914
962
|
self._expect(TokenType.BLOCK_END)
|
|
915
963
|
return node
|
|
916
964
|
|
|
965
|
+
def _looks_like_namespace_call(self) -> bool:
|
|
966
|
+
"""Check if current position looks like a namespace function call.
|
|
967
|
+
|
|
968
|
+
Pattern: keyword::identifier(...) like json::write(), string::cut()
|
|
969
|
+
This allows type keywords to be used as namespace prefixes for function calls.
|
|
970
|
+
"""
|
|
971
|
+
if not self._check(TokenType.KEYWORD):
|
|
972
|
+
return False
|
|
973
|
+
|
|
974
|
+
# Save position
|
|
975
|
+
saved_pos = self.pos
|
|
976
|
+
|
|
977
|
+
self._advance() # Skip keyword
|
|
978
|
+
|
|
979
|
+
# Must be followed by ::
|
|
980
|
+
result = self._check(TokenType.DOUBLE_COLON)
|
|
981
|
+
|
|
982
|
+
# Restore position
|
|
983
|
+
self.pos = saved_pos
|
|
984
|
+
return result
|
|
985
|
+
|
|
917
986
|
def _looks_like_typed_variable(self) -> bool:
|
|
918
987
|
"""Check if current position looks like a typed variable declaration:
|
|
919
988
|
type_name varName; or type_name<T> varName; or type_name varName = value;
|
|
@@ -1415,7 +1484,8 @@ class CSSLParser:
|
|
|
1415
1484
|
elif (self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or
|
|
1416
1485
|
self._check(TokenType.CAPTURED_REF) or self._check(TokenType.SHARED_REF) or
|
|
1417
1486
|
self._check(TokenType.GLOBAL_REF) or self._check(TokenType.SELF_REF) or
|
|
1418
|
-
(self._check(TokenType.KEYWORD) and self._current().value in ('this', 'new'))
|
|
1487
|
+
(self._check(TokenType.KEYWORD) and self._current().value in ('this', 'new')) or
|
|
1488
|
+
self._looks_like_namespace_call()):
|
|
1419
1489
|
return self._parse_expression_statement()
|
|
1420
1490
|
else:
|
|
1421
1491
|
self._advance()
|
|
@@ -1882,32 +1952,42 @@ class CSSLParser:
|
|
|
1882
1952
|
self._expect(TokenType.BLOCK_END)
|
|
1883
1953
|
return node
|
|
1884
1954
|
|
|
1885
|
-
def _parse_injection_filter(self) -> Optional[
|
|
1886
|
-
"""Parse injection filter: [type::helper=value]
|
|
1887
|
-
|
|
1955
|
+
def _parse_injection_filter(self) -> Optional[list]:
|
|
1956
|
+
"""Parse injection filter(s): [type::helper=value] or [f1][f2][f3]...
|
|
1957
|
+
|
|
1958
|
+
Returns a list of filter dictionaries to support chained filters.
|
|
1959
|
+
"""
|
|
1960
|
+
if not self._check(TokenType.BRACKET_START):
|
|
1888
1961
|
return None
|
|
1889
1962
|
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1963
|
+
filters = []
|
|
1964
|
+
|
|
1965
|
+
# Parse multiple consecutive filter brackets
|
|
1966
|
+
while self._match(TokenType.BRACKET_START):
|
|
1967
|
+
filter_info = {}
|
|
1968
|
+
# Parse type::helper=value patterns within this bracket
|
|
1969
|
+
while not self._check(TokenType.BRACKET_END) and not self._is_at_end():
|
|
1970
|
+
if self._check(TokenType.IDENTIFIER) or self._check(TokenType.KEYWORD):
|
|
1971
|
+
filter_type = self._advance().value
|
|
1972
|
+
if self._match(TokenType.DOUBLE_COLON):
|
|
1973
|
+
helper = self._advance().value
|
|
1974
|
+
if self._match(TokenType.EQUALS):
|
|
1975
|
+
value = self._parse_expression()
|
|
1976
|
+
filter_info[f'{filter_type}::{helper}'] = value
|
|
1977
|
+
else:
|
|
1978
|
+
filter_info[f'{filter_type}::{helper}'] = True
|
|
1900
1979
|
else:
|
|
1901
|
-
filter_info[
|
|
1980
|
+
filter_info['type'] = filter_type
|
|
1981
|
+
elif self._check(TokenType.COMMA):
|
|
1982
|
+
self._advance()
|
|
1902
1983
|
else:
|
|
1903
|
-
|
|
1904
|
-
elif self._check(TokenType.COMMA):
|
|
1905
|
-
self._advance()
|
|
1906
|
-
else:
|
|
1907
|
-
break
|
|
1984
|
+
break
|
|
1908
1985
|
|
|
1909
|
-
|
|
1910
|
-
|
|
1986
|
+
self._expect(TokenType.BRACKET_END)
|
|
1987
|
+
if filter_info:
|
|
1988
|
+
filters.append(filter_info)
|
|
1989
|
+
|
|
1990
|
+
return filters if filters else None
|
|
1911
1991
|
|
|
1912
1992
|
def _parse_expression_statement(self) -> Optional[ASTNode]:
|
|
1913
1993
|
expr = self._parse_expression()
|
|
@@ -2118,6 +2198,11 @@ class CSSLParser:
|
|
|
2118
2198
|
elif self._match(TokenType.COMPARE_GE):
|
|
2119
2199
|
right = self._parse_term()
|
|
2120
2200
|
left = ASTNode('binary', value={'op': '>=', 'left': left, 'right': right})
|
|
2201
|
+
elif self._check(TokenType.KEYWORD) and self._peek().value == 'in':
|
|
2202
|
+
# 'in' operator for containment: item in list
|
|
2203
|
+
self._advance() # consume 'in'
|
|
2204
|
+
right = self._parse_term()
|
|
2205
|
+
left = ASTNode('binary', value={'op': 'in', 'left': left, 'right': right})
|
|
2121
2206
|
else:
|
|
2122
2207
|
break
|
|
2123
2208
|
|
|
@@ -2504,6 +2589,20 @@ class CSSLParser:
|
|
|
2504
2589
|
|
|
2505
2590
|
self._expect(TokenType.BLOCK_END) # consume }
|
|
2506
2591
|
|
|
2592
|
+
# Check for array-style initialization: vector<int>[1, 2, 3], array<string>["a", "b"]
|
|
2593
|
+
elif self._check(TokenType.BRACKET_START):
|
|
2594
|
+
self._advance() # consume [
|
|
2595
|
+
init_values = []
|
|
2596
|
+
|
|
2597
|
+
while not self._check(TokenType.BRACKET_END) and not self._is_at_end():
|
|
2598
|
+
init_values.append(self._parse_expression())
|
|
2599
|
+
|
|
2600
|
+
# Optional comma
|
|
2601
|
+
if self._check(TokenType.COMMA):
|
|
2602
|
+
self._advance()
|
|
2603
|
+
|
|
2604
|
+
self._expect(TokenType.BRACKET_END) # consume ]
|
|
2605
|
+
|
|
2507
2606
|
return ASTNode('type_instantiation', value={
|
|
2508
2607
|
'type': name,
|
|
2509
2608
|
'element_type': element_type,
|