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