CD Notes
Master semantic rules: rule specification, constraint checking, type rules, scope rules, dependency resolution, practical implementation in attribute grammar frameworks for modern language compilers.
What Are Semantic Rules?
Semantic rules are formalized specifications of language semantics. They define:
- Type constraints
- Scope rules
- Attribute computations
- Validity conditions
Rule Structure
Semantic Rule
Condition: When does rule apply?
Constraints: What must be true?
Action: What to compute/check?
Error: What if violated?
Example (type checking)
Production: E → E₁ + E₂
Condition: E₁ and E₂ are numeric types
Constraint: type(E₁) == type(E₂) or both numeric
Action: E.type := common_type(E₁, E₂)
Error: "Type mismatch in +, cannot add {type(E₁)} and {type(E₂)}"
Common Semantic Rule Patterns
Type Rule Pattern
| Production | statement |
| Syntax | var := expr |
| Rule | type(var) must be compatible with type(expr) |
| THEN | Assign value |
| ELSE | Type error |
Scope Rule Pattern
| Production | statement |
| Syntax | use identifier |
| Rule | Identifier must be defined in scope |
| THEN | Use identifier |
| ELSE | Undefined identifier error |
Constraint Rule Pattern
| Production | array_access |
| Syntax | array[index] |
| Rule | index must be integer; array must be array type |
| THEN | Result type is array element type |
| ELSE | Type error or index error |
Implementing Semantic Rules
Attribute Grammar Approach
Grammar with rules
E → E₁ + T {
Constraint: E₁.type == T.type
Action: E.type := E₁.type
Error if: E₁.type ≠ T.type
}
E → T {E.type := T.type}
T → ( E ) {T.type := E.type}
T → id {T.type := look_up(id).type}
Evaluation
1. Compute types bottom-up
2. Check constraints at each step
3. Report errors with locations
Rule Checking Code
def check_rules(parse_tree):
for node in post_order_traversal(parse_tree):
production = node.production
# Get semantic rules for this production
rules = get_semantic_rules(production)
for rule in rules:
# Check conditions
if rule.condition(node):
# Check constraints
if not rule.check_constraints(node):
report_error(rule.error_message, node)
node.is_error = True
continue
# Execute action
rule.action(node)Common Semantic Rules in Language Design
Declaration Rules
Rule D1 - Variable Declaration
No redefinition in same scope
int x; // OK
int x; // ERROR: redefinition
Rule D2 - Type Requirements
Abstract types cannot be instantiated
abstract class A { }
A obj = new A(); // ERROR
Rule D3 - Initialization
Variables may require initialization
const int x; // ERROR: uninitialized const
const int y = 5; // OK
Expression Rules
Rule E1 - Operator Compatibility
Operators defined for specific types
int + int → int ✓
int + string → ERROR ✗
string + string → string ✓
Rule E2 - Assignment Compatibility
RHS type must be assignable to LHS type
int x = 5.0; // float→int, OK if permitted
string s = 42; // ERROR: no implicit conversion
Rule E3 - Function Call
Argument count and types must match
void foo(int x);
foo(5); // OK
foo(5, 10); // ERROR: too many args
foo("hello"); // ERROR: wrong type
Control Flow Rules
Rule CF1 - Return
Must return value of correct type
int foo() { return 5; } // OK
int foo() { return "x"; } // ERROR
int foo() { } // ERROR: no return
Rule CF2 - Reachability
Dead code detection
if (true) { return 5; }
x = 10; // WARNING: unreachable
Rule CF3 - Break/Continue
Must be inside loop
while (...) { break; } // OK
if (...) { break; } // ERROR: outside loop
Practical Implementation
Multi-Pass Semantic Analysis
| Pass 1 | Collect declarations |
| Pass 2 | Check usage |
| Pass 3 | Generate code |
Error Accumulation
class SemanticAnalyzer:
def __init__(self):
self.errors = []
def analyze(self, tree):
self.check_all_rules(tree)
if self.errors:
self.report_errors()
return False
return True
def check_rule(self, condition, action, error_msg):
if not condition:
self.errors.append(error_msg)
return False
else:
action()
return TrueQuick Revision Notes
- Semantic rule: Formalized specification of language constraint
- Condition: When rule applies (production context)
- Constraint: What must be true
- Action: Computation or check to perform
- Error handling: Report violations with location context
- Multi-pass: Collect declarations, check usage, generate code
- Rule priority: Order of checking affects error messages
Interview Q&A
Q1: What's the difference between syntax rules and semantic rules?
A: Syntax rules define valid structure (grammar). Semantic rules define meaning/correctness: type compatibility, scope validity, constraint satisfaction. Parsing checks syntax; semantic analysis checks semantics.
Q2: How do you prioritize which semantic rules to check first?
A: Generally: 1) Scope rules (is name defined?), 2) Type rules (are types compatible?), 3) Constraints (other requirements). Scope errors prevent type checking; type errors prevent code generation.
Q3: Can you implement all semantic rules in the parser?
A: No. Parser handles syntax only. Semantic rules require symbol tables, type inference, scope analysis. Must be separate semantic analysis phase after parsing. Mixing them complicates both phases.
Q4: What happens when semantic rules conflict or are ambiguous?
A: Language specification must clarify. Examples: operator associativity (left vs right), type promotion (which types?), scope (lexical vs dynamic). Compiler must implement specification; ambiguity is language design flaw.
Q5: How do you handle optional or language-specific semantic rules?
A: Use configuration/flags. Different language modes (C89 vs C99 vs C++). Rules can be "strict" (error), "warning" (continue), "permissive" (ignore). Compiler configuration selects rule strictness.
Q6: Why are semantic rules important for compiler correctness?
A: Semantic rules formally specify what's valid/invalid. Without clear rules, compiler behavior is unpredictable. Rules enable: test case development, error consistency, language spec compliance, tool verification.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Semantic Rules: Defining Language Semantics in Compiler Construction.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Compiler Design topic.
Search Terms
compiler-design, compiler design, compiler, design, semantic, analysis, rules, semantic rules: defining language semantics in compiler construction
Related Compiler Design Topics