2024-06-06 23:10:38 +03:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
2023-12-31 12:54:49 +03:00
|
|
|
|
|
|
|
|
|
|
namespace PascalABCCompiler.SyntaxTree
|
|
|
|
|
|
{
|
|
|
|
|
|
public class BindCollectLightSymInfo : CollectLightSymInfoVisitor
|
|
|
|
|
|
{
|
|
|
|
|
|
protected override AbstractScopeCreator scopeCreator => _scopeCreator;
|
|
|
|
|
|
|
|
|
|
|
|
private CachingScopeCreator _scopeCreator = new CachingScopeCreator();
|
|
|
|
|
|
|
|
|
|
|
|
public BindCollectLightSymInfo(compilation_unit root) : base(root)
|
|
|
|
|
|
{
|
|
|
|
|
|
Current = Root;
|
|
|
|
|
|
visit(root);
|
2024-06-06 23:10:38 +03:00
|
|
|
|
Current = null;
|
2023-12-31 12:54:49 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-06 23:10:38 +03:00
|
|
|
|
public BindResult bind(ident node)
|
2023-12-31 12:54:49 +03:00
|
|
|
|
{
|
2024-06-06 23:10:38 +03:00
|
|
|
|
|
|
|
|
|
|
Current = null;
|
2023-12-31 12:54:49 +03:00
|
|
|
|
syntax_tree_node cur_node = node;
|
2024-06-06 23:10:38 +03:00
|
|
|
|
var path = new Queue<ScopeSyntax>();
|
2023-12-31 12:54:49 +03:00
|
|
|
|
while (cur_node != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
if (AbstractScopeCreator.IsScopeCreator(cur_node))
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
var cur_scope = scopeCreator.GetScope(cur_node);
|
2024-06-06 23:10:38 +03:00
|
|
|
|
path.Enqueue(cur_scope);
|
2023-12-31 12:54:49 +03:00
|
|
|
|
var prev_scope = Current;
|
|
|
|
|
|
|
|
|
|
|
|
if (prev_scope != null)
|
|
|
|
|
|
prev_scope.Parent = cur_scope;
|
|
|
|
|
|
|
|
|
|
|
|
Current = cur_scope;
|
|
|
|
|
|
if (cur_scope.Parent == null && !(Current is GlobalScopeSyntax))
|
|
|
|
|
|
{
|
|
|
|
|
|
cur_node.visit(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
var res = Current.bind(node);
|
2024-06-06 23:10:38 +03:00
|
|
|
|
if (res != null) return new BindResult(res, path.ToList());
|
2023-12-31 12:54:49 +03:00
|
|
|
|
}
|
|
|
|
|
|
cur_node = cur_node.Parent;
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void Enter(syntax_tree_node st)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (AbstractScopeCreator.IsScopeCreator(st))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (st is procedure_definition pd)
|
|
|
|
|
|
{
|
|
|
|
|
|
var attr = pd.proc_header.class_keyword ? SymbolAttributes.class_attr : 0;
|
|
|
|
|
|
var name = pd.proc_header?.name?.meth_name;
|
|
|
|
|
|
if (name != null)
|
|
|
|
|
|
if (pd.proc_header is function_header)
|
|
|
|
|
|
Current.AddSymbol(name, SymKind.funcname, null, attr);
|
|
|
|
|
|
else
|
|
|
|
|
|
Current.AddSymbol(name, SymKind.procname, null, attr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
visitNode = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void PreExitScope(syntax_tree_node st){}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|