optional · CSS study notes
II.4 Components of a Programming Language
⬆️ P-I.II. Programming Fundamentals · Question Bank · Chapter II (2016–2026)
🧠
Remember: Tokens are words; syntax is grammar; semantics is meaning.
Start here — what you should be able to do
- Classify identifiers, literals, keywords, operators and punctuation.
- Separate syntax, static semantic checks and logic errors.
- Read a simple grammar rule and explain precedence.
Reading order: foundation checks → full notes and examples → exam traps → self-test without notes → past-paper answers. All sections below remain part of the topic; code examples are kept in full.
Foundation checks
Three different kinds of mistake
| Kind | Example | What it means |
|---|---|---|
| Syntax | int x = ; | The token arrangement violates the grammar. |
| Static semantic/type error | Using an undeclared variable | The form may parse, but names/types are invalid. |
| Logic error | Adding when multiplication was required | Legal code solves the wrong problem. |
Do not equate all semantics with logic errors: compilers check many semantic constraints. Comments and whitespace: normally carry no runtime operation, but they separate tokens; removing them carelessly can change the program. Grammar: BNF defines valid forms; a grammar is not automatically unambiguous.
1. Core Concepts
- Syntax: the formal rules governing how valid statements are constructed (the grammar of the language). A compiler checks syntax first — a syntax error stops compilation entirely.
- Semantics: the meaning/behavior associated with syntactically valid statements. Static semantic rules include name and type checks; dynamic semantics describes execution. Logic errors are a separate failure to solve the intended problem.
- Tokens: the smallest meaningful units the compiler recognizes — every program is broken into tokens before parsing. Categories:
- Keywords: reserved words with fixed meaning (
int,if,return,class) — cannot be redefined or used as identifiers - Identifiers: programmer-defined names for variables, functions, classes, etc.
- Literals/Constants: fixed values written directly (
42,3.14,'x',"text",true) - Operators: symbols performing operations (arithmetic, relational, logical, bitwise, assignment)
- Punctuators/Separators: symbols that structure code without performing computation (
;,,,{ },( ),[ ])
- Keywords: reserved words with fixed meaning (
- Comments: non-executable annotations for humans; replaced during translation, with token separation preserved
2. Syntax vs Semantics — Example
int x = 5 / 0;
- Syntactically valid — this line parses fine, follows all grammar rules
- Semantically problematic — division by zero is undefined behavior/runtime error, even though the syntax is correct
Contrast with:
int x = 5 0;
- This is a syntax error — missing an operator between
5and0; the compiler rejects it before it can even consider meaning
3. Grammar and Rules
- Every language defines its syntax formally, often using grammar notations like BNF (Backus-Naur Form), which the compiler's parser uses to validate structure
- A statement must be well-formed (follows the grammar) to compile; it must additionally be meaningful in context (e.g. correct types) to behave as intended
4. 💻 Code Examples: C & C++
The syntax-vs-semantics example from above, made runnable, plus tokens labelled:
C:
#include <stdio.h>
int main(void) {
int x = 5 / 2; /* syntactically valid; semantics: integer division -> 2 */
// int y = 5 0; // would be a SYNTAX error -- missing operator, won't compile
printf("%d\n", x); // tokens: printf ( "%d\n" , x ) ;
return 0;
}
C++:
#include <iostream>
using namespace std;
int main() {
int x = 5 / 2; // syntactically valid; semantics: integer division -> 2
// int y = 5 0; // would be a SYNTAX error
cout << x << endl; // tokens: cout << x << endl ;
return 0;
}
int,returnare keywords;x,mainare identifiers;5,2are literals;/,<<are operators;;,(,)are punctuators — every one of these is a token
5. MCQ Traps
- Error distinction: syntax and static semantic errors can be diagnosed during translation; logic errors are defects in the intended algorithm.
- Keywords are part of the language's fixed vocabulary; identifiers are chosen by the programmer — a keyword can never double as an identifier
- Punctuators (like
;or{}) are tokens too, but they don't perform operations the way operators do - Comments carry no runtime operation; they are replaced during translation and can separate tokens. Do not remove token-separating comments without whitespace.
6. ✅ Self-Test Questions (with Answers)
Q1. Differentiate syntax from semantics with one example each.
Answer
- Syntax: rules for arranging tokens into valid statements; the parser checks these rules.
- Static semantics: names, types and other contextual constraints; many are checked by the compiler.
- Dynamic meaning: what valid code does during execution.
- Logic error: valid code fails the programmer's intended task; testing and tracing are needed.
- Example: a missing semicolon is syntax; an undeclared name is a static semantic error; using the wrong formula is logic.
// SYNTAX ERROR -- breaks the grammar; the compiler rejects it
// int x = 5 0; // no operator between 5 and 0 -> will not compile
// if (a > b // missing ) and ; -> will not compile
// SEMANTIC / LOGIC ERROR -- grammatically perfect, meaning is wrong
int length = 5, width = 3;
int area = length + width; // legal C++, but the formula should be *
cout << area; // prints 8; the correct area is 15
| Aspect | Syntax | Semantics |
|---|---|---|
| Concerns | Form / structure of statements | Meaning / behaviour of statements |
| Checked by | Parser during translation | Static semantic checks by compiler; intended behaviour by reasoning/testing |
| On violation | Syntax diagnostic | May be a type diagnostic, invalid runtime operation, or logic defect |
| Typical error | Missing ; , unbalanced braces | Wrong operator or formula, wrong condition |
MCQ trap: if (x = 5) is semantically wrong, not syntactically — = is a legal assignment whose result (5) is non-zero, so the condition is always true; the intended test was ==. Similarly int x = 5 / 2; is valid syntax whose semantics give 2, because integer division truncates the fractional part.
Q2. List the five categories of tokens found in a typical high-level language.
Answer — key points
- A token is the smallest unit of a program meaningful to the compiler, produced by the lexical analyser as it scans the source text.
- Every C/C++ program reduces to a stream drawn from exactly five categories:
| # | Category | Description | Examples |
|---|---|---|---|
| 1 | Keywords | Reserved words with fixed meaning; cannot be redefined | int, if, while, return, class, void |
| 2 | Identifiers | Programmer-chosen names for variables, functions, classes | total, main, studentAge, _count |
| 3 | Constants / Literals | Fixed values written directly in the code | 42, 3.14, 'x', "text", true |
| 4 | Operators | Symbols that perform an operation on operands | • - * / % == && ! << ++ |
| 5 | Punctuators / Separators | Structure the code without computing anything | ; , ( ) { } [ ] # |
if (count == 10) total += price;
// if -> keyword
// count, total, price -> identifiers
// ==, += -> operators
// 10 -> literal
// ( ) ; -> punctuators
// 11 tokens in total
- Lexical detail: comments/whitespace generally carry no runtime operation, but can separate tokens; removing them carelessly can change tokenisation.
Q3. Why is 5 0; (missing operator) a syntax error while 5/0; is not?
Answer
5 0;fails the grammar because the literals have no operator between them.5 / 0;has a valid expression form, but integer division by zero has undefined behaviour if evaluated.- A compiler may diagnose a constant zero divisor; do not promise that compilation succeeds or that execution must crash.
- Key distinction: grammatical validity does not establish a valid operation or correct algorithm.
| Aspect | 5 0; | 5 / 0; |
|---|---|---|
| Fault type | Syntax (grammar) error | Semantic / run-time error |
| Detected at | Compile time, by the parser | Run time (integer division by zero) |
| Translation outcome | Syntax diagnostic | Depends on context/diagnostics; evaluation is not valid |
| Grammar rule matched? | None exists | expression -> literal / literal |
// int a = 5 0; // SYNTAX ERROR: "expected ';' before numeric constant"
int b = 5 / 0; // compiles; crashes at run time (UB)
int z = 0;
int c = 5 / z; // also compiles -- the compiler cannot always even warn
double d = 5.0 / 0.0; // NO crash: prints inf (IEEE-754 floating point)
- MCQ trap: integer division by zero is undefined behaviour and normally aborts the program, but floating-point division by zero is well defined under IEEE-754 and yields
inf,-infornan— so5/0and5.0/0.0behave completely differently. - A modern compiler may warn about a literal
5/0, but a warning is not a syntax error and compilation still succeeds.
Q4. What role does a formal grammar (e.g. BNF) play in defining a language's syntax?
Answer — key points
- A formal grammar gives a language's syntax a precise, mathematical definition instead of an informal English description, removing all ambiguity about what counts as a legal program.
- BNF (Backus–Naur Form) — devised for ALGOL 60 by John Backus and Peter Naur — expresses the grammar as a set of production rules over non-terminals (
\<expression>) and terminals (literal symbols such as+or;). - The compiler's parser (syntax analyser) uses these rules directly to check whether the token stream from the lexical analyser can be derived from the start symbol
- if it can, a parse tree is built, and if it cannot, a syntax error is reported.
<statement> ::= <if-stmt> | <assignment> | <block>
<if-stmt> ::= "if" "(" <expression> ")" <statement>
| "if" "(" <expression> ")" <statement> "else" <statement>
<assignment>::= <identifier> "=" <expression> ";"
<expression>::= <term> | <expression> "+" <term>
<term> ::= <factor> | <term> "*" <factor>
Its main uses are:
- Unambiguous specification — the language standard says exactly what is legal, so independent compiler vendors agree
- Automatic parser generation — tools such as yacc/bison and ANTLR build a parser straight from the grammar
- Encoding precedence and associativity — note above how
\<term>sits beneath\<expression>, which is why*binds tighter than+in2 + 3 * 4(result 14, not 20) - Extensions — EBNF adds
{ }for repetition,[ ]for optional parts; syntax (railroad) diagrams are the graphical equivalent - MCQ trap: a grammar defines syntax only, never semantics —
x = 5 / 0;is perfectly derivable from the grammar above, so the parser accepts it; the failure appears at run time. - Meaning is specified separately (by attribute grammars, denotational semantics or prose in the standard), which is why a compiler catches missing semicolons but not wrong formulas.
Recall check and coverage
- Explain the three learning outcomes at the top without looking.
- Reproduce one example or trace and test a boundary case.
- Answer each self-test, then compare with the key.
- Attempt each recorded past-paper task on this page.
Recorded written references: No direct written record in this topic's current notes. These concepts support the chapter's programming questions.
Evidence limit: this page preserves the question records found in your Notion notes. Disputed labels and questions not checked against original PDFs remain flagged in the Question Bank; this is not a claim of exhaustive original-paper verification.