@@ -26,18 +26,39 @@ void PolynomialAttr::print(AsmPrinter &p) const {
2626
2727// / Try to parse a monomial. If successful, populate the fields of the outparam
2828// / `monomial` with the results, and the `variable` outparam with the parsed
29- // / variable name.
29+ // / variable name. Sets shouldParseMore to true if the monomial is followed by
30+ // / a '+'.
3031ParseResult parseMonomial (AsmParser &parser, Monomial &monomial,
31- llvm::StringRef &variable, bool *isConstantTerm) {
32+ llvm::StringRef &variable, bool *isConstantTerm,
33+ bool *shouldParseMore) {
3234 APInt parsedCoeff (apintBitWidth, 1 );
33- auto result = parser.parseOptionalInteger (parsedCoeff);
34-
35- // Variable name
36- result = parser.parseOptionalKeyword (&variable);
37- if (!result.has_value () || failed (*result)) {
38- // We allow "failed" because it triggers when the next token is a +,
39- // which is allowed when the input is the constant term.
40- monomial.coefficient = parsedCoeff;
35+ auto parsedCoeffResult = parser.parseOptionalInteger (parsedCoeff);
36+ monomial.coefficient = parsedCoeff;
37+
38+ *isConstantTerm = false ;
39+ *shouldParseMore = false ;
40+
41+ // A + indicates it's a constant term with more to go, as in `1 + x`.
42+ if (succeeded (parser.parseOptionalPlus ())) {
43+ // If no coefficient was parsed, and there's a +, then it's effectively
44+ // parsing an empty string.
45+ if (!parsedCoeffResult.has_value ()) {
46+ return failure ();
47+ }
48+ monomial.exponent = APInt (apintBitWidth, 0 );
49+ *isConstantTerm = true ;
50+ *shouldParseMore = true ;
51+ return success ();
52+ }
53+
54+ // A monomial can be a trailing constant term, as in `x + 1`
55+ if (failed (parser.parseOptionalKeyword (&variable))) {
56+ // If neither a coefficient nor a variable was found, then it's effectively
57+ // parsing an empty string.
58+ if (!parsedCoeffResult.has_value ()) {
59+ return failure ();
60+ }
61+
4162 monomial.exponent = APInt (apintBitWidth, 0 );
4263 *isConstantTerm = true ;
4364 return success ();
@@ -46,29 +67,30 @@ ParseResult parseMonomial(AsmParser &parser, Monomial &monomial,
4667 // Parse exponentiation symbol as **
4768 // We can't use caret because it's reserved for basic block identifiers
4869 // If no star is present, it's treated as a polynomial with exponent 1
49- if (failed (parser.parseOptionalStar ())) {
50- monomial.coefficient = parsedCoeff;
51- monomial.exponent = APInt (apintBitWidth, 1 );
52- return success ();
53- }
70+ if (succeeded (parser.parseOptionalStar ())) {
71+ // If there's one * there must be two
72+ if (failed (parser.parseStar ())) {
73+ parser.emitError (parser.getCurrentLocation (),
74+ " exponents must be specified as a double-asterisk `**`" );
75+ return failure ();
76+ }
5477
55- // If there's one * there must be two
56- if (failed (parser.parseStar ())) {
57- parser.emitError (parser.getCurrentLocation (),
58- " exponents must be specified as a double-asterisk `**`" );
59- return failure ();
60- }
78+ // If there's a **, then the integer exponent is required.
79+ APInt parsedExponent (apintBitWidth, 0 );
80+ if (failed (parser.parseInteger (parsedExponent))) {
81+ parser.emitError (parser.getCurrentLocation (),
82+ " found invalid integer exponent" );
83+ return failure ();
84+ }
6185
62- // If there's a **, then the integer exponent is required.
63- APInt parsedExponent (apintBitWidth, 0 );
64- if (failed (parser.parseInteger (parsedExponent))) {
65- parser.emitError (parser.getCurrentLocation (),
66- " found invalid integer exponent" );
67- return failure ();
86+ monomial.exponent = parsedExponent;
87+ } else {
88+ monomial.exponent = APInt (apintBitWidth, 1 );
6889 }
6990
70- monomial.coefficient = parsedCoeff;
71- monomial.exponent = parsedExponent;
91+ if (succeeded (parser.parseOptionalPlus ())) {
92+ *shouldParseMore = true ;
93+ }
7294 return success ();
7395}
7496
@@ -83,9 +105,11 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
83105 while (true ) {
84106 Monomial parsedMonomial;
85107 llvm::StringRef parsedVariableRef;
86- bool isConstantTerm = false ;
108+ bool isConstantTerm;
109+ bool shouldParseMore;
87110 if (failed (parseMonomial (parser, parsedMonomial, parsedVariableRef,
88- &isConstantTerm))) {
111+ &isConstantTerm, &shouldParseMore))) {
112+ parser.emitError (parser.getCurrentLocation (), " expected a monomial" );
89113 return {};
90114 }
91115
@@ -105,26 +129,16 @@ Attribute PolynomialAttr::parse(AsmParser &parser, Type type) {
105129 }
106130 exponents.insert (parsedMonomial.exponent );
107131
108- // Parse optional +. If a + is absent, require > and break, otherwise forbid
109- // > and continue with the next monomial.
110- // ParseOptional{Plus, Greater} does not return an OptionalParseResult, so
111- // failed means that the token was not found.
112- if (failed (parser.parseOptionalPlus ())) {
113- if (succeeded (parser.parseGreater ())) {
114- break ;
115- }
116- parser.emitError (
117- parser.getCurrentLocation (),
118- " expected + and more monomials, or > to end polynomial attribute" );
119- return {};
120- }
132+ if (shouldParseMore)
133+ continue ;
121134
122135 if (succeeded (parser.parseOptionalGreater ())) {
123- parser.emitError (
124- parser.getCurrentLocation (),
125- " expected another monomial after +, but found > ending attribute" );
126- return {};
136+ break ;
127137 }
138+ parser.emitError (
139+ parser.getCurrentLocation (),
140+ " expected + and more monomials, or > to end polynomial attribute" );
141+ return {};
128142 }
129143
130144 if (variables.size () > 1 ) {
0 commit comments