mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C++, simplify assginemnt-expression parsing
This commit is contained in:
parent
ccfe08746a
commit
7dd1e5bbcf
@ -1589,42 +1589,39 @@ class ASTBracedInitList(ASTBase):
|
|||||||
|
|
||||||
|
|
||||||
class ASTAssignmentExpr(ASTExpression):
|
class ASTAssignmentExpr(ASTExpression):
|
||||||
def __init__(self, exprs: List[Union[ASTExpression, ASTBracedInitList]], ops: List[str]):
|
def __init__(self, leftExpr: ASTExpression, op: str,
|
||||||
assert len(exprs) > 0
|
rightExpr: Union[ASTExpression, ASTBracedInitList]):
|
||||||
assert len(exprs) == len(ops) + 1
|
self.leftExpr = leftExpr
|
||||||
self.exprs = exprs
|
self.op = op
|
||||||
self.ops = ops
|
self.rightExpr = rightExpr
|
||||||
|
|
||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
res = []
|
res = []
|
||||||
res.append(transform(self.exprs[0]))
|
res.append(transform(self.leftExpr))
|
||||||
for i in range(1, len(self.exprs)):
|
res.append(' ')
|
||||||
res.append(' ')
|
res.append(self.op)
|
||||||
res.append(self.ops[i - 1])
|
res.append(' ')
|
||||||
res.append(' ')
|
res.append(transform(self.rightExpr))
|
||||||
res.append(transform(self.exprs[i]))
|
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
def get_id(self, version: int) -> str:
|
def get_id(self, version: int) -> str:
|
||||||
|
# we end up generating the ID from left to right, instead of right to left
|
||||||
res = []
|
res = []
|
||||||
for i in range(len(self.ops)):
|
res.append(_id_operator_v2[self.op])
|
||||||
res.append(_id_operator_v2[self.ops[i]])
|
res.append(self.leftExpr.get_id(version))
|
||||||
res.append(self.exprs[i].get_id(version))
|
res.append(self.rightExpr.get_id(version))
|
||||||
res.append(self.exprs[-1].get_id(version))
|
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
def describe_signature(self, signode: TextElement, mode: str,
|
def describe_signature(self, signode: TextElement, mode: str,
|
||||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||||
self.exprs[0].describe_signature(signode, mode, env, symbol)
|
self.leftExpr.describe_signature(signode, mode, env, symbol)
|
||||||
for i in range(1, len(self.exprs)):
|
signode += addnodes.desc_sig_space()
|
||||||
signode += addnodes.desc_sig_space()
|
if ord(self.op[0]) >= ord('a') and ord(self.op[0]) <= ord('z'):
|
||||||
op = self.ops[i - 1]
|
signode += addnodes.desc_sig_keyword(self.op, self.op)
|
||||||
if ord(op[0]) >= ord('a') and ord(op[0]) <= ord('z'):
|
else:
|
||||||
signode += addnodes.desc_sig_keyword(op, op)
|
signode += addnodes.desc_sig_operator(self.op, self.op)
|
||||||
else:
|
signode += addnodes.desc_sig_space()
|
||||||
signode += addnodes.desc_sig_operator(op, op)
|
self.rightExpr.describe_signature(signode, mode, env, symbol)
|
||||||
signode += addnodes.desc_sig_space()
|
|
||||||
self.exprs[i].describe_signature(signode, mode, env, symbol)
|
|
||||||
|
|
||||||
|
|
||||||
class ASTCommaExpr(ASTExpression):
|
class ASTCommaExpr(ASTExpression):
|
||||||
@ -5654,64 +5651,58 @@ class DefinitionParser(BaseParser):
|
|||||||
|
|
||||||
def _parse_conditional_expression_tail(self, orExprHead: ASTExpression,
|
def _parse_conditional_expression_tail(self, orExprHead: ASTExpression,
|
||||||
inTemplate: bool) -> Optional[ASTConditionalExpr]:
|
inTemplate: bool) -> Optional[ASTConditionalExpr]:
|
||||||
|
# Consumes the orExprHead on success.
|
||||||
|
|
||||||
# -> "?" expression ":" assignment-expression
|
# -> "?" expression ":" assignment-expression
|
||||||
|
self.skip_ws()
|
||||||
if not self.skip_string("?"):
|
if not self.skip_string("?"):
|
||||||
return None
|
return None
|
||||||
then_expr = self._parse_expression()
|
thenExpr = self._parse_expression()
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if not self.skip_string(":"):
|
if not self.skip_string(":"):
|
||||||
self.fail('Expected ":" after "?"')
|
self.fail('Expected ":" after then-expression in conditional expression.')
|
||||||
else_expr = self._parse_assignment_expression(inTemplate)
|
elseExpr = self._parse_assignment_expression(inTemplate)
|
||||||
return ASTConditionalExpr(orExprHead, then_expr, else_expr)
|
return ASTConditionalExpr(orExprHead, thenExpr, elseExpr)
|
||||||
|
|
||||||
def _parse_assignment_expression(self, inTemplate: bool) -> ASTExpression:
|
def _parse_assignment_expression(self, inTemplate: bool) -> ASTExpression:
|
||||||
# -> conditional-expression
|
# -> conditional-expression
|
||||||
# | logical-or-expression assignment-operator initializer-clause
|
# | logical-or-expression assignment-operator initializer-clause
|
||||||
# | throw-expression
|
# | yield-expression -> "co_yield" assignment-expression
|
||||||
# TODO: parse throw-expression: "throw" assignment-expression [opt]
|
# | "co_yield" braced-init-list
|
||||||
# if not a throw expression, then:
|
# | throw-expression -> "throw" assignment-expression[opt]
|
||||||
# -> conditional-expression ->
|
# TODO: yield-expression
|
||||||
|
# TODO: throw-expression
|
||||||
|
|
||||||
|
# Now we have (after expanding conditional-expression:
|
||||||
# logical-or-expression
|
# logical-or-expression
|
||||||
# | logical-or-expression "?" expression ":" assignment-expression
|
# | logical-or-expression "?" expression ":" assignment-expression
|
||||||
# | logical-or-expression assignment-operator initializer-clause
|
# | logical-or-expression assignment-operator initializer-clause
|
||||||
exprs: List[Union[ASTExpression, ASTBracedInitList]] = []
|
leftExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
|
||||||
ops = []
|
# the ternary operator
|
||||||
orExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
|
condExpr = self._parse_conditional_expression_tail(leftExpr, inTemplate)
|
||||||
exprs.append(orExpr)
|
if condExpr is not None:
|
||||||
while True:
|
return condExpr
|
||||||
oneMore = False
|
# and actual assignment
|
||||||
self.skip_ws()
|
for op in _expression_assignment_ops:
|
||||||
prev_expr = exprs[-1]
|
if op[0] in 'anox':
|
||||||
if isinstance(prev_expr, ASTExpression):
|
if not self.skip_word(op):
|
||||||
cond_expr = self._parse_conditional_expression_tail(prev_expr, inTemplate)
|
continue
|
||||||
if cond_expr is not None:
|
else:
|
||||||
exprs[-1] = cond_expr
|
if not self.skip_string(op):
|
||||||
continue
|
continue
|
||||||
for op in _expression_assignment_ops:
|
rightExpr = self._parse_initializer_clause()
|
||||||
if op[0] in 'anox':
|
return ASTAssignmentExpr(leftExpr, op, rightExpr)
|
||||||
if not self.skip_word(op):
|
# just a logical-or-expression
|
||||||
continue
|
return leftExpr
|
||||||
else:
|
|
||||||
if not self.skip_string(op):
|
|
||||||
continue
|
|
||||||
expr = self._parse_initializer_clause()
|
|
||||||
exprs.append(expr)
|
|
||||||
ops.append(op)
|
|
||||||
oneMore = True
|
|
||||||
if not oneMore:
|
|
||||||
break
|
|
||||||
if len(ops) == 0:
|
|
||||||
return cast(ASTExpression, exprs[-1])
|
|
||||||
else:
|
|
||||||
return ASTAssignmentExpr(exprs, ops)
|
|
||||||
|
|
||||||
def _parse_constant_expression(self, inTemplate: bool) -> ASTExpression:
|
def _parse_constant_expression(self, inTemplate: bool) -> ASTExpression:
|
||||||
# -> conditional-expression
|
# -> conditional-expression ->
|
||||||
|
# logical-or-expression
|
||||||
|
# | logical-or-expression "?" expression ":" assignment-expression
|
||||||
orExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
|
orExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
|
||||||
self.skip_ws()
|
condExpr = self._parse_conditional_expression_tail(orExpr, inTemplate)
|
||||||
cond_expr = self._parse_conditional_expression_tail(orExpr, inTemplate)
|
if condExpr is not None:
|
||||||
if cond_expr is not None:
|
return condExpr
|
||||||
return cond_expr
|
|
||||||
return orExpr
|
return orExpr
|
||||||
|
|
||||||
def _parse_expression(self) -> ASTExpression:
|
def _parse_expression(self) -> ASTExpression:
|
||||||
|
@ -327,7 +327,6 @@ def test_domain_cpp_ast_expressions():
|
|||||||
exprCheck('5 ->* 42', 'pmL5EL42E')
|
exprCheck('5 ->* 42', 'pmL5EL42E')
|
||||||
# conditional
|
# conditional
|
||||||
exprCheck('5 ? 7 : 3', 'quL5EL7EL3E')
|
exprCheck('5 ? 7 : 3', 'quL5EL7EL3E')
|
||||||
exprCheck('5 = 6 ? 7 = 8 : 3', 'aSL5EquL6EaSL7EL8EL3E')
|
|
||||||
# assignment
|
# assignment
|
||||||
exprCheck('a = 5', 'aS1aL5E')
|
exprCheck('a = 5', 'aS1aL5E')
|
||||||
exprCheck('a *= 5', 'mL1aL5E')
|
exprCheck('a *= 5', 'mL1aL5E')
|
||||||
@ -344,6 +343,9 @@ def test_domain_cpp_ast_expressions():
|
|||||||
exprCheck('a |= 5', 'oR1aL5E')
|
exprCheck('a |= 5', 'oR1aL5E')
|
||||||
exprCheck('a or_eq 5', 'oR1aL5E')
|
exprCheck('a or_eq 5', 'oR1aL5E')
|
||||||
exprCheck('a = {{1, 2, 3}}', 'aS1ailL1EL2EL3EE')
|
exprCheck('a = {{1, 2, 3}}', 'aS1ailL1EL2EL3EE')
|
||||||
|
# complex assignment and conditional
|
||||||
|
exprCheck('5 = 6 = 7', 'aSL5EaSL6EL7E')
|
||||||
|
exprCheck('5 = 6 ? 7 = 8 : 3', 'aSL5EquL6EaSL7EL8EL3E')
|
||||||
# comma operator
|
# comma operator
|
||||||
exprCheck('a, 5', 'cm1aL5E')
|
exprCheck('a, 5', 'cm1aL5E')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user