IncludeCPP 4.0.2__py3-none-any.whl → 4.1.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.
@@ -113,6 +113,8 @@ class TokenType(Enum):
113
113
  # Append operator for constructor/function extension
114
114
  PLUS_PLUS = auto() # ++ for constructor/function append (keeps old + adds new)
115
115
  MINUS_MINUS = auto() # -- for potential future use
116
+ # Multi-language support (v4.1.0)
117
+ LANG_INSTANCE_REF = auto() # cpp$InstanceName, py$Object - cross-language instance access
116
118
 
117
119
 
118
120
  KEYWORDS = {
@@ -155,6 +157,8 @@ KEYWORDS = {
155
157
  'static', # Static method/function
156
158
  # CSSL Include Keywords
157
159
  'include', 'get',
160
+ # Multi-language support (v4.1.0)
161
+ 'supports', 'libinclude',
158
162
  }
159
163
 
160
164
  # Function modifiers that can appear in any order before function name
@@ -182,6 +186,12 @@ INJECTION_HELPERS = {
182
186
  'string', 'integer', 'json', 'array', 'vector', 'combo', 'dynamic', 'sql'
183
187
  }
184
188
 
189
+ # Language identifiers for multi-language support (v4.1.0)
190
+ # Used in lang$instance patterns like cpp$MyClass, py$Object
191
+ LANGUAGE_IDS = {
192
+ 'cpp', 'py', 'python', 'java', 'csharp', 'js', 'javascript'
193
+ }
194
+
185
195
 
186
196
  @dataclass
187
197
  class Token:
@@ -457,6 +467,25 @@ class CSSLLexer:
457
467
  self._advance()
458
468
  value = self.source[start:self.pos]
459
469
 
470
+ # Check for language$instance pattern (v4.1.0)
471
+ # e.g., cpp$MyClass, py$Object, java$Service
472
+ if value.lower() in LANGUAGE_IDS and self.pos < len(self.source) and self.source[self.pos] == '$':
473
+ lang_id = value
474
+ self._advance() # skip '$'
475
+ # Read instance name
476
+ instance_start = self.pos
477
+ while self.pos < len(self.source) and (self.source[self.pos].isalnum() or self.source[self.pos] == '_'):
478
+ self._advance()
479
+ instance_name = self.source[instance_start:self.pos]
480
+ if instance_name:
481
+ self._add_token(TokenType.LANG_INSTANCE_REF, {'lang': lang_id, 'instance': instance_name})
482
+ return
483
+ # If no instance name, revert and treat as normal identifier
484
+ self.pos = start
485
+ while self.pos < len(self.source) and (self.source[self.pos].isalnum() or self.source[self.pos] == '_'):
486
+ self._advance()
487
+ value = self.source[start:self.pos]
488
+
460
489
  if value in ('True', 'true'):
461
490
  self._add_token(TokenType.BOOLEAN, True)
462
491
  elif value in ('False', 'false'):
@@ -1350,13 +1379,7 @@ class CSSLParser:
1350
1379
  # Wrap in global_assignment to mark as global variable (same as 'global' keyword)
1351
1380
  global_stmt = ASTNode('global_assignment', value=stmt)
1352
1381
  root.children.append(global_stmt)
1353
- # Handle statements - keywords like 'instance', 'list', 'map' can be variable names
1354
- elif (self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or
1355
- self._check(TokenType.SELF_REF) or self._check(TokenType.SHARED_REF) or
1356
- self._check(TokenType.KEYWORD)):
1357
- stmt = self._parse_expression_statement()
1358
- if stmt:
1359
- root.children.append(stmt)
1382
+ # Control flow keywords must be checked BEFORE generic KEYWORD handling
1360
1383
  elif self._match_keyword('if'):
1361
1384
  root.children.append(self._parse_if())
1362
1385
  elif self._match_keyword('while'):
@@ -1365,6 +1388,13 @@ class CSSLParser:
1365
1388
  root.children.append(self._parse_for())
1366
1389
  elif self._match_keyword('foreach'):
1367
1390
  root.children.append(self._parse_foreach())
1391
+ # Handle statements - keywords like 'instance', 'list', 'map' can be variable names
1392
+ elif (self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or
1393
+ self._check(TokenType.SELF_REF) or self._check(TokenType.SHARED_REF) or
1394
+ self._check(TokenType.KEYWORD)):
1395
+ stmt = self._parse_expression_statement()
1396
+ if stmt:
1397
+ root.children.append(stmt)
1368
1398
  # Skip comments and newlines
1369
1399
  elif self._check(TokenType.COMMENT) or self._check(TokenType.NEWLINE):
1370
1400
  self._advance()
@@ -1627,15 +1657,22 @@ class CSSLParser:
1627
1657
  # class Child : extends Parent (param1, param2) { ... } <- constructor args for parent
1628
1658
  extends_class = None
1629
1659
  extends_is_python = False
1660
+ extends_lang_ref = None # v4.1.0: Cross-language inheritance (cpp$ClassName)
1630
1661
  extends_args = []
1631
1662
  overwrites_class = None
1632
1663
  overwrites_is_python = False
1664
+ supports_language = None # v4.1.0: Multi-language syntax support
1633
1665
 
1634
1666
  if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON):
1635
1667
  # Parse extends and/or overwrites (can be chained with : or ::)
1636
1668
  while True:
1637
1669
  if self._match_keyword('extends'):
1638
- if self._check(TokenType.IDENTIFIER):
1670
+ # v4.1.0: Check for cross-language inheritance: extends cpp$ClassName
1671
+ if self._check(TokenType.LANG_INSTANCE_REF):
1672
+ ref = self._advance().value
1673
+ extends_lang_ref = ref # {'lang': 'cpp', 'instance': 'ClassName'}
1674
+ extends_class = ref['instance']
1675
+ elif self._check(TokenType.IDENTIFIER):
1639
1676
  extends_class = self._advance().value
1640
1677
  elif self._check(TokenType.SHARED_REF):
1641
1678
  extends_class = self._advance().value
@@ -1660,8 +1697,20 @@ class CSSLParser:
1660
1697
  # Skip optional () after class name
1661
1698
  if self._match(TokenType.PAREN_START):
1662
1699
  self._expect(TokenType.PAREN_END)
1700
+ # v4.1.0: Parse 'supports' keyword for multi-language syntax
1701
+ elif self._match_keyword('supports'):
1702
+ if self._check(TokenType.AT):
1703
+ self._advance() # consume @
1704
+ if self._check(TokenType.IDENTIFIER):
1705
+ supports_language = '@' + self._advance().value
1706
+ else:
1707
+ raise CSSLSyntaxError("Expected language identifier after '@' in 'supports'")
1708
+ elif self._check(TokenType.IDENTIFIER):
1709
+ supports_language = self._advance().value
1710
+ else:
1711
+ raise CSSLSyntaxError("Expected language identifier after 'supports'")
1663
1712
  else:
1664
- raise CSSLSyntaxError("Expected 'extends' or 'overwrites' after ':' or '::' in class declaration")
1713
+ raise CSSLSyntaxError("Expected 'extends', 'overwrites', or 'supports' after ':' or '::' in class declaration")
1665
1714
  # Check for another : or :: for chaining
1666
1715
  if not (self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON)):
1667
1716
  break
@@ -1673,9 +1722,11 @@ class CSSLParser:
1673
1722
  'class_params': class_params,
1674
1723
  'extends': extends_class,
1675
1724
  'extends_is_python': extends_is_python,
1725
+ 'extends_lang_ref': extends_lang_ref, # v4.1.0
1676
1726
  'extends_args': extends_args,
1677
1727
  'overwrites': overwrites_class,
1678
- 'overwrites_is_python': overwrites_is_python
1728
+ 'overwrites_is_python': overwrites_is_python,
1729
+ 'supports_language': supports_language # v4.1.0
1679
1730
  }, children=[])
1680
1731
  self._expect(TokenType.BLOCK_START)
1681
1732
 
@@ -1945,6 +1996,7 @@ class CSSLParser:
1945
1996
  extends_method_ref = None
1946
1997
  overwrites_class_ref = None
1947
1998
  overwrites_method_ref = None
1999
+ supports_language = None # v4.1.0: Multi-language syntax support
1948
2000
 
1949
2001
  if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON):
1950
2002
  # Parse extends and/or overwrites (supports :: method-level syntax)
@@ -2005,6 +2057,18 @@ class CSSLParser:
2005
2057
  # Skip optional () after function/method name
2006
2058
  if self._match(TokenType.PAREN_START):
2007
2059
  self._expect(TokenType.PAREN_END)
2060
+ # v4.1.0: Parse 'supports' keyword for multi-language syntax
2061
+ elif self._match_keyword('supports'):
2062
+ if self._check(TokenType.AT):
2063
+ self._advance() # consume @
2064
+ if self._check(TokenType.IDENTIFIER):
2065
+ supports_language = '@' + self._advance().value
2066
+ else:
2067
+ raise CSSLSyntaxError("Expected language identifier after '@' in 'supports'")
2068
+ elif self._check(TokenType.IDENTIFIER):
2069
+ supports_language = self._advance().value
2070
+ else:
2071
+ raise CSSLSyntaxError("Expected language identifier after 'supports'")
2008
2072
  else:
2009
2073
  break
2010
2074
  # Check for another :: or : for chaining extends/overwrites
@@ -2092,7 +2156,9 @@ class CSSLParser:
2092
2156
  # New append mode fields
2093
2157
  'append_mode': append_mode,
2094
2158
  'append_ref_class': append_ref_class,
2095
- 'append_ref_member': append_ref_member
2159
+ 'append_ref_member': append_ref_member,
2160
+ # v4.1.0: Multi-language support
2161
+ 'supports_language': supports_language
2096
2162
  }, children=[])
2097
2163
  self._expect(TokenType.BLOCK_START)
2098
2164
 
@@ -2352,42 +2418,40 @@ class CSSLParser:
2352
2418
 
2353
2419
  Supports: i = i + 1, i++, ++i, i += 1, i -= 1
2354
2420
  """
2355
- # Check for prefix increment/decrement: ++i or --i
2356
- if self._check(TokenType.PLUS) or self._check(TokenType.MINUS):
2357
- op_token = self._advance()
2358
- # Check for double operator (++ or --)
2359
- if self._check(op_token.type):
2360
- self._advance()
2361
- var_name = self._advance().value
2362
- op = 'increment' if op_token.type == TokenType.PLUS else 'decrement'
2363
- return ASTNode('c_for_update', value={'var': var_name, 'op': op})
2421
+ # Check for prefix increment/decrement: ++i or --i (as single PLUS_PLUS/MINUS_MINUS token)
2422
+ if self._check(TokenType.PLUS_PLUS):
2423
+ self._advance()
2424
+ var_name = self._advance().value
2425
+ return ASTNode('c_for_update', value={'var': var_name, 'op': 'increment'})
2426
+ elif self._check(TokenType.MINUS_MINUS):
2427
+ self._advance()
2428
+ var_name = self._advance().value
2429
+ return ASTNode('c_for_update', value={'var': var_name, 'op': 'decrement'})
2364
2430
 
2365
2431
  # Regular variable assignment or postfix
2366
2432
  var_name = self._advance().value
2367
2433
 
2368
- # Check for postfix increment/decrement: i++ or i--
2369
- if self._check(TokenType.PLUS):
2434
+ # Check for postfix increment/decrement: i++ or i-- (as single PLUS_PLUS/MINUS_MINUS token)
2435
+ if self._check(TokenType.PLUS_PLUS):
2436
+ self._advance()
2437
+ return ASTNode('c_for_update', value={'var': var_name, 'op': 'increment'})
2438
+ elif self._check(TokenType.MINUS_MINUS):
2439
+ self._advance()
2440
+ return ASTNode('c_for_update', value={'var': var_name, 'op': 'decrement'})
2441
+ # i += value
2442
+ elif self._check(TokenType.PLUS):
2370
2443
  self._advance()
2371
- if self._check(TokenType.PLUS):
2444
+ if self._check(TokenType.EQUALS):
2372
2445
  self._advance()
2373
- return ASTNode('c_for_update', value={'var': var_name, 'op': 'increment'})
2374
- else:
2375
- # i += value
2376
- if self._check(TokenType.EQUALS):
2377
- self._advance()
2378
- value = self._parse_expression()
2379
- return ASTNode('c_for_update', value={'var': var_name, 'op': 'add', 'value': value})
2446
+ value = self._parse_expression()
2447
+ return ASTNode('c_for_update', value={'var': var_name, 'op': 'add', 'value': value})
2448
+ # i -= value
2380
2449
  elif self._check(TokenType.MINUS):
2381
2450
  self._advance()
2382
- if self._check(TokenType.MINUS):
2451
+ if self._check(TokenType.EQUALS):
2383
2452
  self._advance()
2384
- return ASTNode('c_for_update', value={'var': var_name, 'op': 'decrement'})
2385
- else:
2386
- # i -= value
2387
- if self._check(TokenType.EQUALS):
2388
- self._advance()
2389
- value = self._parse_expression()
2390
- return ASTNode('c_for_update', value={'var': var_name, 'op': 'subtract', 'value': value})
2453
+ value = self._parse_expression()
2454
+ return ASTNode('c_for_update', value={'var': var_name, 'op': 'subtract', 'value': value})
2391
2455
 
2392
2456
  # Regular assignment: i = expression
2393
2457
  if self._check(TokenType.EQUALS):
@@ -2948,6 +3012,14 @@ class CSSLParser:
2948
3012
  if self._match(TokenType.MINUS):
2949
3013
  operand = self._parse_unary()
2950
3014
  return ASTNode('unary', value={'op': '-', 'operand': operand})
3015
+ # Prefix increment: ++i
3016
+ if self._match(TokenType.PLUS_PLUS):
3017
+ operand = self._parse_unary()
3018
+ return ASTNode('increment', value={'op': 'prefix', 'operand': operand})
3019
+ # Prefix decrement: --i
3020
+ if self._match(TokenType.MINUS_MINUS):
3021
+ operand = self._parse_unary()
3022
+ return ASTNode('decrement', value={'op': 'prefix', 'operand': operand})
2951
3023
  if self._match(TokenType.AMPERSAND):
2952
3024
  # Reference operator: &variable or &@module
2953
3025
  operand = self._parse_unary()
@@ -3148,6 +3220,28 @@ class CSSLParser:
3148
3220
  break
3149
3221
  return node
3150
3222
 
3223
+ # v4.1.0: Cross-language instance reference: cpp$ClassName, py$Object
3224
+ if self._check(TokenType.LANG_INSTANCE_REF):
3225
+ token = self._advance()
3226
+ ref = token.value # {'lang': 'cpp', 'instance': 'ClassName'}
3227
+ node = ASTNode('lang_instance_ref', value=ref, line=token.line, column=token.column)
3228
+ # Check for member access, calls, indexing
3229
+ while True:
3230
+ if self._match(TokenType.PAREN_START):
3231
+ args, kwargs = self._parse_call_arguments()
3232
+ self._expect(TokenType.PAREN_END)
3233
+ node = ASTNode('call', value={'callee': node, 'args': args, 'kwargs': kwargs})
3234
+ elif self._match(TokenType.DOT):
3235
+ member = self._advance().value
3236
+ node = ASTNode('member_access', value={'object': node, 'member': member})
3237
+ elif self._match(TokenType.BRACKET_START):
3238
+ index = self._parse_expression()
3239
+ self._expect(TokenType.BRACKET_END)
3240
+ node = ASTNode('index_access', value={'object': node, 'index': index})
3241
+ else:
3242
+ break
3243
+ return node
3244
+
3151
3245
  if self._check(TokenType.NUMBER):
3152
3246
  return ASTNode('literal', value=self._advance().value)
3153
3247
 
@@ -3398,6 +3492,12 @@ class CSSLParser:
3398
3492
  index = self._parse_expression()
3399
3493
  self._expect(TokenType.BRACKET_END)
3400
3494
  node = ASTNode('index_access', value={'object': node, 'index': index})
3495
+ # Postfix increment: i++
3496
+ elif self._match(TokenType.PLUS_PLUS):
3497
+ node = ASTNode('increment', value={'op': 'postfix', 'operand': node})
3498
+ # Postfix decrement: i--
3499
+ elif self._match(TokenType.MINUS_MINUS):
3500
+ node = ASTNode('decrement', value={'op': 'postfix', 'operand': node})
3401
3501
  else:
3402
3502
  break
3403
3503