Operator-precedence grammar

An operator precedence grammar is a kind of grammar for formal languages.

Technically, an operator precedence grammar is a context-free grammar that has the property (among others){{harvnb|Aho|Sethi|Ullman|1988|p=203}}

that no production has either an empty right-hand side or two adjacent nonterminals in its

right-hand side. These properties allow precedence relations to be

defined between the terminals of the grammar. A parser that exploits these relations is considerably simpler than more general-purpose parsers, such as LALR parsers. Operator-precedence parsers can be constructed for a large class of context-free grammars.

Precedence relations

Operator precedence grammars rely on the following three precedence relations between the terminals:{{harvnb|Aho|Sethi|Ullman|1988|pp=203–204}}

class="wikitable"
Relation

! Meaning

a \lessdot b

| {{mvar|a}} yields precedence to {{mvar|b}}

a \doteq b

| {{mvar|a}} has the same precedence as {{mvar|b}}

a \gtrdot b

| {{mvar|a}} takes precedence over {{mvar|b}}

These operator precedence relations allow to delimit the handles in the right sentential forms: \lessdot marks the left end, \doteq appears in the interior of the handle, and \gtrdot marks the right end. Contrary to other shift-reduce parsers, all nonterminals are considered equal for the purpose of identifying handles.{{harvnb|Aho|Sethi|Ullman|1988|pp=205–206}}

The relations do not have the same properties as their un-dotted counterparts;

e. g. a \doteq b does not generally imply b \doteq a, and b \gtrdot a does not follow

from a \lessdot b. Furthermore, a \doteq a does not generally hold, and a \gtrdot a is possible.

Let us assume that between the terminals {{mvar|ai}} and {{math|ai+1}} there is always exactly one precedence relation. Suppose that $ is the end of the string.

Then for all terminals {{mvar|b}} we define: \$ \lessdot b and b \gtrdot \$. If we remove all nonterminals and place the correct precedence relation:

\lessdot, \doteq, \gtrdot between the remaining terminals, there remain strings that can be analyzed by an easily developed bottom-up parser.

= Example =

For example, the following operator precedence relations can

be introduced for simple expressions:{{harvnb|Aho|Sethi|Ullman|1988|p=205}}

:\begin{array}{c|cccc}

& \mathrm{id}

& +

& *

& \$

\\

\hline

\mathrm{id}

&

& \gtrdot

& \gtrdot

& \gtrdot

\\

+

& \lessdot

& \gtrdot

& \lessdot

& \gtrdot

\\

*

& \lessdot

& \gtrdot

& \gtrdot

& \gtrdot

\\

\$

& \lessdot

& \lessdot

& \lessdot

&

\end{array}

They follow from the following facts:{{harvnb|Aho|Sethi|Ullman|1988|p=204}}

  • + has lower precedence than * (hence + \lessdot * and * \gtrdot +).
  • Both + and * are left-associative (hence + \gtrdot + and * \gtrdot *).

The input string

: \mathrm{id}_1 + \mathrm{id}_2 * \mathrm{id}_3

after adding end markers and inserting precedence relations becomes

: \$ \lessdot \mathrm{id}_1 \gtrdot + \lessdot \mathrm{id}_2 \gtrdot * \lessdot \mathrm{id}_3 \gtrdot \$

Operator precedence parsing

Having precedence relations allows to identify handles as follows:

  • scan the string from left until seeing \gtrdot
  • scan backwards (from right to left) over any \doteq until seeing \lessdot
  • everything between the two relations \lessdot and \gtrdot, including any intervening or surrounding nonterminals, forms the handle

It is generally not necessary to scan the entire sentential form to find the handle.

Operator precedence parsing algorithm

The algorithm below is from Aho et al.:{{harvnb|Aho|Sethi|Ullman|1988|p=206}}

If $ is on the top of the stack and ip points to $ then return

else

Let a be the top terminal on the stack, and b the symbol pointed to by ip

if a \lessdot b or a \doteq b then

push b onto the stack

advance ip to the next input symbol

else if a \gtrdot b then

repeat

pop the stack

until the top stack terminal is related by \lessdot to the terminal most recently popped

else error()

end

Precedence functions

An operator precedence parser usually does not store the precedence table with the relations, which can get rather large. Instead, precedence functions f and g are defined.{{harvnb|Aho|Sethi|Ullman|1988|pp=208–209}}

They map terminal symbols to integers, and so the precedence relations between the symbols are implemented by numerical comparison:

{{tmath|f(a) < g(b)}} must hold if a \lessdot b holds, etc.

Not every table of precedence relations has precedence functions, but in practice for most grammars such functions can be designed.{{harvnb|Aho|Sethi|Ullman|1988|p=209}}

= Algorithm for constructing precedence functions =

The below algorithm is from Aho et al.:{{harvnb|Aho|Sethi|Ullman|1988|pp=209–210}}

  1. Create symbols {{mvar|fa}} and {{mvar|ga}} for each grammar terminal {{mvar|a}} and for the end of string symbol;
  2. Partition the created symbols in groups so that {{mvar|fa}} and {{mvar|gb}} are in the same group if a \doteq b (there can be symbols in the same group even if their terminals are not connected by this relation);
  3. Create a directed graph whose nodes are the groups. For each pair {{tmath|(a,b)}} of terminals do: place an edge from the group of {{mvar|gb}} to the group of {{mvar|fa}} if {{nobreak|a \lessdot b,}} otherwise if a \gtrdot b place an edge from the group of {{mvar|fa}} to that of {{mvar|gb}};
  4. If the constructed graph has a cycle then no precedence functions exist. When there are no cycles, let {{tmath|f(a)}} be the length of the longest path from the group of {{mvar|fa}} and let {{tmath|g(a)}} be the length of the longest path from the group of {{mvar|ga}}.

= Example =

Consider the following table (repeated from above):{{harvnb|Aho|Sethi|Ullman|1988|p=210}}

:\begin{array}{c|cccc}

& \mathrm{id}

& +

& *

& \$

\\

\hline

\mathrm{id}

&

& \gtrdot

& \gtrdot

& \gtrdot

\\

+

& \lessdot

& \gtrdot

& \lessdot

& \gtrdot

\\

*

& \lessdot

& \gtrdot

& \gtrdot

& \gtrdot

\\

\$

& \lessdot

& \lessdot

& \lessdot

&

\end{array}

Using the algorithm leads to the following graph:

gid

\

fid f*

\ /

g*

/

f+

| \

| g+

| |

g$ f$

from which we extract the following precedence functions from the maximum heights in the directed acyclic graph:

:

class="wikitable"
! id

! +

! *

! $

f

| 4

| 2

| 4

| 0

g

| 5

| 1

| 3

| 0

Operator-precedence languages

The class of languages described by operator-precedence grammars, i.e., operator-precedence languages, is strictly contained in the class of deterministic context-free languages, and strictly contains visibly pushdown languages.{{harvnb|Crespi Reghizzi|Mandrioli|2012}}

Operator-precedence languages enjoy many closure properties: union, intersection, complementation,{{harvnb|Crespi Reghizzi|Mandrioli|Martin|1978}} concatenation, and they are the largest known class closed under all these operations and for which the emptiness problem is decidable. Another peculiar feature of operator-precedence languages is their local parsability,{{harvnb|Barenghi|Crespi Reghizzi|Mandrioli|Panella|2015}} that enables efficient parallel parsing.

There are also characterizations based on an equivalent form of automata and monadic second-order logic.{{harvnb|Lonati|Mandrioli|Panella|Pradella|2015}}

Notes

{{Reflist}}

References

  • {{cite book |last=Aho |first=Alfred V. |last2=Sethi |first2=Ravi |last3=Ullman |first3=Jeffrey D. |date=1988 |title=Compilers — Principles, Techniques, and Tools |publisher=Addison-Wesley}}
  • {{cite journal|last1=Crespi Reghizzi|first1=Stefano|last2=Mandrioli|first2=Dino|title=Operator precedence and the visibly pushdown property|journal=Journal of Computer and System Sciences|year=2012|volume=78|issue=6|pages=1837–1867|doi=10.1016/j.jcss.2011.12.006|doi-access=free}}
  • {{cite journal|last1=Crespi Reghizzi|first1=Stefano|last2=Mandrioli|first2=Dino|last3=Martin|first3=David F.|title=Algebraic Properties of Operator Precedence Languages|journal=Information and Control|year=1978|volume=37|issue=2|pages=115–133|doi=10.1016/S0019-9958(78)90474-6|doi-access=free}}
  • {{cite journal|last1=Barenghi|first1=Alessandro|last2=Crespi Reghizzi|first2=Stefano|last3=Mandrioli|first3=Dino|last4=Panella|first4=Federica|last5=Pradella|first5=Matteo|title=Parallel parsing made practical|journal=Science of Computer Programming|year=2015|volume=112|issue=3|pages=245–249|doi=10.1016/j.scico.2015.09.002|doi-access=free|hdl=11311/971391|hdl-access=free}}
  • {{cite journal|last1=Lonati|first1=Violetta|last2=Mandrioli|first2=Dino|last3=Panella|first3=Federica|last4=Pradella|first4=Matteo|title=Operator Precedence Languages: Their Automata-Theoretic and Logic Characterization|journal=SIAM Journal on Computing|year=2015|volume=44|issue=4|pages=1026–1088|doi=10.1137/140978818|hdl=2434/352809|hdl-access=free}}

Further reading

  • {{Cite journal | last = Floyd | first = R. W. | authorlink = Robert W. Floyd | title = Syntactic Analysis and Operator Precedence | journal = Journal of the ACM | volume = 10 | issue = 3 | pages = 316–333 | date=July 1963 | doi = 10.1145/321172.321179| s2cid = 19785090 | doi-access = free }}