mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7373 from jakobandersen/cpp_alternate_ops
C++, alternative spellings of operators
This commit is contained in:
commit
0aedc353d6
1
CHANGES
1
CHANGES
@ -18,6 +18,7 @@ Bugs fixed
|
||||
|
||||
* #7364: autosummary: crashed when :confval:`autosummary_generate` is False
|
||||
* #7370: autosummary: raises UnboundLocalError when unknown module given
|
||||
* #7367: C++, alternate operator spellings are now supported.
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
@ -306,6 +306,7 @@ _operator_re = re.compile(r'''(?x)
|
||||
| ->\*? | \,
|
||||
| (<<|>>)=? | && | \|\|
|
||||
| [!<>=/*%+|&^~-]=?
|
||||
| (\b(and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|xor|xor_eq)\b)
|
||||
''')
|
||||
_fold_operator_re = re.compile(r'''(?x)
|
||||
->\* | \.\* | \,
|
||||
@ -464,37 +465,37 @@ _id_operator_v2 = {
|
||||
# '-(unary)' : 'ng',
|
||||
# '&(unary)' : 'ad',
|
||||
# '*(unary)' : 'de',
|
||||
'~': 'co',
|
||||
'~': 'co', 'compl': 'co',
|
||||
'+': 'pl',
|
||||
'-': 'mi',
|
||||
'*': 'ml',
|
||||
'/': 'dv',
|
||||
'%': 'rm',
|
||||
'&': 'an',
|
||||
'|': 'or',
|
||||
'^': 'eo',
|
||||
'&': 'an', 'bitand': 'an',
|
||||
'|': 'or', 'bitor': 'or',
|
||||
'^': 'eo', 'xor': 'eo',
|
||||
'=': 'aS',
|
||||
'+=': 'pL',
|
||||
'-=': 'mI',
|
||||
'*=': 'mL',
|
||||
'/=': 'dV',
|
||||
'%=': 'rM',
|
||||
'&=': 'aN',
|
||||
'|=': 'oR',
|
||||
'^=': 'eO',
|
||||
'&=': 'aN', 'and_eq': 'aN',
|
||||
'|=': 'oR', 'or_eq': 'oR',
|
||||
'^=': 'eO', 'xor_eq': 'eO',
|
||||
'<<': 'ls',
|
||||
'>>': 'rs',
|
||||
'<<=': 'lS',
|
||||
'>>=': 'rS',
|
||||
'==': 'eq',
|
||||
'!=': 'ne',
|
||||
'!=': 'ne', 'not_eq': 'ne',
|
||||
'<': 'lt',
|
||||
'>': 'gt',
|
||||
'<=': 'le',
|
||||
'>=': 'ge',
|
||||
'!': 'nt',
|
||||
'&&': 'aa',
|
||||
'||': 'oo',
|
||||
'!': 'nt', 'not': 'nt',
|
||||
'&&': 'aa', 'and': 'aa',
|
||||
'||': 'oo', 'or': 'oo',
|
||||
'++': 'pp',
|
||||
'--': 'mm',
|
||||
',': 'cm',
|
||||
@ -511,8 +512,8 @@ _id_operator_unary_v2 = {
|
||||
'&': 'ad',
|
||||
'+': 'ps',
|
||||
'-': 'ng',
|
||||
'!': 'nt',
|
||||
'~': 'co'
|
||||
'!': 'nt', 'not': 'nt',
|
||||
'~': 'co', 'compl': 'co'
|
||||
}
|
||||
_id_char_from_prefix = {
|
||||
None: 'c', 'u8': 'c',
|
||||
@ -520,21 +521,21 @@ _id_char_from_prefix = {
|
||||
} # type: Dict[Any, str]
|
||||
# these are ordered by preceedence
|
||||
_expression_bin_ops = [
|
||||
['||'],
|
||||
['&&'],
|
||||
['|'],
|
||||
['^'],
|
||||
['&'],
|
||||
['==', '!='],
|
||||
['||', 'or'],
|
||||
['&&', 'and'],
|
||||
['|', 'bitor'],
|
||||
['^', 'xor'],
|
||||
['&', 'bitand'],
|
||||
['==', '!=', 'not_eq'],
|
||||
['<=', '>=', '<', '>'],
|
||||
['<<', '>>'],
|
||||
['+', '-'],
|
||||
['*', '/', '%'],
|
||||
['.*', '->*']
|
||||
]
|
||||
_expression_unary_ops = ["++", "--", "*", "&", "+", "-", "!", "~"]
|
||||
_expression_unary_ops = ["++", "--", "*", "&", "+", "-", "!", "not", "~", "compl"]
|
||||
_expression_assignment_ops = ["=", "*=", "/=", "%=", "+=", "-=",
|
||||
">>=", "<<=", "&=", "^=", "|="]
|
||||
">>=", "<<=", "&=", "and_eq", "^=", "|=", "xor_eq", "or_eq"]
|
||||
_id_explicit_cast = {
|
||||
'dynamic_cast': 'dc',
|
||||
'static_cast': 'sc',
|
||||
@ -1260,7 +1261,10 @@ class ASTUnaryOpExpr(ASTExpression):
|
||||
self.expr = expr
|
||||
|
||||
def _stringify(self, transform: StringifyTransform) -> str:
|
||||
return transform(self.op) + transform(self.expr)
|
||||
if self.op[0] in 'cn':
|
||||
return transform(self.op) + " " + transform(self.expr)
|
||||
else:
|
||||
return transform(self.op) + transform(self.expr)
|
||||
|
||||
def get_id(self, version: int) -> str:
|
||||
return _id_operator_unary_v2[self.op] + self.expr.get_id(version)
|
||||
@ -1268,6 +1272,8 @@ class ASTUnaryOpExpr(ASTExpression):
|
||||
def describe_signature(self, signode: TextElement, mode: str,
|
||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||
signode.append(nodes.Text(self.op))
|
||||
if self.op[0] in 'cn':
|
||||
signode.append(nodes.Text(' '))
|
||||
self.expr.describe_signature(signode, mode, env, symbol)
|
||||
|
||||
|
||||
@ -1584,6 +1590,8 @@ class ASTOperatorBuildIn(ASTOperator):
|
||||
def get_id(self, version: int) -> str:
|
||||
if version == 1:
|
||||
ids = _id_operator_v1
|
||||
if self.op not in ids:
|
||||
raise NoOldIdError()
|
||||
else:
|
||||
ids = _id_operator_v2
|
||||
if self.op not in ids:
|
||||
@ -1592,7 +1600,7 @@ class ASTOperatorBuildIn(ASTOperator):
|
||||
return ids[self.op]
|
||||
|
||||
def _stringify(self, transform: StringifyTransform) -> str:
|
||||
if self.op in ('new', 'new[]', 'delete', 'delete[]'):
|
||||
if self.op in ('new', 'new[]', 'delete', 'delete[]') or self.op[0] in "abcnox":
|
||||
return 'operator ' + self.op
|
||||
else:
|
||||
return 'operator' + self.op
|
||||
@ -5016,7 +5024,11 @@ class DefinitionParser(BaseParser):
|
||||
self.skip_ws()
|
||||
for op in _expression_unary_ops:
|
||||
# TODO: hmm, should we be able to backtrack here?
|
||||
if self.skip_string(op):
|
||||
if op[0] in 'cn':
|
||||
res = self.skip_word(op)
|
||||
else:
|
||||
res = self.skip_string(op)
|
||||
if res:
|
||||
expr = self._parse_cast_expression()
|
||||
return ASTUnaryOpExpr(op, expr)
|
||||
if self.skip_word_and_ws('sizeof'):
|
||||
@ -5144,8 +5156,12 @@ class DefinitionParser(BaseParser):
|
||||
pos = self.pos
|
||||
oneMore = False
|
||||
for op in _expression_bin_ops[opId]:
|
||||
if not self.skip_string(op):
|
||||
continue
|
||||
if op[0] in 'abcnox':
|
||||
if not self.skip_word(op):
|
||||
continue
|
||||
else:
|
||||
if not self.skip_string(op):
|
||||
continue
|
||||
if op == '&' and self.current_char == '&':
|
||||
# don't split the && 'token'
|
||||
self.pos -= 1
|
||||
@ -5187,8 +5203,12 @@ class DefinitionParser(BaseParser):
|
||||
oneMore = False
|
||||
self.skip_ws()
|
||||
for op in _expression_assignment_ops:
|
||||
if not self.skip_string(op):
|
||||
continue
|
||||
if op[0] in 'anox':
|
||||
if not self.skip_word(op):
|
||||
continue
|
||||
else:
|
||||
if not self.skip_string(op):
|
||||
continue
|
||||
expr = self._parse_logical_or_expression(False)
|
||||
exprs.append(expr)
|
||||
ops.append(op)
|
||||
|
@ -197,7 +197,9 @@ def test_expressions():
|
||||
exprCheck('+5', 'psL5E')
|
||||
exprCheck('-5', 'ngL5E')
|
||||
exprCheck('!5', 'ntL5E')
|
||||
exprCheck('not 5', 'ntL5E')
|
||||
exprCheck('~5', 'coL5E')
|
||||
exprCheck('compl 5', 'coL5E')
|
||||
exprCheck('sizeof...(a)', 'sZ1a')
|
||||
exprCheck('sizeof(T)', 'st1T')
|
||||
exprCheck('sizeof -42', 'szngL42E')
|
||||
@ -221,13 +223,19 @@ def test_expressions():
|
||||
exprCheck('(int)2', 'cviL2E')
|
||||
# binary op
|
||||
exprCheck('5 || 42', 'ooL5EL42E')
|
||||
exprCheck('5 or 42', 'ooL5EL42E')
|
||||
exprCheck('5 && 42', 'aaL5EL42E')
|
||||
exprCheck('5 and 42', 'aaL5EL42E')
|
||||
exprCheck('5 | 42', 'orL5EL42E')
|
||||
exprCheck('5 bitor 42', 'orL5EL42E')
|
||||
exprCheck('5 ^ 42', 'eoL5EL42E')
|
||||
exprCheck('5 xor 42', 'eoL5EL42E')
|
||||
exprCheck('5 & 42', 'anL5EL42E')
|
||||
exprCheck('5 bitand 42', 'anL5EL42E')
|
||||
# ['==', '!=']
|
||||
exprCheck('5 == 42', 'eqL5EL42E')
|
||||
exprCheck('5 != 42', 'neL5EL42E')
|
||||
exprCheck('5 not_eq 42', 'neL5EL42E')
|
||||
# ['<=', '>=', '<', '>']
|
||||
exprCheck('5 <= 42', 'leL5EL42E')
|
||||
exprCheck('A <= 42', 'le1AL42E')
|
||||
@ -261,8 +269,11 @@ def test_expressions():
|
||||
exprCheck('a >>= 5', 'rS1aL5E')
|
||||
exprCheck('a <<= 5', 'lS1aL5E')
|
||||
exprCheck('a &= 5', 'aN1aL5E')
|
||||
exprCheck('a and_eq 5', 'aN1aL5E')
|
||||
exprCheck('a ^= 5', 'eO1aL5E')
|
||||
exprCheck('a xor_eq 5', 'eO1aL5E')
|
||||
exprCheck('a |= 5', 'oR1aL5E')
|
||||
exprCheck('a or_eq 5', 'oR1aL5E')
|
||||
|
||||
# Additional tests
|
||||
# a < expression that starts with something that could be a template
|
||||
@ -531,30 +542,62 @@ def test_function_definitions():
|
||||
|
||||
|
||||
def test_operators():
|
||||
check('function', 'void operator new [ ] ()',
|
||||
{1: "new-array-operator", 2: "nav"}, output='void operator new[]()')
|
||||
check('function', 'void operator delete ()',
|
||||
{1: "delete-operator", 2: "dlv"}, output='void operator delete()')
|
||||
check('function', 'operator bool() const',
|
||||
{1: "castto-b-operatorC", 2: "NKcvbEv"}, output='operator bool() const')
|
||||
check('function', 'void operator new()', {1: "new-operator", 2: "nwv"})
|
||||
check('function', 'void operator new[]()', {1: "new-array-operator", 2: "nav"})
|
||||
check('function', 'void operator delete()', {1: "delete-operator", 2: "dlv"})
|
||||
check('function', 'void operator delete[]()', {1: "delete-array-operator", 2: "dav"})
|
||||
check('function', 'operator bool() const', {1: "castto-b-operatorC", 2: "NKcvbEv"})
|
||||
check('function', 'void operator""_udl()', {2: 'li4_udlv'})
|
||||
|
||||
check('function', 'void operator * ()',
|
||||
{1: "mul-operator", 2: "mlv"}, output='void operator*()')
|
||||
check('function', 'void operator - ()',
|
||||
{1: "sub-operator", 2: "miv"}, output='void operator-()')
|
||||
check('function', 'void operator + ()',
|
||||
{1: "add-operator", 2: "plv"}, output='void operator+()')
|
||||
check('function', 'void operator = ()',
|
||||
{1: "assign-operator", 2: "aSv"}, output='void operator=()')
|
||||
check('function', 'void operator / ()',
|
||||
{1: "div-operator", 2: "dvv"}, output='void operator/()')
|
||||
check('function', 'void operator % ()',
|
||||
{1: "mod-operator", 2: "rmv"}, output='void operator%()')
|
||||
check('function', 'void operator ! ()',
|
||||
{1: "not-operator", 2: "ntv"}, output='void operator!()')
|
||||
|
||||
check('function', 'void operator "" _udl()',
|
||||
{2: 'li4_udlv'}, output='void operator""_udl()')
|
||||
check('function', 'void operator~()', {1: "inv-operator", 2: "cov"})
|
||||
check('function', 'void operator compl()', {2: "cov"})
|
||||
check('function', 'void operator+()', {1: "add-operator", 2: "plv"})
|
||||
check('function', 'void operator-()', {1: "sub-operator", 2: "miv"})
|
||||
check('function', 'void operator*()', {1: "mul-operator", 2: "mlv"})
|
||||
check('function', 'void operator/()', {1: "div-operator", 2: "dvv"})
|
||||
check('function', 'void operator%()', {1: "mod-operator", 2: "rmv"})
|
||||
check('function', 'void operator&()', {1: "and-operator", 2: "anv"})
|
||||
check('function', 'void operator bitand()', {2: "anv"})
|
||||
check('function', 'void operator|()', {1: "or-operator", 2: "orv"})
|
||||
check('function', 'void operator bitor()', {2: "orv"})
|
||||
check('function', 'void operator^()', {1: "xor-operator", 2: "eov"})
|
||||
check('function', 'void operator xor()', {2: "eov"})
|
||||
check('function', 'void operator=()', {1: "assign-operator", 2: "aSv"})
|
||||
check('function', 'void operator+=()', {1: "add-assign-operator", 2: "pLv"})
|
||||
check('function', 'void operator-=()', {1: "sub-assign-operator", 2: "mIv"})
|
||||
check('function', 'void operator*=()', {1: "mul-assign-operator", 2: "mLv"})
|
||||
check('function', 'void operator/=()', {1: "div-assign-operator", 2: "dVv"})
|
||||
check('function', 'void operator%=()', {1: "mod-assign-operator", 2: "rMv"})
|
||||
check('function', 'void operator&=()', {1: "and-assign-operator", 2: "aNv"})
|
||||
check('function', 'void operator and_eq()', {2: "aNv"})
|
||||
check('function', 'void operator|=()', {1: "or-assign-operator", 2: "oRv"})
|
||||
check('function', 'void operator or_eq()', {2: "oRv"})
|
||||
check('function', 'void operator^=()', {1: "xor-assign-operator", 2: "eOv"})
|
||||
check('function', 'void operator xor_eq()', {2: "eOv"})
|
||||
check('function', 'void operator<<()', {1: "lshift-operator", 2: "lsv"})
|
||||
check('function', 'void operator>>()', {1: "rshift-operator", 2: "rsv"})
|
||||
check('function', 'void operator<<=()', {1: "lshift-assign-operator", 2: "lSv"})
|
||||
check('function', 'void operator>>=()', {1: "rshift-assign-operator", 2: "rSv"})
|
||||
check('function', 'void operator==()', {1: "eq-operator", 2: "eqv"})
|
||||
check('function', 'void operator!=()', {1: "neq-operator", 2: "nev"})
|
||||
check('function', 'void operator not_eq()', {2: "nev"})
|
||||
check('function', 'void operator<()', {1: "lt-operator", 2: "ltv"})
|
||||
check('function', 'void operator>()', {1: "gt-operator", 2: "gtv"})
|
||||
check('function', 'void operator<=()', {1: "lte-operator", 2: "lev"})
|
||||
check('function', 'void operator>=()', {1: "gte-operator", 2: "gev"})
|
||||
check('function', 'void operator!()', {1: "not-operator", 2: "ntv"})
|
||||
check('function', 'void operator not()', {2: "ntv"})
|
||||
check('function', 'void operator&&()', {1: "sand-operator", 2: "aav"})
|
||||
check('function', 'void operator and()', {2: "aav"})
|
||||
check('function', 'void operator||()', {1: "sor-operator", 2: "oov"})
|
||||
check('function', 'void operator or()', {2: "oov"})
|
||||
check('function', 'void operator++()', {1: "inc-operator", 2: "ppv"})
|
||||
check('function', 'void operator--()', {1: "dec-operator", 2: "mmv"})
|
||||
check('function', 'void operator,()', {1: "comma-operator", 2: "cmv"})
|
||||
check('function', 'void operator->*()', {1: "pointer-by-pointer-operator", 2: "pmv"})
|
||||
check('function', 'void operator->()', {1: "pointer-operator", 2: "ptv"})
|
||||
check('function', 'void operator()()', {1: "call-operator", 2: "clv"})
|
||||
check('function', 'void operator[]()', {1: "subscript-operator", 2: "ixv"})
|
||||
|
||||
|
||||
def test_class_definitions():
|
||||
|
Loading…
Reference in New Issue
Block a user