+redef class Npriority
+ # It is the last priority group?
+ var is_last = false
+
+ # The associated production
+ var prod: nullable Production
+
+ # The production in the with the next less priority class.
+ # `null` if there is no priority or if the first priority class.
+ var next: nullable Production
+
+ redef fun accept_collect_prod(v) do
+ var old = v.prod
+ assert old != null
+ var spe = old.spe
+ assert spe != null
+ if is_last then
+ prod = spe
+ else
+ v.pricpt -= 1
+ prod = new Production(spe.name + "${v.pricpt}")
+ prod.spe = spe
+ v.gram.prods.add(prod.as(not null))
+ end
+ next = old
+ v.prod = prod
+ super
+
+ end
+ redef fun accept_check_name_visitor(v) do
+ var old = v.prod
+ v.prod = prod
+ v.pri = self
+ super
+
+ # Inject a new alternative that goes to the next less priority class
+ var alt = prod.new_alt2(prod.name + "_" + prod.alts.length.to_s, [next.as(not null)])
+ alt.trans = true
+ alt.codes = [new CodePop]
+
+ v.pri = null
+ v.prod = old
+ end
+
+ # Check and transform `v.elems` for priority
+ private fun check_priority(v: CheckNameVisitor) is abstract
+end
+
+redef class Npriority_left
+ redef fun check_priority(v) do
+ var p = prod.spe or else prod
+ assert p != null
+ if v.elems.length < 2 or v.elems.first != p or v.elems.last != p then
+ print("Error: in a Left priority class, left and right must be the production")
+ exit(1)
+ end
+ v.elems.first = prod.as(not null)
+ v.elems.last = next.as(not null)
+ end
+end
+
+redef class Npriority_right
+ redef fun check_priority(v) do
+ var p = prod.spe or else prod
+ assert p != null
+ if v.elems.length < 2 or v.elems.first != p or v.elems.last != p then
+ print("Error: in a Right priority class, left and right must be the production")
+ exit(1)
+ end
+ v.elems.first = next.as(not null)
+ v.elems.last = prod.as(not null)
+ end
+end
+
+redef class Npriority_unary
+ redef fun check_priority(v) do
+ var p = prod.spe or else prod
+ assert p != null
+ if v.elems.length < 2 or (v.elems.first != p and v.elems.last != p) then
+ print("Error: in a Unary priority class, left or right must be the production")
+ exit(1)
+ end
+ if v.elems.first == p then v.elems.first = prod.as(not null)
+ if v.elems.last == p then v.elems.last = prod.as(not null)
+ end
+end
+