Example fragment of C:
int i; float j;
float f (int i) {int k; float r; k= i*j; r= k; return r;}
After lexical analysis - corresponding lexemes and namelist:
(int, -) int (id, -> i in namelist) float (;, -) f (float, -) i (id, -> j in namelist) j (;, -) k etc. r
After syntactic analysis - corresponding parse tree:
program
|
decl--------var
| [int, *->i]
|
decl--------var
| [float, *->j]
|
decl--------func--------+----------------------+
[float, *->f] decl-------param exp--------[=]
| [int,*->i] | [*->k] [*]
| | [*->i] [*->j]
decl-------var |
| [int,*->k] exp--------[=]
| | [*->r] [*->k]
decl-------var |
[float,*->r] return-----[*->r]
(as in lexemes, identifiers are pointers to entries in the namelist.)
After semantic analysis - enhanced parse tree:
program[2 vars]
|
decl--func----+
[*->f] exp--------[I,=]
| [F,->I]
| [I,*->k] [F,*]
| [I->F]
| [I,*->i] [F,*->j]
|
exp--------[F,=]
| [I->F]
| [F,*->r] [I,*->k]
|
return-----[F,*->r]
(identifiers have become pointers to property entries.)
(F short for float, I for int)
Possible dictionary for example C program:
int [type | int] <--I
float [type | float] <--F
f [func | global | ? | 1 param | 2 vars | *->F]
i [param | local | 1 | *->I]
[var | global | 1 | *->I]
j [var | global | 2 | *->F]
k [var | local | 1 | *->I]
r [var | local | 2 | *->F]