Syntax of numeric constants

The Fortran standard dated 2023-12-18 seems to prevent a negative integer being a literal constant. R605 offers 6 possibilities of which the only relevant one is int-literal-constant. That is defined in R708, which does not allow the sign. R707 does, but that defines signed-int-literal-constant, not mentioned in R605. Is there a bug in the standard or have I missed something? Perhaps R707 and R708 should say this in F202Y:

int-literal-constant is [sign]unsigned-int-literal-constant

unsigned-int-literal-constant is digit-string[_kind-param]

There is a similar but more complicated problem with a real literal constant.

1 Like

If I understand it correctly, Fortran has defined literal constants without sign for half an eternity. This is a very explicit choice, not a mistake. I am sure @sblionel can elaborate on that. Unfortunately, a quick search did not bring up any reference that discusses this.

1 Like

Indeed I can elaborate, and did. Doctor Fortran in "Order! Order!" - Doctor Fortran Don’t ask me why, though - it’s way before my time. All I can suggest is that it was a choice that was made and there was no good reason to change it. I agree it is inconsistent with most other languages, but it most cases is invisible.

2 Likes

Ah, that is where I know it from :slight_smile:

Interesting, I’ve been programming Fortran for a long time and never realized this restriction existed. Does this mean something like

integer, parameter :: i1 = -42

evaluates to 42 or is this just (as I would expect it to be) a standard assignment.

Also, what about enumerations since I assume they mimic C integer rules.

enum, bind(c)
    enumerator :: i1=-1, i2, i3, i4
end enum

As an aside I really wish the standards folks would consider making the bind(c) requirement on enums optional. Most of my uses for enum have nothing to do with C interop.

It sets i1 to -42, just as

integer, parameter :: i1 = (-1) * 42

would. If it did not, people would have complained.

But something like

If (i1 /= -42) Then

would be a problem (yes ? no?)

Is

If (i1 /= -(42)) Then

a problem :wink: ? The RHS is evaluated to -42 at run time, so all good.

Yes, I knew that it does. my question is why are we having this discussion. The OPs opening statement said that the standard prohibited negative integer literal constants. So does it or doesn’t it. I’ve never seen a case where negative integer constants were prohibited but there is apparently some Language Lawyer language in the standard that implies that it does. If that’s the case I would consider that an error in the standard and should either be removed or further clarified.

Negative integer constants are fine. The language doesn’t call them “literal” constants, but you can treat them as such for MOST purposes.

I do see that I was perhaps a bit loose saying that Fortran doesn’t permit consecutive operators. I should have clarified this as being limited to Level-2 expressions (the arithmetic operators - I just edited the post to say this). @rwmsu 's example of:
If (i1 /= -42)
is OK. /= is a rel-op and a Level-4 expression is:

[level-3-expr rel-op] level-3-expr

-42 is a level-3-expr (also level-2-expr).

I think the key here is that literal constants don’t appear in syntax rules outside of expressions - what you generally care about is constant expressions, which are much broader.

DATA statements in legacy codes are related to this issue. The following data statement is not allowed because -i is an expression, not a constant, and expressions are not allowed in data statements.

integer, parameter :: i=42
integer, save :: j
data j/-i/

The workaround is to define also the parameter mi=-i, and then use mi in the data statement. Of course, data j/-42/ is allowed, but I’m not sure why.

However, the modern equivalent

integer, parameter :: i = 42
integer, save :: j = -i

is allowed because this form allows initialization expressions.

I don’t know what the standard says or how it says it re. this topic but if it isn’t as clear a description as the following paragraph from Adams, et al, “The Fortran 2003 Handbook”, page 70 last paragraph (hard cover edition) then the standard sections need to be rewritten.

" A signed integer constant(R405) is an integer constant preceded by an optional sign, which is either + or -. Contrary to what might be expected from the terminology, a signed integer constant is not in general an integer constant. Signed integer constants are used only in a few places in the language. In most contexts, a sign followed by an integer constant parses as an operator and an unsigned integer constant rather than a signed integer constant. This distinction makes little difference in practice except in one special case: on machines where the most negative integer is larger in magnitude than the most positive one, overflow can result from trying to write a literal for the most negative integer in the obvious way"

Too bad there has been apparently little interest (I presume because of the passing of some of the original authors) in following up this book with a “Modern Fortran Handbook”. I see both the Fortran 2003 Handbook and its predecessor as very detailed synopses of the standard written by people who write with something other than their feet which is to me what parts of the standard read like. I particulary like the Rules and restrictions sections which itemized what you can and can’t do with particular language features.

Given @arjen’s and @sblionel’s points about literal constants being signless, shouldn’t “mantissa” also be signless for consistency so that 13.7.2.3.2 paragraph 3 could begin “The standard form of the input field is an IEEE exceptional specification, a hexadecimal-significand number, or consists of an optional sign followed by a mantissa optionally followed by an exponent. The form of the mantissa is a string of one or more digits optionally containing a decimal symbol…”. The natural place for that definition would be 7.4.3.2 near the definition of “significand”, because 3E4 has no significand according to R715 but it has mantissa 3 according to either the present 13.7.2.3.2 or the one suggested above.

It is.

Do not confuse forms acceptable for formatted input with the formal language syntax rules.