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.
@@ -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 == '>':
@@ -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[dict]:
1886
- """Parse injection filter: [type::helper=value]"""
1887
- if not self._match(TokenType.BRACKET_START):
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
- 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
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[f'{filter_type}::{helper}'] = True
1969
+ filter_info['type'] = filter_type
1970
+ elif self._check(TokenType.COMMA):
1971
+ self._advance()
1902
1972
  else:
1903
- filter_info['type'] = filter_type
1904
- elif self._check(TokenType.COMMA):
1905
- self._advance()
1906
- else:
1907
- break
1973
+ break
1908
1974
 
1909
- self._expect(TokenType.BRACKET_END)
1910
- return filter_info if filter_info else None
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,