99import Foundation
1010
1111public class SemanticAnalyzer {
12- private let symbolTable = ScopedSymbolTable ( name : " global " , level : 1 )
12+ private var currentScope : ScopedSymbolTable ?
1313
1414 public init ( ) {
1515
1616 }
1717
1818 public func build( node: AST ) -> ScopedSymbolTable {
1919 visit ( node: node)
20- return symbolTable
20+ return ScopedSymbolTable ( name : " global " , level : 1 , enclosingScope : nil )
2121 }
2222
2323 private func visit( node: AST ) {
@@ -28,7 +28,11 @@ public class SemanticAnalyzer {
2828 }
2929 visit ( node: compoundStatement)
3030 case let . program( name: _, block: block) :
31+ let globalScope = ScopedSymbolTable ( name: " global " , level: 1 , enclosingScope: nil )
32+ currentScope = globalScope
3133 visit ( node: block)
34+ print ( globalScope)
35+ currentScope = nil
3236 case let . binaryOperation( left: left, operation: _, right: right) :
3337 visit ( node: left)
3438 visit ( node: right)
@@ -43,41 +47,57 @@ public class SemanticAnalyzer {
4347 case . noOp:
4448 break
4549 case let . variable( name) :
46- guard symbolTable. lookup ( name) != nil else {
50+ guard let scope = currentScope else {
51+ fatalError ( " Cannot access a variable outside a scope " )
52+ }
53+ guard scope. lookup ( name) != nil else {
4754 fatalError ( " Symbol(indetifier) not found ' \( name) ' " )
4855 }
4956 case let . variableDeclaration( name: variable, type: variableType) :
57+ guard let scope = currentScope else {
58+ fatalError ( " Cannot declare a variable outside a scope " )
59+ }
60+
5061 guard case let . variable( name) = variable, case let . type( type) = variableType else {
5162 fatalError ( " Invalid variable \( variable) or invalid type \( variableType) " )
5263 }
5364
54- guard symbolTable . lookup ( name) == nil else {
65+ guard scope . lookup ( name, currentScopeOnly : true ) == nil else {
5566 fatalError ( " Duplicate identifier ' \( name) ' found " )
5667 }
5768
58- guard let symbolType = symbolTable . lookup ( type. description) else {
69+ guard let symbolType = scope . lookup ( type. description) else {
5970 fatalError ( " Type not found ' \( type. description) ' " )
6071 }
6172
62- symbolTable . insert ( . variable( name: name, type: symbolType) )
73+ scope . insert ( . variable( name: name, type: symbolType) )
6374 case let . assignment( left: left, right: right) :
6475 visit ( node: right)
6576 visit ( node: left)
6677 case . type:
6778 break
68- case let . procedure( name: name, params: params, block: _) :
79+ case let . procedure( name: name, params: params, block: block) :
80+ let scope = ScopedSymbolTable ( name: name, level: ( currentScope? . level ?? 0 ) + 1 , enclosingScope: currentScope)
81+ currentScope = scope
82+
6983 var parameters : [ Symbol ] = [ ]
7084 for param in params {
7185 guard case let . param( name: name, type: . type( type) ) = param else {
7286 fatalError ( " Only built int type parameters supported in procedure, got \( param) " )
7387 }
74- guard let symbol = symbolTable . lookup ( type. description) else {
88+ guard let symbol = scope . lookup ( type. description) else {
7589 fatalError ( " Type not found ' \( type. description) ' " )
7690 }
77- parameters. append ( . variable( name: name, type: symbol) )
91+ let variable = Symbol . variable ( name: name, type: symbol)
92+ parameters. append ( variable)
93+ scope. insert ( variable)
7894 }
7995 let symbol = Symbol . procedure ( name: name, params: parameters)
80- symbolTable. insert ( symbol)
96+ scope. insert ( symbol)
97+
98+ visit ( node: block)
99+ print ( scope)
100+ currentScope = currentScope? . enclosingScope
81101 case . param:
82102 break
83103 }
0 commit comments