[GRASS-dev] [GRASS GIS] #2770: r.mapcalc reports syntax error for valid script but no error for separate expressions

#2770: r.mapcalc reports syntax error for valid script but no error for separate
expressions
-------------------------+-------------------------
Reporter: marisn | Owner: grass-dev@…
     Type: defect | Status: new
Priority: normal | Milestone:
Component: Raster | Version: svn-trunk
Keywords: r.mapcalc | CPU: Unspecified
Platform: Unspecified |
-------------------------+-------------------------
Seems that r.mapcalc doesn't like some sequences of valid expressions.
Following examples show the same expressions copy/pasted into interactive
r.mapcalc session all together and one by one. Notice - same syntax once
causes "syntax error" but no "syntax error" is generated if execution
happens to be performed on a separate r.mapcalc process.
{{{
r.mapcalc --overwrite
Enter expressions, "end" when done.
mapcalc> speed_up = if(speed < 5, speed + 1, speed)
mapcalc> max_speed = if( !isnull(speed[0,1]), 0,\
mapcalc> if( !isnull(speed[0,2]), 1,\
mapcalc> if( !isnull(speed[0,3]), 2,\
mapcalc> if( !isnull(speed[0,4]), 3,\
mapcalc> if( !isnull(speed[0,5]), 4, 5)))))
mapcalc> res_speed = if(speed_up > max_speed, max_speed, speed_up)
mapcalc> moved = if( res_speed[0, 0] == 0, 0,\
syntax error, unexpected '[', expecting ')'
mapcalc> if( res_speed[0,-1] == 1, 1,\
mapcalc> if( res_speed[0,-2] == 2, 2,\
mapcalc> if( res_speed[0,-3] == 3, 3,\
mapcalc> if( res_speed[0,-4] == 4, 4,\
mapcalc> if( res_speed[0,-5] == 5, 5, null()))))))
mapcalc> end
Parse error

}}}

{{{
r.mapcalc --overwrite
Enter expressions, "end" when done.
mapcalc> speed_up = if(speed < 5, speed + 1, speed)
mapcalc> end

  100%
GRASS 7.1.svn (xy_loc):~/soft/grass_trunk > r.mapcalc --overwrite
Enter expressions, "end" when done.
mapcalc> max_speed = if( !isnull(speed[0,1]), 0,\
mapcalc> if( !isnull(speed[0,2]), 1,\
mapcalc> if( !isnull(speed[0,3]), 2,\
mapcalc> if( !isnull(speed[0,4]), 3,\
mapcalc> if( !isnull(speed[0,5]), 4, 5)))))
mapcalc> end

  100%
GRASS 7.1.svn (xy_loc):~/soft/grass_trunk > r.mapcalc --overwrite
Enter expressions, "end" when done.
mapcalc> res_speed = if(speed_up > max_speed, max_speed, speed_up)
mapcalc> end

  100%
GRASS 7.1.svn (xy_loc):~/soft/grass_trunk > r.mapcalc --overwrite
Enter expressions, "end" when done.
mapcalc> moved = if( res_speed[0, 0] == 0, 0,\
mapcalc> if( res_speed[0,-1] == 1, 1,\
mapcalc> if( res_speed[0,-2] == 2, 2,\
mapcalc> if( res_speed[0,-3] == 3, 3,\
mapcalc> if( res_speed[0,-4] == 4, 4,\
mapcalc> if( res_speed[0,-5] == 5, 5, null()))))))
mapcalc> end

  100%
}}}

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2770&gt;
GRASS GIS <https://grass.osgeo.org>

#2770: r.mapcalc reports syntax error for valid script but no error for separate
expressions
--------------------------+-------------------------
  Reporter: marisn | Owner: grass-dev@…
      Type: defect | Status: new
  Priority: normal | Milestone:
Component: Raster | Version: svn-trunk
Resolution: | Keywords: r.mapcalc
       CPU: Unspecified | Platform: Unspecified
--------------------------+-------------------------

Comment (by glynn):

Replying to [ticket:2770 marisn]:

> Seems that r.mapcalc doesn't like some sequences of valid expressions.
> Following examples show the same expressions copy/pasted into
interactive r.mapcalc session all together and one by one. Notice - same
syntax once causes "syntax error" but no "syntax error" is generated if
execution happens to be performed on a separate r.mapcalc process.

This is not a bug. It could really do with better documentation, though.

A "name" (*) refers to a variable if it has previously occurred on the
left-hand side of an assignment expression, and to an input map otherwise.

The neighbourhood modifier "map[row,col]" can only be applied to input
maps, not to variables. Likewise for the @ and # modifiers.

Each assignment expression which occurs at the top level (i.e. not nested
within a sub-expression) creates a variable, and also results in the
creation of an output map. An assignment other than at the top level only
creates a variable, not an output map. At the end of processing each row,
any variables defined at the top level have their value written as the
current row of the corresponding output map.

Any maps generated by an r.mapcalc command only exist after the entire
command has completed. All maps are generated concurrently, row-by-row
(i.e. there is an implicit "for row in rows {...}" around the entire
expression).

At present, it's impossible to read from a map which is in the process of
being created. And even if it was possible, reading from such a map with a
positive row offset would be awkward; in the worst case, two maps could
each depend upon not-yet-calculated rows of each other.

(*) A name is either
a) any sequence of (letters, digits, any of the symbols dollar, period,
backslash, underscore, backtick, left brace, right brace, or any character
>= 127), excluding anything with a prefix which can be parsed as a number,
or
b) any sequence of characters delimited by single or double quotes.

(!**) The set of characters which are allowed without quoting is probably
too liberal; AFAICT, it's essentially anything that doesn't result in the
grammar being ambiguous.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2770#comment:1&gt;
GRASS GIS <https://grass.osgeo.org>

#2770: r.mapcalc reports syntax error for valid script but no error for separate
expressions
--------------------------+-------------------------
  Reporter: marisn | Owner: grass-dev@…
      Type: defect | Status: new
  Priority: normal | Milestone: 7.0.3
Component: Raster | Version: svn-trunk
Resolution: | Keywords: r.mapcalc
       CPU: Unspecified | Platform: Unspecified
--------------------------+-------------------------
Changes (by marisn):

* milestone: => 7.0.3

Comment:

If I understood correctly, r.mapcalc works like this:
{{{
for output_row in computational_region:
     for output_cell in output_row:
         first expression
         second expression
         third expression
}}}
thus "first" becomes a map only at the end of r.mapcalc run.

Leaving open as an update to documentation is needed (I'll try to write it
if above logic is correct).

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2770#comment:2&gt;
GRASS GIS <https://grass.osgeo.org>

#2770: r.mapcalc reports syntax error for valid script but no error for separate
expressions
--------------------------+-------------------------
  Reporter: marisn | Owner: grass-dev@…
      Type: defect | Status: new
  Priority: normal | Milestone: 7.0.3
Component: Raster | Version: svn-trunk
Resolution: | Keywords: r.mapcalc
       CPU: Unspecified | Platform: Unspecified
--------------------------+-------------------------

Comment (by glynn):

Replying to [comment:2 marisn]:

> If I understood correctly, r.mapcalc works like this:
{{{
for output_row in computational_region:
     for output_cell in output_row:
         first expression
         second expression
         third expression
}}}

That's close enough for the purpose of this discussion.

But in the interests of ~~pedantry~~ accuracy, I'll point out that the
"for output_cell" loop actually occurs within the evaluation of each
expression and subexpression. All of the C functions used to implement
r.mapcalc's operators and functions take entire rows as arguments and
return an entire row as their result.

> thus "first" becomes a map only at the end of r.mapcalc run.
Well, it's opened as an output map prior to reading any input; but output
maps only become visible (or, if they already exist, the changes only
become visible) when they are closed.

An "identifier" is treated as an input map if and only if it hasn't
previously occurred on the left-hand side of an "=" anywhere in the input
expression(s). If it has so occurred, then it's treated as a variable,
regardless of whether any map with that name already exists, and
regardless of whether the assignment occurs at the top level (creating an
output map) or nested within an expression (e.g. as an argument to
eval()).

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2770#comment:3&gt;
GRASS GIS <https://grass.osgeo.org>

#2770: r.mapcalc reports syntax error for valid script but no error for separate
expressions
--------------------------+-------------------------
  Reporter: marisn | Owner: grass-dev@…
      Type: defect | Status: closed
  Priority: normal | Milestone: 7.0.4
Component: Raster | Version: svn-trunk
Resolution: fixed | Keywords: r.mapcalc
       CPU: Unspecified | Platform: Unspecified
--------------------------+-------------------------
Changes (by marisn):

* status: new => closed
* resolution: => fixed

Comment:

Probably documentation needs even more improvements, but at least part of
explanations have been moved to the manual (r68268 and r68269).

Closing as "fixed" as the main issue was in the documentation and has been
fixed there.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2770#comment:6&gt;
GRASS GIS <https://grass.osgeo.org>