+ var endl = _last_location
+ if endl == null then _last_location = old_last
+
+ n._last_location = endl
+ var startl = n._first_location
+ if startl != null then
+ # Non-epsilon production
+ assert endl != null
+
+ n.location = new Location(startl.file, startl.line_start, endl.line_end, startl.column_start, endl.column_end)
+
+ for no in _need_before_epsilons do
+ # Epsilon production that starts the current non-epsilon production
+ #var startl = n.location
+ no.location = new Location(startl.file, startl.line_start, startl.line_start, startl.column_start, startl.column_start)
+ end
+ _need_before_epsilons.clear
+
+ for no in _need_after_epsilons do
+ # Epsilon production that finishes the current non-epsilon production
+ #var endl = n.location
+ no.location = new Location(endl.file, endl.line_end, endl.line_end, endl.column_end, endl.column_end)
+ end
+ _need_after_epsilons.clear
+ else
+ # No first token means epsilon production (or "throw all my tokens" production)
+ # So, it must be located it later
+ if endl == null then
+ # Epsilon production that starts a parent non-epsilon production
+ _need_before_epsilons.add(n)
+ else
+ # Epsilon production in the middle or that finishes a parent non-epsilon production
+ _need_after_epsilons.add(n)
+ end
+ end