From c6f1bf66e0adbe003a21b7d3fc480fbc184bf204 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Tue, 24 Mar 2020 18:38:42 +0100 Subject: [PATCH] C, alternative spellings of operators --- CHANGES | 1 + sphinx/domains/c.py | 45 +++++++++++++++++++++++++++++------------- tests/test_domain_c.py | 11 +++++++++++ 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 2b6a8f47b..a75d24e2e 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,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. +* C, alternate operator spellings are now supported. Testing -------- diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index 8f071a9aa..3f98b7261 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -53,21 +53,21 @@ _keywords = [ # 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"] _max_id = 1 _id_prefix = [None, 'c.', 'Cv2.'] @@ -423,11 +423,16 @@ 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 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) @@ -2241,7 +2246,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'): @@ -2313,8 +2322,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 @@ -2353,8 +2366,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 'abcnox': + if not self.skip_word(op): + continue + else: + if not self.skip_string(op): + continue expr = self._parse_logical_or_expression() exprs.append(expr) ops.append(op) diff --git a/tests/test_domain_c.py b/tests/test_domain_c.py index 6d4ba9cea..9daed2800 100644 --- a/tests/test_domain_c.py +++ b/tests/test_domain_c.py @@ -172,7 +172,9 @@ def test_expressions(): exprCheck('+5') exprCheck('-5') exprCheck('!5') + exprCheck('not 5') exprCheck('~5') + exprCheck('compl 5') exprCheck('sizeof(T)') exprCheck('sizeof -42') exprCheck('alignof(T)') @@ -180,13 +182,19 @@ def test_expressions(): exprCheck('(int)2') # binary op exprCheck('5 || 42') + exprCheck('5 or 42') exprCheck('5 && 42') + exprCheck('5 and 42') exprCheck('5 | 42') + exprCheck('5 bitor 42') exprCheck('5 ^ 42') + exprCheck('5 xor 42') exprCheck('5 & 42') + exprCheck('5 bitand 42') # ['==', '!='] exprCheck('5 == 42') exprCheck('5 != 42') + exprCheck('5 not_eq 42') # ['<=', '>=', '<', '>'] exprCheck('5 <= 42') exprCheck('5 >= 42') @@ -215,8 +223,11 @@ def test_expressions(): exprCheck('a >>= 5') exprCheck('a <<= 5') exprCheck('a &= 5') + exprCheck('a and_eq 5') exprCheck('a ^= 5') + exprCheck('a xor_eq 5') exprCheck('a |= 5') + exprCheck('a or_eq 5') def test_type_definitions():