Compiling DMD parser?
Markus Koskimies
markus at reaaliaika.net
Tue Jul 15 01:44:25 PDT 2008
On Mon, 14 Jul 2008 04:07:00 +0000, Markus Koskimies wrote:
>> actually dparser is not 1.014 anymore. it's somewhat 1.024ish the
>> parsing ability has been improved a lot, it can parse itself, and some
>> ctfes.
>> 700 or so cases from dstress fail.
>
> :o
>
> I fetched the sources (I tried to select the latest ones), and attached
> that DParser to my own code.
Jihuu! Now it works!
I wrote a somewhat general purpose AST walker. It can be inherited and
modified for different purposes. As an example, I made a class for
scanning unused local variables:
class UnusedScan : ASTWalk
{
/* To track down variable usage from nested functions, the
* variable reference table is global.
*/
bool[VarDeclaration] referenced;
/* Frame holds list of local variable definitions */
class Frame { VarDeclaration[] vars; }
Stack!(Frame) frames;
//-------------------------------------------------------------------------
// Whenever we meet a new variable frame, push it. When popping it
out,
// we check, if the variable was referenced.
//-------------------------------------------------------------------------
void push()
{
frames.push( new Frame() );
}
void pop()
{
Frame frame = frames.pop();
foreach(VarDeclaration var; frame.vars)
{
if(referenced[var]) continue;
writefln("%s: Unused variable: %s",
var.loc.toString(),
var.toString()
);
}
}
//-------------------------------------------------------------------------
// Constructor
//-------------------------------------------------------------------------
this()
{
frames = new Stack!(Frame)();
}
//-------------------------------------------------------------------------
// Whenever we meet a function, class or similar, make a new frame.
// After scanning, check if there were unreferenced variables.
//-------------------------------------------------------------------------
override void walk(Module m)
{
push(); super.walk(m); pop();
}
override void walk(ClassDeclaration d)
{
push(); super.walk(d); pop();
}
override void walk(FuncDeclaration f)
{
push(); super.walk(f); pop();
}
//-------------------------------------------------------------------------
// For every var declaration, put it to frame.
//-------------------------------------------------------------------------
override void walk(VarDeclaration var)
{
referenced[var] = false;
frames.top().vars ~= var;
}
//-------------------------------------------------------------------------
// When var is used, mark it to frame.
//-------------------------------------------------------------------------
override void walk(VarExp var)
{
referenced[cast(VarDeclaration)var.var] = true;
}
}
---
Then I tested it against a small D program:
import std.stdio;
void main()
{
int a, b;
int unused;
// a is used inside expression
writefln("%d", 23+a);
// b is used from local function
int f1() { int f2() { return b; } return f2(); }
// unused is shadowed; still, the main unused should remain
// not referred.
void f3() { int unused; unused = 1; }
return;
}
---
And it reports:
PASS 1: Building parse tree...
semantic1 done
semantic2 done
semantic3 done 0
PASS 2: Walking parse tree...
UnusedLocal1.d(8): Unused variable: unused
...Just as it should do :D
I'll put the full sources available somewhere (to my home pages, at
least), and continue developing walking & warning thing.
Davidl, do you want the sources for your repository?
More information about the Digitalmars-d
mailing list