C:\tests>rexx -e "arg(0)~x"
1 *-* arg(0)~x
Error 40 running INSTORE line 1: Incorrect call to routine.
Error 40.14: ARG argument 1 must be positive; found "0".
C:\tests>rexx -e "arg (0)~x"
1 *-* arg (0)~x
Error 38 running INSTORE line 1: Invalid template or pattern.
Error 38.1: Incorrect PARSE template detected at "~".
Anonymous
By the rules of Rexx instruction parsing, putting an ARG() function call at the start of the clause results in this being an ARG instruction, not a call to the ARG() bif. Use
(arg(0)~x)
to keep this from happening. See section 2.0 Keyword instructions in the Rexx reference for documentation.
Thanks, Rick. Maybe I didn't make myself clear enough. I know that "ARG whatever" is an ARG instruction. This is precisely the reason why both instructions above should produce the same error, not two different ones. The first error message is wrong. That's why I tried to summarize in the title.
You're right, I misread what you were trying to report. I've had to deal with the ARG(0) is not a function call question more than once in the past.
That said, it is still an invalid problem. "arg(0)~x" matches the pattern of a message instrunction, which is checked before keyword instructions. The presence of the "~x" triggers the leading part to be treated as an expression to which the message X is sent. This is the correct error message for that situation.
Thanks again. I was not aware about this precedence. Is it documented anywhere? Indeed, rexxref chapter 2 says
Most probably, the docs should be updated to reflect this.
Section 1.12 defines the different types of instructions and the rules for
determining what sort of instruction it is.
On Mon, Dec 15, 2025 at 4:18 PM Josep Maria Blasco jmblasc2@users.sourceforge.net wrote:
Related
Bugs:
#2043I asked if such a documentation exists.
https://chatgpt.com/share/69408365-0404-8007-a813-bc0429a3f96d
I'm not sure that the conclusion is pertinent, because there is this assumption: the order of description in the doc implies the same order when parsing...
And the conclusion based on thi assumption is:
The key rule in ooRexx’s parser is the instruction type hierarchy:
* Message instructions (including message send via the ~ operator)
* Keyword instructions (e.g. ARG, PARSE, IF, etc.)
* Command instructions
Ok, thanks Rick and Jean Louis. Now I understand. It's the form of the instruction which determines how it is parsed, rexxref is very clear about it. But ooRexx breaks the old, Classic Rexx, rule: if token1 is a symbol and and token2 is an equal sign, it's an assignment; otherwise, if token1 is a keyword, it's a keyword instruction; otherwise, it's a command.
The form is certainly unambiguous, and therefore the rule is clear. But at the same time, this is a big departure from Classic Rexx, because you may need a lot of lookahead to decide what is the nature of an instruction. In Classic Rexx, you could do that with only two tokens.
That piqued my interest :-)
Code review of instructionParser.cpp
LanguageParser::nextInstruction
Try 1) or else 2) or else 3) etc...
There is indeed a lot of lookahead at point 4)
// get the first token of the clause
RexxToken *first = nextReal();
1)
// a :: at the start of a clause is a directive, which ends this execution block.
if (first->isType(TOKEN_DCOLON)) ...
RexxToken *second = nextToken();
2)
// First check is for a label.
if (first->isSymbolOrLiteral() && second->isType(TOKEN_COLON)) ...
3)
// this is potentially an assignment of the form "symbol = expr"
if (first->isSymbol()) ... // test if 2nd is == or = or like +=
4)
// reset to the beginning and parse off the first term (which could be a
// message send)
firstToken();
RexxInternalObject *term = parseMessageTerm();
// a lot depends on the nature of the second token
second = nextToken();
// some sort of recognizable message term? Need to check for the
// special cases.
if (term != OREF_NULL) ...
5)
// ok, none of the special cases passed....now start the keyword processing
// reset again and get the first token
firstToken();
first = nextToken();
// see if we can get an instruction keyword match from the first token
InstructionKeyword keyword = first->keyword();
if (keyword != KEYWORD_NONE) ... // test all the instruction keywords
6)
// does not begin with a recognized keyword...this is a "command" instruction.
else ...