Parsing answers one fundamental question:
Is this program structurally correct according to the grammar?
Semantic analysis answers a different one:
Does this program actually make sense?
A program can be grammatically valid and still be meaningless. For example:
var x = 10;
var x = 15; // Parser: seems okay to me...
However, the above code redeclares the same variable in the same scope, which violates the language rules. This is where semantic analysis comes into the picture.
var x = 10;
var x = 15; // ERROR: x has already been declared!
In this phase, we operate on the AST produced by the parser and perform checks related to names, scopes, and declarations.
To keep the compiler simple and focused, this implementation performs only name and scope related semantic checks for now. Specifically:
Undeclared Variable Access
Using a variable before it has been declared should fail.
Redeclaration in the Same Scope
Declaring var x; var x; in the same scope is illegal.
Scope Visibility Rules
A variable declared inside a block (for example, an if statement) is not visible outside that block.
Duplicate Parameters
A function cannot have multiple parameters with the same name.
Valid return Placement
A return statement is only allowed inside a function body. Using it at global scope is an error.