So my own ambiguity handling proposals have changed a couple times over the course of this thread. Some of your criticisms apply to the 10:14am version, but, not improved heuristic I posted at 11:08 :)
For reference, this is the version of prefixexp() that I'm working with atm. The error heuristic is 2+ function calls, one of which places its '(' at the start of a new line.
static void primaryexp (LexState *ls, expdesc *v) {
/* primaryexp ->
prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
FuncState *fs = ls->fs;
int line = ls->linenumber;
prefixexp(ls, v);
for (int funcalls=0,danger=0;;) {
switch (ls->t.token) {
case '.': { /* fieldsel */
fieldsel(ls, v);
break;
}
case '[': { /* `[' exp1 `]' */
expdesc key;
luaK_exp2anyregup(fs, v);
yindex(ls, &key);
luaK_indexed(fs, v, &key);
break;
}
case ':': { /* `:' NAME funcargs */
expdesc key;
luaX_next(ls);
checkname(ls, &key);
luaK_self(fs, v, &key);
funcargs(ls, v, line);
funcalls++;
break;
}
case '(': /* funcargs */
/* look for dangerous formatting, and maybe throw an error*/
if(ls->linenumber != ls->lastline) danger++;
if(danger && funcalls)
luaX_syntaxerror(ls, "dangerous formatting: function call followed by newline followed by '('.");
case TK_STRING: case '{': {
luaK_exp2nextreg(fs, v);
funcargs(ls, v, line);
funcalls++;
break;
}
default: return;
}
}
}