summaryrefslogtreecommitdiff
path: root/sphinx/domains/cpp.py
diff options
context:
space:
mode:
authorJeremy Maitin-Shepard <jbms@google.com>2022-03-17 18:13:47 -0700
committerJakob Lykke Andersen <Jakob@caput.dk>2022-04-17 14:22:24 +0200
commit2d2e0ac01a6594389eef267d04f53f1645f27bad (patch)
tree4b9329666de9c7e8264558877493225155c3ecb7 /sphinx/domains/cpp.py
parent128f0ccc775ff392781e84ba9308599b16c7b523 (diff)
downloadsphinx-git-2d2e0ac01a6594389eef267d04f53f1645f27bad.tar.gz
[C++] Support conditional operator "?"
Diffstat (limited to 'sphinx/domains/cpp.py')
-rw-r--r--sphinx/domains/cpp.py67
1 files changed, 61 insertions, 6 deletions
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index 64985a37f..9248a35e0 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -529,7 +529,8 @@ _id_operator_v2 = {
'->': 'pt',
'()': 'cl',
'[]': 'ix',
- '.*': 'ds' # this one is not overloadable, but we need it for expressions
+ '.*': 'ds', # this one is not overloadable, but we need it for expressions
+ '?': 'cn',
}
_id_operator_unary_v2 = {
'++': 'pp_',
@@ -1518,6 +1519,44 @@ class ASTBinOpExpr(ASTExpression):
self.exprs[i].describe_signature(signode, mode, env, symbol)
+class ASTConditionalExpr(ASTExpression):
+ def __init__(self, if_expr: ASTExpression, then_expr: ASTExpression,
+ else_expr: ASTExpression):
+ self.if_expr = if_expr
+ self.then_expr = then_expr
+ self.else_expr = else_expr
+
+ def _stringify(self, transform: StringifyTransform) -> str:
+ res = []
+ res.append(transform(self.if_expr))
+ res.append(' ? ')
+ res.append(transform(self.then_expr))
+ res.append(' : ')
+ res.append(transform(self.else_expr))
+ return ''.join(res)
+
+ def get_id(self, version: int) -> str:
+ assert version >= 2
+ res = []
+ res.append(_id_operator_v2['?'])
+ res.append(self.if_expr.get_id(version))
+ res.append(self.then_expr.get_id(version))
+ res.append(self.else_expr.get_id(version))
+ return ''.join(res)
+
+ def describe_signature(self, signode: TextElement, mode: str,
+ env: "BuildEnvironment", symbol: "Symbol") -> None:
+ self.if_expr.describe_signature(signode, mode, env, symbol)
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_operator('?', '?')
+ signode += addnodes.desc_sig_space()
+ self.then_expr.describe_signature(signode, mode, env, symbol)
+ signode += addnodes.desc_sig_space()
+ signode += addnodes.desc_sig_operator(':', ':')
+ signode += addnodes.desc_sig_space()
+ self.else_expr.describe_signature(signode, mode, env, symbol)
+
+
class ASTBracedInitList(ASTBase):
def __init__(self, exprs: List[Union[ASTExpression, "ASTBracedInitList"]],
trailingComma: bool) -> None:
@@ -5613,9 +5652,17 @@ class DefinitionParser(BaseParser):
return ASTBinOpExpr(exprs, ops)
return _parse_bin_op_expr(self, 0, inTemplate=inTemplate)
- def _parse_conditional_expression_tail(self, orExprHead: Any) -> None:
+ def _parse_conditional_expression_tail(self, orExprHead: ASTExpression,
+ inTemplate: bool) -> Optional[ASTConditionalExpr]:
# -> "?" expression ":" assignment-expression
- return None
+ if not self.skip_string("?"):
+ return None
+ then_expr = self._parse_expression()
+ self.skip_ws()
+ if not self.skip_string(":"):
+ self.fail('Expected ":" after "?"')
+ else_expr = self._parse_assignment_expression(inTemplate)
+ return ASTConditionalExpr(orExprHead, then_expr, else_expr)
def _parse_assignment_expression(self, inTemplate: bool) -> ASTExpression:
# -> conditional-expression
@@ -5631,10 +5678,15 @@ class DefinitionParser(BaseParser):
ops = []
orExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
exprs.append(orExpr)
- # TODO: handle ternary with _parse_conditional_expression_tail
while True:
oneMore = False
self.skip_ws()
+ prev_expr = exprs[-1]
+ if isinstance(prev_expr, ASTExpression):
+ cond_expr = self._parse_conditional_expression_tail(prev_expr, inTemplate)
+ if cond_expr is not None:
+ exprs[-1] = cond_expr
+ continue
for op in _expression_assignment_ops:
if op[0] in 'anox':
if not self.skip_word(op):
@@ -5649,14 +5701,17 @@ class DefinitionParser(BaseParser):
if not oneMore:
break
if len(ops) == 0:
- return orExpr
+ return cast(ASTExpression, exprs[-1])
else:
return ASTAssignmentExpr(exprs, ops)
def _parse_constant_expression(self, inTemplate: bool) -> ASTExpression:
# -> conditional-expression
orExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
- # TODO: use _parse_conditional_expression_tail
+ self.skip_ws()
+ cond_expr = self._parse_conditional_expression_tail(orExpr, inTemplate)
+ if cond_expr is not None:
+ return cond_expr
return orExpr
def _parse_expression(self) -> ASTExpression: