where _block_label is a simple rule to alias $.identifier to $.block_label. Similar optional items are present in other block statements. The unit tests also contain examples like:
cond1: IF (y < 0) THEN
y = 9
ELSE IF (x > 0) THEN cond1
r = 9
IF (arg(1:1)) THEN
r = 0
ELSE
n = 0
END IF
ELSE cond1
y = 10
END IF cond1
With some minor additions to make it a proper subroutine which can be compiled, I see that gfortran as well as ifx do not complain. But I could not find anything about this extension. Does anybody know something about this extension?
It looks like I looked at the only rule, where the construct name (block label) is not allowed by the grammar (i.e. after if (…) then), but accepted by the treesitter grammar (but not by compilers!). To include this in the treesitter grammar is fine, as this should also accept incomplete or slightly incorrect code as best as possible.
The code uses an if-construct-name, which is discussed in the Fortran 2018 standard, section 11.1.8.1 Purpose and form of the IF construct:
If the if-then-stmt of an if-construct specifies an if-construct-name, the corresponding end-if stmt shall specify the same if-construct-name. If the if-then-stmt of an if-construct does not specify an if-construct-name, the corresponding end-if-stmt shall not specify an if-construct-name. If an else-if stmt or else-stmt specifies an if-construct-name, the corresponding if-then-stmt shall specify the same if-construct-name.
ChatGPT 5.2 says this feature was introduced in Fortran 90.
Yes, you’re correct that block_label strictly isn’t allowed in that context. The 2023 standard says that if-construct-name is only allowed after else if (...) then, else, and end if, but not if (...) then (R1136-1140).
But as you note, tree-sitter grammars should parse all valid code and not necessarily try to reject invalid code. In fact, sometimes accepting invalid code makes it easier to autocomplete valid code or apply fixes, etc.
I have to admit that I did not know about the possibility of intermediate label after then, case (…)and other such block statements. My thumb of rule was, if you need construct names (block labels) for clarity, it is time to refactor. So I do not use them.
Anyway I was just not sufficiently careful and unlucky enough to check the only(?) exception.
Here is another related label question. Is this really valid
double_loop: do 400, i=1,10
inner: do 500, j=1,10
500 enddo inner
400 enddo double_loop
It looks a bit wild. Has this ever been used? And why is it mentioned and allowed in the standard:
R1120 do-stmt is nonlabel-do-stmt
or label-do-stmt
R1121 label-do-stmt is [ do-construct-name : ] DO label [ loop-control ]
R1122 nonlabel-do-stmt is [ do-construct-name : ] DO [ loop-control ]