I have a C++ audio project that is a Score-Based Music System for offline computation and audio rendering. It is based on two distinct scores, that actually are text files, one that contains the DAG of the instrument and one with the parametric of that instrument. I implemented two distinct front-end compilers, namely the lexer and the parser to read them distinctly, and now I am writing a class that acts as linker between them while implementing a semantic analysis. It also contains a back-end part for the audio processing management but actually I do not have any audio processors stable implemented.
Let me provide you also an example to clear the implementation and expectation.
~
// instrument.txt
AudioSystem as;
SinOsc osc;
WriteSF writer;
osc -> writer;
// parameters.txt
double frequency_ = 100;
AudioSystem::as T = 1000;
AudioSystem::as SR = 48000;
SinOsc::osc frequency = sqrt(frequency_);
WriteSF::writer filename = “testOsc.wav”;
~
Assume that in the Back-End I have an oscillator generator called SinOsc that is registered in a Factory class, that has a parameter called frequency that is a double, and a SoundFiles writer class that has the parameter filename that is the string of the filename to be created. AudioSystem is the container of the processing and contains the time of the total duration, in this case 1 sec, and the sampling rate as variable, both double. Note: in this moment the compiler accepts double or strings as type. All parameters are in the form: TypeSpecifier Identifier = Expression;
Let's focus on the linking phase and the semantic analysis. I list all the errors that I would find in this stage and I am able to categorize them in four distinct categories. Moreover, let's give a name to these classes: Vocabulary is the register in which during the parsing of the score lke instrument.txt each AudioProcessor plus AudioSystem registers their parameters, like frequency for SinOsc. ScoreSemAnalyzer is the class that receives the AST from the parser of the scores like parameters.txt . The categories are:
1. Errors that can find ScoreSemAnalyzer alone.
2. Errors that need communication from SSA to ExpressionEvaluator (there is a list of function, like sin, osc or sqrt, that can be provided to the user and are effectively usable in ExpressionEvaluator, that is the responsible to evaluate such kind of expressions and it is called by Vocabulary to resolve them).
3. Errors that need communication from Vocabulary to SSA (a parameter needs to be initialized but it is not found in the parameters' score).
4. Errors that need communication from ScoreSemAnalyzer to Vocabulary (type checking: SSA needs to from Vocabulary the type of frequency of SinOsc).
In the actual logic, Errors of kind 1 and 2 can be processed immediately, "at compile time", because to be solved they do not need the knowledge of Vocabulary content. Errors of type 3 and 4 must processed at linking time, while providing communication between SSA and Vocabulary. 
Let's focus on Errors of type 1. In my opinion they are:
a. Name Duplicate
double frequency = 440;
double frequency = 880;
All variables are immutable, so the compiler can not resolve this situation because the second declaration contains the exact pair TypeSpecifier and Identifier of the first one.
b. Name Collision
double frequency = 440;
SinOsc::osc1 frequency = 880;
SinOsc::osc2 frequency = frequency;
The LHS of these declaration are fine, however the RHS of the third one creates a name collision because the compiler can not resolve the Initializer.
Question: At this stage, what can be a convenient data structure that SSA must hold to solve these two errors? Note: the structure of the AST is:
Program
	Declaration
		TypeSpecifier
			BaseType
			[Qualifier]
		Declarator
			Identifier
		Initializer
			[Literal] or [Expression]
			[SubExpression]