IncludeCPP 3.8.3__py3-none-any.whl → 3.8.5__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.
@@ -114,7 +114,7 @@ class TokenType(Enum):
114
114
 
115
115
  KEYWORDS = {
116
116
  # Service structure
117
- 'service-init', 'service-run', 'service-include', 'struct', 'define', 'main', 'class', 'new', 'this',
117
+ 'service-init', 'service-run', 'service-include', 'struct', 'define', 'main', 'class', 'constr', 'extends', 'overwrites', 'new', 'this', 'super',
118
118
  # Control flow
119
119
  'if', 'else', 'elif', 'while', 'for', 'foreach', 'in', 'range',
120
120
  'switch', 'case', 'default', 'break', 'continue', 'return',
@@ -1045,7 +1045,7 @@ class CSSLParser:
1045
1045
 
1046
1046
  # Check for * prefix (non-nullable indicator)
1047
1047
  non_null = False
1048
- if self._match(TokenType.ASTERISK):
1048
+ if self._match(TokenType.MULTIPLY):
1049
1049
  non_null = True
1050
1050
 
1051
1051
  # Get variable name
@@ -1378,12 +1378,73 @@ class CSSLParser:
1378
1378
  """
1379
1379
  # Check for * prefix (non-null class - all methods return non-null)
1380
1380
  non_null = False
1381
- if self._match(TokenType.ASTERISK):
1381
+ if self._match(TokenType.MULTIPLY):
1382
1382
  non_null = True
1383
1383
 
1384
1384
  class_name = self._advance().value
1385
1385
 
1386
- node = ASTNode('class', value={'name': class_name, 'non_null': non_null}, children=[])
1386
+ # Check for class-level constructor parameters: class MyClass (int x, string y) { ... }
1387
+ class_params = []
1388
+ if self._match(TokenType.PAREN_START):
1389
+ class_params = self._parse_parameter_list()
1390
+ self._expect(TokenType.PAREN_END)
1391
+
1392
+ # Check for inheritance and overwrites:
1393
+ # class Child : extends Parent { ... }
1394
+ # class Child : extends $PythonObject { ... }
1395
+ # class Child : extends Parent : overwrites Parent { ... }
1396
+ # class Child : extends Parent (param1, param2) { ... } <- constructor args for parent
1397
+ extends_class = None
1398
+ extends_is_python = False
1399
+ extends_args = []
1400
+ overwrites_class = None
1401
+ overwrites_is_python = False
1402
+
1403
+ if self._match(TokenType.COLON):
1404
+ # Parse extends and/or overwrites (can be chained)
1405
+ while True:
1406
+ if self._match_keyword('extends'):
1407
+ if self._check(TokenType.IDENTIFIER):
1408
+ extends_class = self._advance().value
1409
+ elif self._check(TokenType.SHARED_REF):
1410
+ extends_class = self._advance().value
1411
+ extends_is_python = True
1412
+ else:
1413
+ raise CSSLSyntaxError("Expected parent class name after 'extends'")
1414
+ # Check for constructor arguments: extends Parent (arg1, arg2)
1415
+ if self._match(TokenType.PAREN_START):
1416
+ while not self._check(TokenType.PAREN_END):
1417
+ arg = self._parse_expression()
1418
+ extends_args.append(arg)
1419
+ self._match(TokenType.COMMA)
1420
+ self._expect(TokenType.PAREN_END)
1421
+ elif self._match_keyword('overwrites'):
1422
+ if self._check(TokenType.IDENTIFIER):
1423
+ overwrites_class = self._advance().value
1424
+ elif self._check(TokenType.SHARED_REF):
1425
+ overwrites_class = self._advance().value
1426
+ overwrites_is_python = True
1427
+ else:
1428
+ raise CSSLSyntaxError("Expected class name after 'overwrites'")
1429
+ # Skip optional () after class name
1430
+ if self._match(TokenType.PAREN_START):
1431
+ self._expect(TokenType.PAREN_END)
1432
+ else:
1433
+ raise CSSLSyntaxError("Expected 'extends' or 'overwrites' after ':' in class declaration")
1434
+ # Check for another : for chaining
1435
+ if not self._match(TokenType.COLON):
1436
+ break
1437
+
1438
+ node = ASTNode('class', value={
1439
+ 'name': class_name,
1440
+ 'non_null': non_null,
1441
+ 'class_params': class_params,
1442
+ 'extends': extends_class,
1443
+ 'extends_is_python': extends_is_python,
1444
+ 'extends_args': extends_args,
1445
+ 'overwrites': overwrites_class,
1446
+ 'overwrites_is_python': overwrites_is_python
1447
+ }, children=[])
1387
1448
  self._expect(TokenType.BLOCK_START)
1388
1449
 
1389
1450
  while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
@@ -1412,25 +1473,217 @@ class CSSLParser:
1412
1473
  method = self._parse_define()
1413
1474
  node.children.append(method)
1414
1475
 
1476
+ # Check for constr keyword (constructor declaration)
1477
+ # Syntax: constr ConstructorName() { ... }
1478
+ # or: constr ConstructorName() : extends Parent::ConstructorName { ... }
1479
+ elif self._match_keyword('constr'):
1480
+ constructor = self._parse_constructor(class_name)
1481
+ node.children.append(constructor)
1482
+
1415
1483
  else:
1416
1484
  self._advance()
1417
1485
 
1418
1486
  self._expect(TokenType.BLOCK_END)
1419
1487
  return node
1420
1488
 
1489
+ def _parse_constructor(self, class_name: str) -> ASTNode:
1490
+ """Parse constructor declaration inside a class.
1491
+
1492
+ Syntax:
1493
+ constr ConstructorName() { ... }
1494
+ constr ConstructorName() : extends ParentClass::ConstructorName { ... }
1495
+ constr ConstructorName() : extends ParentClass::ConstructorName : overwrites ParentClass::ConstructorName { ... }
1496
+
1497
+ Multiple constructors are allowed and executed in order.
1498
+ Constructors can access parent constructor via super().
1499
+ """
1500
+ # Get constructor name
1501
+ if not self._check(TokenType.IDENTIFIER):
1502
+ raise CSSLSyntaxError("Expected constructor name after 'constr'")
1503
+ constr_name = self._advance().value
1504
+
1505
+ # Parse method-level extends/overwrites with :: syntax
1506
+ # constr Name() :: extends Parent::Name :: overwrites Parent::Name { ... }
1507
+ extends_target = None
1508
+ extends_class_ref = None
1509
+ extends_method_ref = None
1510
+ overwrites_target = None
1511
+ overwrites_class_ref = None
1512
+ overwrites_method_ref = None
1513
+
1514
+ # Parse parameters
1515
+ params = []
1516
+ if self._match(TokenType.PAREN_START):
1517
+ params = self._parse_parameter_list()
1518
+ self._expect(TokenType.PAREN_END)
1519
+
1520
+ # Check for method-level extends/overwrites with :: or :
1521
+ if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON):
1522
+ while True:
1523
+ if self._match_keyword('extends'):
1524
+ # Parse Parent::method or just method
1525
+ extends_target = self._parse_qualified_method_ref()
1526
+ if '::' in extends_target:
1527
+ parts = extends_target.split('::')
1528
+ extends_class_ref = parts[0]
1529
+ extends_method_ref = parts[1]
1530
+ else:
1531
+ extends_method_ref = extends_target
1532
+ elif self._match_keyword('overwrites'):
1533
+ # Parse Parent::method or just method
1534
+ overwrites_target = self._parse_qualified_method_ref()
1535
+ if '::' in overwrites_target:
1536
+ parts = overwrites_target.split('::')
1537
+ overwrites_class_ref = parts[0]
1538
+ overwrites_method_ref = parts[1]
1539
+ else:
1540
+ overwrites_method_ref = overwrites_target
1541
+ else:
1542
+ break
1543
+ # Check for another :: or : for chaining
1544
+ if not (self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON)):
1545
+ break
1546
+
1547
+ # Parse constructor body
1548
+ self._expect(TokenType.BLOCK_START)
1549
+ body = []
1550
+ while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
1551
+ stmt = self._parse_statement()
1552
+ if stmt:
1553
+ body.append(stmt)
1554
+ self._expect(TokenType.BLOCK_END)
1555
+
1556
+ return ASTNode('constructor', value={
1557
+ 'name': constr_name,
1558
+ 'class_name': class_name,
1559
+ 'params': params,
1560
+ 'is_constructor': True,
1561
+ 'extends_target': extends_target,
1562
+ 'extends_class': extends_class_ref,
1563
+ 'extends_method': extends_method_ref,
1564
+ 'overwrites_target': overwrites_target,
1565
+ 'overwrites_class': overwrites_class_ref,
1566
+ 'overwrites_method': overwrites_method_ref
1567
+ }, children=body)
1568
+
1569
+ def _parse_qualified_method_ref(self) -> str:
1570
+ """Parse a qualified method reference like 'ParentClass::methodName' or just 'methodName'.
1571
+
1572
+ Returns the qualified name as a string (e.g., 'Parent::init' or just 'init').
1573
+ """
1574
+ # Check for $PythonObject
1575
+ if self._check(TokenType.SHARED_REF):
1576
+ class_ref = self._advance().value # Gets the name without $
1577
+ class_ref = f'${class_ref}'
1578
+ elif self._check(TokenType.IDENTIFIER):
1579
+ class_ref = self._advance().value
1580
+ else:
1581
+ raise CSSLSyntaxError("Expected class or method name in extends/overwrites")
1582
+
1583
+ # Check for :: to get method part
1584
+ if self._match(TokenType.DOUBLE_COLON):
1585
+ if self._check(TokenType.IDENTIFIER):
1586
+ method_ref = self._advance().value
1587
+ return f'{class_ref}::{method_ref}'
1588
+ else:
1589
+ raise CSSLSyntaxError("Expected method name after '::'")
1590
+
1591
+ # Just method name, no class qualifier
1592
+ return class_ref
1593
+
1421
1594
  def _parse_define(self) -> ASTNode:
1422
1595
  """Parse define function declaration.
1423
1596
 
1424
1597
  Syntax:
1425
1598
  define MyFunc(args) { }
1426
1599
  define *MyFunc(args) { } // Non-null: must never return None
1600
+ define MyFunc : extends OtherFunc() { } // Inherit local vars
1601
+ define MyFunc : overwrites OtherFunc() { } // Replace OtherFunc
1602
+ define MyFunc :: extends Parent::Method :: overwrites Parent::Method() { } // Method-level inheritance
1427
1603
  """
1428
1604
  # Check for * prefix (non-null function - must return non-null)
1429
1605
  non_null = False
1430
- if self._match(TokenType.ASTERISK):
1606
+ if self._match(TokenType.MULTIPLY):
1431
1607
  non_null = True
1432
1608
 
1433
1609
  name = self._advance().value
1610
+
1611
+ # Check for extends/overwrites: define func : extends/overwrites target() { }
1612
+ # Also supports method-level :: syntax: define func :: extends Parent::method
1613
+ extends_func = None
1614
+ overwrites_func = None
1615
+ extends_is_python = False
1616
+ overwrites_is_python = False
1617
+ extends_class_ref = None
1618
+ extends_method_ref = None
1619
+ overwrites_class_ref = None
1620
+ overwrites_method_ref = None
1621
+
1622
+ if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON):
1623
+ # Parse extends and/or overwrites (supports :: method-level syntax)
1624
+ while True:
1625
+ if self._match_keyword('extends'):
1626
+ # Check for qualified reference: Parent::method
1627
+ if self._check(TokenType.SHARED_REF):
1628
+ extends_is_python = True
1629
+ extends_func = self._advance().value
1630
+ # Check for ::method
1631
+ if self._match(TokenType.DOUBLE_COLON):
1632
+ extends_class_ref = f'${extends_func}'
1633
+ if self._check(TokenType.IDENTIFIER):
1634
+ extends_method_ref = self._advance().value
1635
+ else:
1636
+ raise CSSLSyntaxError("Expected method name after '::'")
1637
+ elif self._check(TokenType.IDENTIFIER):
1638
+ first_part = self._advance().value
1639
+ # Check for ::method (qualified reference)
1640
+ if self._match(TokenType.DOUBLE_COLON):
1641
+ extends_class_ref = first_part
1642
+ if self._check(TokenType.IDENTIFIER):
1643
+ extends_method_ref = self._advance().value
1644
+ else:
1645
+ raise CSSLSyntaxError("Expected method name after '::'")
1646
+ else:
1647
+ extends_func = first_part
1648
+ else:
1649
+ raise CSSLSyntaxError("Expected function name after 'extends'")
1650
+ # Skip optional () after function/method name
1651
+ if self._match(TokenType.PAREN_START):
1652
+ self._expect(TokenType.PAREN_END)
1653
+ elif self._match_keyword('overwrites'):
1654
+ # Check for qualified reference: Parent::method
1655
+ if self._check(TokenType.SHARED_REF):
1656
+ overwrites_is_python = True
1657
+ overwrites_func = self._advance().value
1658
+ # Check for ::method
1659
+ if self._match(TokenType.DOUBLE_COLON):
1660
+ overwrites_class_ref = f'${overwrites_func}'
1661
+ if self._check(TokenType.IDENTIFIER):
1662
+ overwrites_method_ref = self._advance().value
1663
+ else:
1664
+ raise CSSLSyntaxError("Expected method name after '::'")
1665
+ elif self._check(TokenType.IDENTIFIER):
1666
+ first_part = self._advance().value
1667
+ # Check for ::method (qualified reference)
1668
+ if self._match(TokenType.DOUBLE_COLON):
1669
+ overwrites_class_ref = first_part
1670
+ if self._check(TokenType.IDENTIFIER):
1671
+ overwrites_method_ref = self._advance().value
1672
+ else:
1673
+ raise CSSLSyntaxError("Expected method name after '::'")
1674
+ else:
1675
+ overwrites_func = first_part
1676
+ else:
1677
+ raise CSSLSyntaxError("Expected function name after 'overwrites'")
1678
+ # Skip optional () after function/method name
1679
+ if self._match(TokenType.PAREN_START):
1680
+ self._expect(TokenType.PAREN_END)
1681
+ else:
1682
+ break
1683
+ # Check for another :: or : for chaining extends/overwrites
1684
+ if not (self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON)):
1685
+ break
1686
+
1434
1687
  params = []
1435
1688
 
1436
1689
  if self._match(TokenType.PAREN_START):
@@ -1446,7 +1699,7 @@ class CSSLParser:
1446
1699
  if self._match(TokenType.AMPERSAND):
1447
1700
  param_info['ref'] = True
1448
1701
  # Handle * prefix for non-null parameters
1449
- if self._match(TokenType.ASTERISK):
1702
+ if self._match(TokenType.MULTIPLY):
1450
1703
  param_info['non_null'] = True
1451
1704
  # Get parameter name
1452
1705
  if self._check(TokenType.IDENTIFIER):
@@ -1468,7 +1721,20 @@ class CSSLParser:
1468
1721
  break
1469
1722
  self._expect(TokenType.PAREN_END)
1470
1723
 
1471
- node = ASTNode('function', value={'name': name, 'params': params, 'non_null': non_null}, children=[])
1724
+ node = ASTNode('function', value={
1725
+ 'name': name,
1726
+ 'params': params,
1727
+ 'non_null': non_null,
1728
+ 'extends': extends_func,
1729
+ 'extends_is_python': extends_is_python,
1730
+ 'overwrites': overwrites_func,
1731
+ 'overwrites_is_python': overwrites_is_python,
1732
+ # Method-level inheritance (Parent::method syntax)
1733
+ 'extends_class': extends_class_ref,
1734
+ 'extends_method': extends_method_ref,
1735
+ 'overwrites_class': overwrites_class_ref,
1736
+ 'overwrites_method': overwrites_method_ref
1737
+ }, children=[])
1472
1738
  self._expect(TokenType.BLOCK_START)
1473
1739
 
1474
1740
  while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
@@ -1514,6 +1780,10 @@ class CSSLParser:
1514
1780
  elif self._check(TokenType.SUPER_FUNC):
1515
1781
  # Super-function for .cssl-pl payload files
1516
1782
  return self._parse_super_function()
1783
+ elif (self._check(TokenType.KEYWORD) and self._current().value == 'super' and
1784
+ self._peek(1).type == TokenType.PAREN_START):
1785
+ # super() call - calls parent constructor/method
1786
+ return self._parse_super_call()
1517
1787
  elif (self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or
1518
1788
  self._check(TokenType.CAPTURED_REF) or self._check(TokenType.SHARED_REF) or
1519
1789
  self._check(TokenType.GLOBAL_REF) or self._check(TokenType.SELF_REF) or
@@ -1524,6 +1794,43 @@ class CSSLParser:
1524
1794
  self._advance()
1525
1795
  return None
1526
1796
 
1797
+ def _parse_super_call(self) -> ASTNode:
1798
+ """Parse super() call to invoke parent constructor or method.
1799
+
1800
+ Syntax:
1801
+ super() - Call parent constructor with no args
1802
+ super(arg1, arg2) - Call parent constructor with args
1803
+ super::method() - Call specific parent method
1804
+ super::method(args) - Call specific parent method with args
1805
+
1806
+ Used inside constructors (constr) and methods to call parent implementations.
1807
+ """
1808
+ # Consume 'super' keyword
1809
+ self._advance()
1810
+
1811
+ # Check for ::method syntax
1812
+ target_method = None
1813
+ if self._match(TokenType.DOUBLE_COLON):
1814
+ if not self._check(TokenType.IDENTIFIER):
1815
+ raise CSSLSyntaxError("Expected method name after 'super::'")
1816
+ target_method = self._advance().value
1817
+
1818
+ # Parse arguments
1819
+ args = []
1820
+ self._expect(TokenType.PAREN_START)
1821
+ while not self._check(TokenType.PAREN_END):
1822
+ arg = self._parse_expression()
1823
+ args.append(arg)
1824
+ if not self._match(TokenType.COMMA):
1825
+ break
1826
+ self._expect(TokenType.PAREN_END)
1827
+ self._match(TokenType.SEMICOLON)
1828
+
1829
+ return ASTNode('super_call', value={
1830
+ 'method': target_method, # None for constructor, method name for specific method
1831
+ 'args': args
1832
+ })
1833
+
1527
1834
  def _parse_if(self) -> ASTNode:
1528
1835
  """Parse if statement with support for else if AND elif syntax."""
1529
1836
  self._expect(TokenType.PAREN_START)