Opened 9 years ago
Closed 9 years ago
#2770 closed defect (fixed)
r.mapcalc reports syntax error for valid script but no error for separate expressions
Reported by: | marisn | Owned by: | |
---|---|---|---|
Priority: | normal | Milestone: | 7.0.4 |
Component: | Raster | Version: | svn-trunk |
Keywords: | r.mapcalc | Cc: | |
CPU: | Unspecified | Platform: | Unspecified |
Description
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%
Change History (6)
comment:1 by , 9 years ago
follow-up: 3 comment:2 by , 9 years ago
Milestone: | → 7.0.3 |
---|
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).
comment:3 by , 9 years ago
Replying to 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()).
comment:6 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Replying to marisn:
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.