Skip to content

Commit 0bdfa29

Browse files
committed
Improve requires clause parsing
1 parent 23cf0ac commit 0bdfa29

File tree

1 file changed

+33
-27
lines changed

1 file changed

+33
-27
lines changed

cxxheaderparser/parser.py

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -803,13 +803,6 @@ def _parse_concept(
803803
),
804804
)
805805

806-
# fmt: off
807-
_expr_operators = {
808-
"<", ">", "|", "%", "^", "!", "*", "-", "+", "&", "=",
809-
"&&", "||", "<<"
810-
}
811-
# fmt: on
812-
813806
def _parse_requires(
814807
self,
815808
tok: LexToken,
@@ -818,38 +811,51 @@ def _parse_requires(
818811

819812
rawtoks: typing.List[LexToken] = []
820813

821-
# The easier case -- requires requires
822-
if tok.type == "requires":
823-
rawtoks.append(tok)
824-
for tt in ("(", "{"):
825-
tok = self._next_token_must_be(tt)
826-
rawtoks.extend(self._consume_balanced_tokens(tok))
827-
# .. and that's it?
828-
829-
# this is either a parenthesized expression or a primary clause
830-
elif tok.type == "(":
831-
rawtoks.extend(self._consume_balanced_tokens(tok))
832-
else:
814+
# The expression in a requires clause must be one of the following:
815+
# 1) A primary expression
816+
# 2) A sequence of (1) joined with &&
817+
# 3) A sequence of (2) joined with ||
818+
#
819+
# In general, a primary expression is one of the following:
820+
# 1) this
821+
# 2) a literal
822+
# 3) an identifier expression
823+
# 4) a lambda expression
824+
# 5) a fold expression
825+
# 6) a requires expression
826+
# 7) any parenthesized expression
827+
#
828+
# For simplicity, we only consider the following primary expressions:
829+
# 1) parenthesized expressions (which includes fold expressions)
830+
# 2) requires expressions
831+
# 3) identifer expressions (possibly qualified, possibly templated)
832+
while True:
833833
while True:
834834
if tok.type == "(":
835835
rawtoks.extend(self._consume_balanced_tokens(tok))
836+
elif tok.type == "requires":
837+
rawtoks.append(tok)
838+
for tt in ("(", "{"):
839+
tok = self._next_token_must_be("{")
840+
rawtoks.extend(self._consume_balanced_tokens(tok))
836841
else:
837842
tok = self._parse_requires_segment(tok, rawtoks)
838843

839-
# If this is not an operator of some kind, we don't know how
840-
# to proceed so let the next parser figure it out
841-
if tok.value not in self._expr_operators:
844+
if tok.value != "&&":
842845
break
843846

844847
rawtoks.append(tok)
845848

846-
# check once more for compound operator?
847849
tok = self.lex.token()
848-
if tok.value in self._expr_operators:
849-
rawtoks.append(tok)
850-
tok = self.lex.token()
851850

852-
self.lex.return_token(tok)
851+
if tok.value != "||":
852+
break
853+
854+
rawtoks.append(tok)
855+
856+
tok = self.lex.token()
857+
858+
self.lex.return_token(tok)
853859

854860
return self._create_value(rawtoks)
855861

0 commit comments

Comments
 (0)