<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://illuminatedcomputing.com/">
  <id>https://illuminatedcomputing.com/</id>
  <title>Illuminated Computing</title>
  <updated>2024-10-23T00:00:00Z</updated>
  <link rel="alternate" href="https://illuminatedcomputing.com/" type="text/html"/>
  <link rel="self" href="https://illuminatedcomputing.com/tags/parsing/atom.xml" type="application/atom+xml"/>
  <author>
    <name>Paul A. Jungwirth</name>
    <uri>https://illuminatedcommputing.com/</uri>
  </author>
  <entry>
    <id>tag:illuminatedcomputing.com,2024-10-23:/posts/2024/10/bison-shift-reduce-conflict/</id>
    <title type="html">Solving bison shift/reduce conflicts in Postgres</title>
    <published>2024-10-23T00:00:00Z</published>
    <updated>2024-10-23T00:00:00Z</updated>
    <link rel="alternate" href="https://illuminatedcomputing.com/posts/2024/10/bison-shift-reduce-conflict/" type="text/html"/>
    <content type="html">
&lt;p&gt;I had to fix some shift/reduce conflicts in the Postgres bison grammar recently.&lt;/p&gt;

&lt;p&gt;I’ve never done this before, so it was a learning experience. Maybe my story will help some other new Postgres contributor—or anyone struggling with this technology that is central to computer science but for many day-to-day programmers seldom-used.&lt;/p&gt;

&lt;p&gt;Back in 2018 I read &lt;em&gt;lex &amp;amp; yacc&lt;/em&gt; by Doug Brown, John R. Levine, and Tony Mason (second edition published in 1992). Levine’s 2009 &lt;em&gt;flex &amp;amp; bison&lt;/em&gt; would have been a more practical choice, but I liked getting some history too. Re-reading some parts of that book was very helpful. So were &lt;a href="https://www.gnu.org/software/bison/manual/html_node/Algorithm.html"&gt;the bison manual&lt;/a&gt; and &lt;a href="https://stackoverflow.com/questions/26188276/why-doesnt-prec-have-an-effect-in-this-bison-grammar?noredirect=1&amp;amp;lq=1"&gt;some&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/9716917/why-does-this-simple-grammar-have-a-shift-reduce-conflict?rq=3"&gt;StackOverflow&lt;/a&gt; &lt;a href="https://stackoverflow.com/questions/76244745/bison-nonassoc-vs-token"&gt;questions&lt;/a&gt;. Now I’m working through &lt;a href="https://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools"&gt;The Dragon Book&lt;/a&gt;, and that would have made a great resource too. It’s easy to write some bison without going that deep, but if you get stuck it can be frustrating.&lt;/p&gt;

&lt;p&gt;I’ve been adding syntax from SQL:2011 for &lt;a href="https://sigmodrecord.org/publications/sigmodRecord/1209/pdfs/07.industry.kulkarni.pdf"&gt;application-time updates and deletes&lt;/a&gt;. If you have a &lt;code&gt;PERIOD&lt;/code&gt; or range column named &lt;code&gt;valid_at&lt;/code&gt;, you can say &lt;code&gt;UPDATE t FOR PORTION OF valid_at FROM '2024-01-01' TO '2024-02-01' SET foo = bar&lt;/code&gt;. (For more details you can &lt;a href="/pages/temporal-data-theory-and-postgres/"&gt;watch my talk&lt;/a&gt;.) The &lt;code&gt;FOR PORTION OF&lt;/code&gt; bounds don’t have to be just literals. You could also say, for example, &lt;code&gt;FROM current_time TO current_time + INTERVAL '1' HOUR&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Actually I picked that example on purpose. Did you know that intervals support this syntax: &lt;code&gt;INTERVAL '1:02:03' HOUR TO MINUTE&lt;/code&gt;? That means: Interpret the string as hours, and preserve the precision down to the minute. By default if you ask for &lt;code&gt;1:02:03 HOUR&lt;/code&gt; you get just an hour. But &lt;code&gt;TO MINUTE&lt;/code&gt; means you get 1 hour and 2 minutes. (You still lose the seconds.)&lt;/p&gt;

&lt;p&gt;So how does &lt;a href="https://en.wikipedia.org/wiki/LR_parser"&gt;an LR(1) parser&lt;/a&gt; deal with &lt;code&gt;FOR PORTION OF valid_at FROM current_time + INTERVAL '1' HOUR TO MINUTE&lt;/code&gt;? When we consider the &lt;code&gt;TO&lt;/code&gt;, does it belong with the interval, or does it start the closing bound of the &lt;code&gt;FOR PORTION OF&lt;/code&gt;? This is a shift/reduce conflict. Bison can’t look ahead further than one token to guess what is correct—and I’m not sure it would help even if it could.&lt;/p&gt;

&lt;p&gt;When the next token is able to complete some piece of the grammar, called a “rule”, the parser “reduces”: it consumes those tokens and lets you run a custom “action” attached to your rule. Otherwise, bison shifts the token onto a stack of not-yet-reduced tokens, so that it can reduce a rule in the future. But bison needs to decide each time it sees a token whether to reduce or to shift.&lt;/p&gt;

&lt;p&gt;Here is the rule for &lt;code&gt;FOR PORTION OF&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for_portion_of_clause:
  FOR PORTION OF ColId FROM a_expr TO a_expr
    {
      ForPortionOfClause *n = makeNode(ForPortionOfClause);
      n-&amp;gt;range_name = $4;
      n-&amp;gt;location = @4;
      n-&amp;gt;target_start = $6;
      n-&amp;gt;target_end = $8;
      $$ = n;
    }
;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The first line is the name of the rule, so we can use it in higher-level contexts: the &lt;code&gt;UPDATE&lt;/code&gt; statement (and also &lt;code&gt;DELETE&lt;/code&gt;). The second line has the inputs we need to match to complete the rule. Some of them are “terminals”: keywords, identifiers, operators, literals, punctuation, etc.—in this case &lt;code&gt;FOR&lt;/code&gt;, &lt;code&gt;PORTION&lt;/code&gt;, &lt;code&gt;OF,&lt;/code&gt; &lt;code&gt;FROM&lt;/code&gt;, &lt;code&gt;TO&lt;/code&gt;. Some are “non-terminal”: further rules. Below all that is a block of C code: the action that gets run when we reduce. We call the name the “left side” of the rule, and the inputs the “right side” or “body”. Rules are also sometimes called “productions”. The &lt;em&gt;lex &amp;amp; yacc&lt;/em&gt; book doesn’t use that terminology, but the Dragon Book does, and so does the Postgres source code.&lt;/p&gt;

&lt;p&gt;So each bound is an &lt;code&gt;a_expr&lt;/code&gt;. The &lt;code&gt;a_expr&lt;/code&gt; rule is a complicated production with just about anything you can do in Postgres: a literal, a variable, a function call, an operator, a subquery, lots of weird SQL keywords, etc. Many contexts forbid some of these things, e.g. you can’t refer to a column in a &lt;code&gt;DEFAULT&lt;/code&gt; expression or a partition bound—but that is enforced during analysis, not by the grammar.&lt;/p&gt;

&lt;p&gt;To speak more precisely, when a non-terminal can match inputs in more than one way (like &lt;code&gt;a_expr&lt;/code&gt;), we should call &lt;em&gt;each alternative&lt;/em&gt; a rule or production. But in bison you commonly write the name once then separate each body with a pipe (&lt;code&gt;|&lt;/code&gt;), so all the rules share one name. There is not one &lt;code&gt;a_expr&lt;/code&gt; rule, but many: 68 by my count. But such terminological precision is rarely needed.&lt;/p&gt;

&lt;p&gt;Take our example, &lt;code&gt;FOR PORTION OF valid_at FROM current_time + INTERVAL '1' HOUR • TO MINUTE&lt;/code&gt;. I’ve added a dot to represent bison’s “cursor”. It is considering what to do with the &lt;code&gt;TO&lt;/code&gt;. We could reduce the &lt;code&gt;a_expr&lt;/code&gt; right now, leaving the &lt;code&gt;TO&lt;/code&gt; to become part of the &lt;code&gt;FOR PORTION OF&lt;/code&gt;. Or we could shift the &lt;code&gt;TO&lt;/code&gt; so that it eventually gets reduced as part of the &lt;code&gt;a_expr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Actually it’s not about reducing the &lt;code&gt;a_expr&lt;/code&gt;, but reducing one of its many sub-rules, in this case the interval. An &lt;code&gt;a_expr&lt;/code&gt; can be a &lt;code&gt;c_expr&lt;/code&gt; (among other things), and a &lt;code&gt;c_expr&lt;/code&gt; can be an &lt;code&gt;AexprConst&lt;/code&gt; (among other things), and an &lt;code&gt;AexprConst&lt;/code&gt; can be a &lt;code&gt;ConstInterval Sconst opt_interval&lt;/code&gt; (among other things), and the &lt;code&gt;opt_interval&lt;/code&gt; is the problem, because it can optionally have a &lt;code&gt;TO&lt;/code&gt;. Here is that rule:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;opt_interval:
  YEAR_P
    { $$ = list_make1(makeIntConst(INTERVAL_MASK(YEAR), @1)); }
  | MONTH_P
    { $$ = list_make1(makeIntConst(INTERVAL_MASK(MONTH), @1)); }
  | DAY_P
    { $$ = list_make1(makeIntConst(INTERVAL_MASK(DAY), @1)); }
  | HOUR_P
    { $$ = list_make1(makeIntConst(INTERVAL_MASK(HOUR), @1)); }
  | MINUTE_P
    { $$ = list_make1(makeIntConst(INTERVAL_MASK(MINUTE), @1)); }
  | interval_second
    { $$ = $1; }
  | YEAR_P TO MONTH_P
    { ... }
  | DAY_P TO HOUR_P
    { ... }
  | DAY_P TO MINUTE_P
    { ... }
  | DAY_P TO interval_second
    { ... }
  | HOUR_P TO MINUTE_P
    { ... }
  | HOUR_P TO interval_second
    { ... }
  | MINUTE_P TO interval_second
    { ... }
  | /*EMPTY*/
    { $$ = NIL; }
;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(I’ve omitted most of the actions, since actions don’t affect bison’s choices.) The &lt;code&gt;opt_interval&lt;/code&gt; rule is what bison is trying to reduce.&lt;/p&gt;

&lt;p&gt;When you have a shift/reduce conflict, &lt;code&gt;make&lt;/code&gt; gives you an error like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/usr/bin/bison -d -o gram.c gram.y
gram.y: conflicts: 4 shift/reduce
gram.y: expected 0 shift/reduce conflicts
make[2]: *** [gram.c] Error 1
make[1]: *** [parser/gram.h] Error 2
make: *** [submake-generated-headers] Error 2&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That is not much to go on.&lt;/p&gt;

&lt;p&gt;By the way, do you see the &lt;code&gt;expected 0&lt;/code&gt;? A shift/reduce conflict doesn’t have to be fatal. Bison will default to shift. But this is a bit sketchy. It means you could accidentally write an ambiguous grammar that causes trouble later. So bison lets you declare how many conflicts you expect, and it only fails if it finds a different count. I like that for Postgres the expected conflict count is zero. For MariaDB &lt;a href="https://github.com/MariaDB/server/blob/4b6922a315fa5411665ac99c0b40fd7238093403/sql/sql_yacc.yy#L357-L361"&gt;it is 62&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anyway, we have four shift/reduce conflicts. Now what? Let’s ask Bison where they are. It can take a &lt;code&gt;-v/--verbose&lt;/code&gt; option to generate a “report file”. Since Postgres’s grammar lives in &lt;code&gt;gram.y&lt;/code&gt;, the report file is &lt;code&gt;gram.output&lt;/code&gt;. (Modern versions offer more control with &lt;code&gt;-r/--report&lt;/code&gt; and &lt;code&gt;--report-file&lt;/code&gt;, but macOS only supports &lt;code&gt;-v&lt;/code&gt;.) We aren’t running bison directly, but we can control things like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;make BISONFLAGS=-v&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That gives us a file with 5.5 million lines, but right at the top we see:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;State 1454 conflicts: 1 shift/reduce
State 1455 conflicts: 1 shift/reduce
State 1456 conflicts: 1 shift/reduce
State 1459 conflicts: 1 shift/reduce&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then if we &lt;code&gt;/^state 1454&lt;/code&gt; we see this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;state 1454

  2000 opt_interval: DAY_P .
  2005             | DAY_P . TO HOUR_P
  2006             | DAY_P . TO MINUTE_P
  2007             | DAY_P . TO interval_second

    TO  shift, and go to state 2670

    TO        [reduce using rule 2000 (opt_interval)]
    $default  reduce using rule 2000 (opt_interval)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So in this state, bison has four candidate rules it could eventually reduce, numbered 2000, 2005, 2006, 2007. Below that are possible valid tokens and what to do for each one. We see &lt;code&gt;TO&lt;/code&gt; twice, which is the problem. The square brackets highlight the conflict: they mark a transition that will never happen. (The &lt;code&gt;$default&lt;/code&gt; line means if the next token is &lt;em&gt;not&lt;/em&gt; a &lt;code&gt;TO&lt;/code&gt;, we can reduce and leave that token for some higher-level rule to match.) So this is how we know one half of the problem is &lt;code&gt;opt_interval&lt;/code&gt;. The other half is &lt;code&gt;for_portion_of_clause&lt;/code&gt;. Bison doesn’t tell us that, but (1) we just added it to a previously-working grammar (2) we can see that &lt;code&gt;TO&lt;/code&gt; is the issue, and that’s where we match a &lt;code&gt;TO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is one of the four shift/reduce conflicts. The other three are also from &lt;code&gt;opt_interval&lt;/code&gt;, caused by &lt;code&gt;YEAR_P TO MONTH_P&lt;/code&gt;, &lt;code&gt;HOUR_P TO {MINUTE_P,interval_second}&lt;/code&gt;, and &lt;code&gt;MINUTE_P TO interval_second&lt;/code&gt;. Essentially it’s all one conflict, but we can hit the &lt;code&gt;TO&lt;/code&gt; after &lt;code&gt;DAY&lt;/code&gt;, &lt;code&gt;HOUR&lt;/code&gt;, &lt;code&gt;YEAR&lt;/code&gt;, or &lt;code&gt;MINUTE&lt;/code&gt;, so that’s four different states.&lt;/p&gt;

&lt;p&gt;We can use “precedence” to resolve such ambiguities. It’s just like elementary arithmetic: multiplication has higher precedence than addition. It is stickier. We do it first. But what does that mean in bison? Bison compares the precedence of the non-terminal rule it could reduce (&lt;code&gt;opt_interval&lt;/code&gt;) vs the precedence of the token it could shift (&lt;code&gt;TO&lt;/code&gt;). Rules don’t really have precedence themselves, but they get the precedence of their final terminal token.&lt;/p&gt;

&lt;p&gt;So in state 1454, if we give &lt;code&gt;DAY_P&lt;/code&gt; a different precedence than &lt;code&gt;TO&lt;/code&gt;, bison will know whether to reduce (rule 2000), or shift (and eventually reduce rule 2005, 2006, or 2007). If &lt;code&gt;DAY_P&lt;/code&gt; is higher, we’ll reduce. If &lt;code&gt;TO&lt;/code&gt; is higher, we’ll shift.&lt;/p&gt;

&lt;p&gt;Should we shift or reduce? The only answer is to shift. If we reduce by default, then users can &lt;em&gt;never&lt;/em&gt; say &lt;code&gt;INTERVAL '1' DAY TO HOUR&lt;/code&gt; (even in a completely different context). No amount of parens will make bison do otherwise. But if we shift, then this is a syntax error: &lt;code&gt;FOR PORTION OF valid_at FROM '2013-03-01'::timestamp + INTERVAL '1' HOUR TO '2014-01-01'&lt;/code&gt; (because after shifting the &lt;code&gt;TO&lt;/code&gt; bison is still trying to reduce &lt;code&gt;opt_interval&lt;/code&gt;), but this fixes it: &lt;code&gt;FOR PORTION OF valid_at FROM ('2013-03-01'::timestamp + INTERVAL '1' HOUR) TO '2014-01-01'&lt;/code&gt;. Users can get what they want by adding parens.&lt;/p&gt;

&lt;p&gt;So to shift, we give &lt;code&gt;TO&lt;/code&gt; a higher precedence than &lt;code&gt;YEAR_P&lt;/code&gt;, &lt;code&gt;DAY_P&lt;/code&gt;, &lt;code&gt;HOUR_P&lt;/code&gt;, and &lt;code&gt;MINUTE_P&lt;/code&gt;. By default a token has no precedence, but bison lets you make a list of declarations where &lt;em&gt;lower lines&lt;/em&gt; have &lt;em&gt;higher precedence&lt;/em&gt;. So for a long time my patch added this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;%nonassoc YEAR_P DAY_P HOUR_P MINUTE_P
%nonassoc TO&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(Actually I had &lt;code&gt;MONTH_P&lt;/code&gt; in there too, but that isn’t needed because you can’t have &lt;code&gt;MONTH TO ...&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;But this is frowned upon. There is a comment right above my change that gave me a guilty conscience for at least a year, maybe a few:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/*
 * Sometimes it is necessary to assign precedence to keywords that are not
 * really part of the operator hierarchy, in order to resolve grammar
 * ambiguities.  It's best to avoid doing so whenever possible, because such
 * assignments have global effect and may hide ambiguities besides the one
 * you intended to solve.  (Attaching a precedence to a single rule with
 * %prec is far safer and should be preferred.)  If you must give precedence
 * to a new keyword, try very hard to give it the same precedence as IDENT.
 * If the keyword has IDENT's precedence then it clearly acts the same as
 * non-keywords and other similar keywords, thus reducing the risk of
 * unexpected precedence effects.
 */&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I knew I had to fix this before my patch would get accepted. Those two lines had to go.&lt;/p&gt;

&lt;p&gt;What is the &lt;code&gt;%prec&lt;/code&gt; approach suggested by the comment? I said above that a rule’s precedence comes from its last terminal token. But you can override a rule’s precedence by putting &lt;code&gt;%prec token_name&lt;/code&gt; after the right side. For example &lt;code&gt;a_expr&lt;/code&gt; has this rule:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;| a_expr AT TIME ZONE a_expr      %prec AT
  { ... }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We’re saying we should reduce this rule with the precedence of &lt;code&gt;AT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I tried all kinds of &lt;code&gt;%prec&lt;/code&gt; placements that didn’t work. My mental model of bison’s process was too vague. The reason I’m writing this story is really to record the details and thought process that finally gave me the solution.&lt;/p&gt;

&lt;p&gt;For example, putting &lt;code&gt;%prec&lt;/code&gt; on &lt;code&gt;for_portion_of_clause&lt;/code&gt; doesn’t do any good, because the conflict is lower down than that, inside &lt;code&gt;opt_interval&lt;/code&gt;. That was counter-intuitive, because I knew that adding &lt;code&gt;for_portion_of_clause&lt;/code&gt; was what caused the problem. It’s what offers bison a way to reduce early and still have a place to use the &lt;code&gt;TO&lt;/code&gt;. But despite &lt;code&gt;for_portion_of_clause&lt;/code&gt; exerting influence, at the moment of decision we are in the middle of a different rule. It’s action-at-a-distance.&lt;/p&gt;

&lt;p&gt;Another breakthrough was realizing that the comparison is between a &lt;em&gt;rule&lt;/em&gt; (to reduce) and a &lt;em&gt;token&lt;/em&gt; (to shift). Within &lt;code&gt;opt_interval&lt;/code&gt; I kept trying to give low precedence to the rules without &lt;code&gt;TO&lt;/code&gt; and high precedence to the rules with it. But the comparison isn’t between two rules. It’s between a rule and a token. The token is &lt;code&gt;TO&lt;/code&gt; itself. There isn’t any way to give precedence to a &lt;em&gt;token&lt;/em&gt; with &lt;code&gt;%prec&lt;/code&gt;. That only modifies a rule. If &lt;code&gt;TO&lt;/code&gt; has an undefined precedence, there will always be a conflict. So I &lt;em&gt;did&lt;/em&gt; have to declare a precedence for &lt;code&gt;TO&lt;/code&gt;, but following the comment above I could give it the same precedence as &lt;code&gt;IDENT&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;%nonassoc IDENT PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE ROLLUP
      SET KEYS OBJECT_P SCALAR TO VALUE_P WITH WITHOUT PATH&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then the conflicting &lt;code&gt;opt_interval&lt;/code&gt; rules needed a lower precedence, to prevent reducing early. A low-precedence keyword we use a lot is &lt;code&gt;IS&lt;/code&gt;, so I did this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;opt_interval:
  YEAR_P                                %prec IS
    { ... }
  | DAY_P                               %prec IS
    { ... }
  | HOUR_P                              %prec IS
    { ... }
  | MINUTE_P                            %prec IS
    { ... }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we’ll shift the &lt;code&gt;TO&lt;/code&gt; and follow those rules that include it.&lt;/p&gt;

&lt;p&gt;Finally I had a solution!&lt;/p&gt;

&lt;p&gt;It’s worth considering another approach. We can also enforce precedence with the structure of our rules, without declaring an explicit higher/lower precedence for terminals. For example for simple arithmetic we could do this (from the Dragon Book, p. 49–50):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;expr: expr + term
  | expr - term
  | term

term: term * factor
  | term / factor
  | factor

factor: digit
  | '(' expr ')'&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For &lt;code&gt;n&lt;/code&gt; levels of precedence, we need &lt;code&gt;n+1&lt;/code&gt; different rules. But I think this approach gets unwieldy quickly. And anyway was I going to rewrite the Postgres grammar to do this?&lt;/p&gt;

&lt;p&gt;Postgres actually does this a bit already though. We’ve seen &lt;code&gt;a_expr&lt;/code&gt; and &lt;code&gt;c_expr&lt;/code&gt;. Of course there is also &lt;code&gt;b_expr&lt;/code&gt;. &lt;code&gt;b_expr&lt;/code&gt; is a more limited set of rules than &lt;code&gt;a_expr&lt;/code&gt;, and &lt;code&gt;c_expr&lt;/code&gt; is everything they have in common.&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;b_expr&lt;/code&gt; to solve some shift/reduce conflicts. For example a column’s &lt;code&gt;DEFAULT&lt;/code&gt; value can only take a &lt;code&gt;b_expr&lt;/code&gt;, because a &lt;code&gt;NOT&lt;/code&gt; would be a shift/reduce conflict: is it a &lt;code&gt;NOT NULL&lt;/code&gt; constraint on the column, or is it part of the &lt;code&gt;DEFAULT&lt;/code&gt; expression, e.g. &lt;code&gt;NOT LIKE&lt;/code&gt;? One rule that &lt;code&gt;b_expr&lt;/code&gt; accepts is &lt;code&gt;'(' a_expr ')'&lt;/code&gt;, so even in contexts like &lt;code&gt;DEFAULT&lt;/code&gt;, you can get whatever you want by wrapping your text in parentheses.&lt;/p&gt;

&lt;p&gt;So could I have saved myself a lot of trouble and made &lt;code&gt;FOR PORTION OF&lt;/code&gt; take &lt;code&gt;FROM b_expr TO b_expr&lt;/code&gt; instead? No, because the problem was inside &lt;code&gt;c_expr&lt;/code&gt;, which is shared by both rules.&lt;/p&gt;

&lt;p&gt;I probably could have invented a &lt;code&gt;d_expr&lt;/code&gt;, but that would have been a lot of work, only to produce a more tangled grammar that I expect no reviewer would have accepted.&lt;/p&gt;

&lt;p&gt;So that’s the story of how I fixed my four shift-reduce conflicts.&lt;/p&gt;

&lt;p&gt;But just when you think you’ve killed the zombie, he rises from the dead. Right around the same time, I realized my grammar was wrong. In SQL, you can give your table an alias when you &lt;code&gt;UPDATE&lt;/code&gt; or &lt;code&gt;DELETE&lt;/code&gt;. It can use &lt;code&gt;AS&lt;/code&gt; or not: &lt;code&gt;UPDATE tablename [[AS] t]&lt;/code&gt; and &lt;code&gt;DELETE FROM tablename [[AS] t]&lt;/code&gt;. I was putting &lt;code&gt;FOR PORTION OF&lt;/code&gt; &lt;em&gt;after&lt;/em&gt; the alias, but according to SQL:2011 it comes &lt;em&gt;before&lt;/em&gt;. I tried moving it, and I got . . . 30 shift/reduce conflicts!&lt;/p&gt;

&lt;p&gt;These looked really hairy: the problem was that &lt;code&gt;AS&lt;/code&gt; is optional and the alias can be nearly anything. It can’t be a &lt;em&gt;reserved&lt;/em&gt; keyword (unless you quote it), but many keywords are not reserved (per the standard), so there’s ambiguity there. Allowing &lt;code&gt;a_expr&lt;/code&gt;, which can be nearly anything, followed by an optional alias, which can be nearly anything, is bad news. I really thought I was in trouble.&lt;/p&gt;

&lt;p&gt;Could I just ignore the standard? I don’t think that would be acceptable, not in this matter. But it was tempting enough that I checked what MariaDB and IBM DB2 were doing. Somehow they were making it work. I should figure it out too.&lt;/p&gt;

&lt;p&gt;I think I took a walk, or maybe I slept on it, but I realized that we already have the same problem with &lt;em&gt;column&lt;/em&gt; aliases when you &lt;code&gt;SELECT&lt;/code&gt;. Each selected column is an &lt;code&gt;a_expr&lt;/code&gt;, and their aliases don’t require &lt;code&gt;AS&lt;/code&gt;. What was Postgres doing to make that work?&lt;/p&gt;

&lt;p&gt;I found this rule for &lt;code&gt;SELECT&lt;/code&gt;ing:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;target_el:  a_expr AS ColLabel { ...}
      | a_expr BareColLabel { ... }
      | a_expr { ... }
      | '*' { ... }
    ;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It turns out that &lt;code&gt;ColLabel&lt;/code&gt; allows anything (even reserved keywords!), but &lt;code&gt;BareColLabel&lt;/code&gt; is more restricted.&lt;/p&gt;

&lt;p&gt;So I could do something similar: when there is an &lt;code&gt;AS&lt;/code&gt;, permit everything, but otherwise only permit tokens that are conflict-free. If fact to keep backward-compatibility, I could leave the old grammar rule for &lt;code&gt;UPDATE&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt; in place (each had only one), and only get more restrictive when &lt;code&gt;FOR PORTION OF&lt;/code&gt; is present. Maybe reviewers will ask me to change things, but at the moment my solution looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;opt_alias:
  AS ColId { ... }
  | BareColLabel { ... }
  | /* empty */ %prec UMINUS { $$ = NULL; }
;

UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias
  SET set_clause_list
  from_clause
  where_or_current_clause
  returning_clause
    { ... }
  | opt_with_clause UPDATE relation_expr
  for_portion_of_clause opt_alias
  SET set_clause_list
  from_clause
  where_or_current_clause
  returning_clause
    { ... }
;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I’m not sure I like using &lt;code&gt;BareColLabel&lt;/code&gt; for non-column aliases, but the existing &lt;code&gt;relation_expr_opt_alias&lt;/code&gt; uses &lt;code&gt;ColId&lt;/code&gt;, so maybe it’s okay.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;%prec&lt;/code&gt; is necessary to resolve a conflict with &lt;code&gt;USING&lt;/code&gt;, which is permitted by &lt;code&gt;BareColLabel&lt;/code&gt;, and also allowed in &lt;code&gt;DELETE FROM ... USING&lt;/code&gt;. If I added a separate list for bare &lt;em&gt;table&lt;/em&gt; labels, we could leave out &lt;code&gt;USING&lt;/code&gt; and not use &lt;code&gt;%prec&lt;/code&gt; here, but I don’t think maintaining another keyword list would be popular.&lt;/p&gt;

&lt;p&gt;That’s it! I’m happy that at 47 I can still work out the errors in my mental model of something and correct them. Hopefully by writing this down I won’t have to do it more than once. :-)&lt;/p&gt;
</content>
  </entry>
</feed>

