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.
@@ -1,5 +1,5 @@
1
1
  """
2
- CSSL Parser - Lexer and Parser for CSO Service Script Language
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 (for infusion)
256
- self._read_captured_ref()
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[dict]:
1886
- """Parse injection filter: [type::helper=value]"""
1887
- if not self._match(TokenType.BRACKET_START):
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
- filter_info = {}
1891
- # Parse type::helper=value patterns
1892
- while not self._check(TokenType.BRACKET_END) and not self._is_at_end():
1893
- if self._check(TokenType.IDENTIFIER) or self._check(TokenType.KEYWORD):
1894
- filter_type = self._advance().value
1895
- if self._match(TokenType.DOUBLE_COLON):
1896
- helper = self._advance().value
1897
- if self._match(TokenType.EQUALS):
1898
- value = self._parse_expression()
1899
- filter_info[f'{filter_type}::{helper}'] = value
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[f'{filter_type}::{helper}'] = True
1980
+ filter_info['type'] = filter_type
1981
+ elif self._check(TokenType.COMMA):
1982
+ self._advance()
1902
1983
  else:
1903
- filter_info['type'] = filter_type
1904
- elif self._check(TokenType.COMMA):
1905
- self._advance()
1906
- else:
1907
- break
1984
+ break
1908
1985
 
1909
- self._expect(TokenType.BRACKET_END)
1910
- return filter_info if filter_info else None
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,