Difference between syntax and semantic error in programming languages When compilers generate errors for a specific programming language, there's distinction between syntax &amp; semantic errors. E.g. ) + f 3 has ill-formed syntax, but type checking is considered as part of semantic analysis.

My intuition tells me that, by setting more constraints on the language syntax, some semantic errors can become syntax errors. And my question is if there are any intrinsic differences between syntax and semantics? Or are they just checking performed on different levels, for example syntax checking is a rather local checking while semantic checking is global? Is there anything fundamental that makes semantics checking different from syntax checking? Is it possible to embed all semantic checking within syntax? Are there any theories related to these questions?

It may also be the case that my intuition is wrong - if that's the case, please also explain to me why that is wrong.
In the strictest sense, there is no real difference between syntax errors and semantics errors, at least as far as language theory is concerned: the only salient difference is the complexity of the automaton required to recognize that language, with, e.g.


Context-free languages only requiring pushdown automata (PDA)
General recursive languages requiring full Turing machines (TM)


If every "syntactic task" merely required pushdown automata and every "semantic task" something more, then the matter would be settled, but unfortunately there are many tasks that are associated with programming language syntax that cannot be handled by PDA alone, and conversely, some semantic tasks which seem to require only weak computation power. Still, the distinction provides some intuition.

Pragmatically, compilers are designed in phases, which makes managing the task of generating executable code manageable. I particularly like this diagram from the Compcert website.



Typically, the first 1-3 phases turn what is essentially a stream of bytes or tokens into something more naturally seen as a tree structure. Everything before the tree creation will be labelled as "syntax" and everything after as "semantics".

In C, the syntactic phases are typically tokenization, macro expansion and parsing, everything after that will be semantics. Again, opinions may differ, since there is no accepted formal distinction.



I think there's a larger discussion to be had about how to distinguish syntactic notions from semantic notions in the field of formal logic, but I'm not sure I feel qualified to have it.