Note: this is exactly the same problem as in the syntax of Fortran (where it was evern more critical): Fortran had keywords for its instructions or some operators, and also allowed identifiers to have multiple letters; but whitespaces separators between them were optional (to save precious encoding size on punchcards...). This had a consequence: a very slow parser, very complex to write and maintain (even if the compiler produced a very fast program). Novel dialects of Fortran disallowed this practice of optional whitespaces between keywords and/or identifiers, forcing to use whitespaces everywhere it would create an ambiguity.
The Lua syntax is normally made to be parsed very esasily and efficiently with minimal code, so having to use rollbacks from a previous "shift" attempt to retry with a "reduce" was disallowed by design. This simplifies a lot the treatment of syntax error in the input, and requires simpler data structures if it does not have to maintain the possibility of rolling back.
As a consequence, we have a ";" in Lua, and we must use it everytime there's a possible ambiguity.
As well, Lua does not support "f(x=0)" because of currification, and then chosed to sacrifice the possibility of performing assignments in the middle of expressions.
C/C++/Java do not have currification, they still have ";" needed between statements but not always at end of them (if the statement is terminated by a "}" at end of a block), so they can have assignments in the middle of expressions (which can be statements by themselves like in Lua).
Lua could have chosen to use a keyword (like "void") to start a statement performing a function call without assigning its return value(s) in an assignment statement, this would also have solved the ambiguity of currified function calls. But it preferred to use ";" when needed (following the common pratice and because it was just simpler to type and read).
Lua also allowed parentheses around parameters of function to be discarded. But with currification it would have been even more problematic to disambiguite things without rolling back, if there was no ";" or "void" keyword before the next instruction. Still Lua is ambiguous about the parentheses surrounding the function parameters: it chooses to favor the "shift" action (and then parses the first opening parenthese after any leading subexpression, as meaning it marks a function call and not parentheses surrounding an _expression_ (the disambiguation is then needed when expressions are used in list of expressions for table initialisers or for fuinction parameters; Lua solved the problem by requiring a "," between expressions as as members an initializer list for a table, or expressions given as function parameters).