view src/expression/expression_apd.d @ 1:4a9dcbd9e54f

-files of 0.13 beta -fixes so that it now compiles with the current dmd version
author marton@basel.hu
date Tue, 05 Apr 2011 20:44:01 +0200
parents
children
line wrap: on
line source

// Written in the D programming language

/*
 *  This file has been automatically generated by APaGeD v0.4.2 beta - Attributed Parser Generator for D.
 *
 *  Sections generated from custom input are marked as "generated code" and
 *  are subject to the terms and conditions stated in one of these sections.
 *  The remaining sections are part of the APaGeD package and subject
 *  to the terms and conditions of the corresponding license.
 *
 *  Attributed Parser Generator for D
 *  Copyright (c) 2007 Jascha Wetzel. All rights reserved
 *  License: Artistic License 2.0
 */

// generated code start

#line 12 "D:\src\ddbg_continued\src\expression\expression.apd"

module expression.expression_apd;
    
import codeview.decl;
import codeview.codeview;
import expression.evaluationcontext;
import expression.datahandler;
import util;

//import internal.aaA;

	struct aaA
	{
	    aaA *left;
	    aaA *right;
	    hash_t hash;
	    /* key   */
	    /* value */
	}

        struct BB
	{
	    aaA*[] b;
	    size_t nodes;       // total number of aaA nodes
	}

import std.demangle;
import std.stdio;

import win32.winnt;

/**********************************************************************************************

**********************************************************************************************/
bool castArrayIndex(ubyte[] data, string type, out size_t index)
{
    assert(type.length>0);
    switch ( type[0] )
    {
        case 'a':
            if ( *cast(char*)data.ptr < 0 )
                throw new EvaluationException("Cannot access array with negative index");
        case 'h':
            index = *cast(ubyte*)data.ptr;
            return true;
        case 's':
            if ( *cast(short*)data.ptr < 0 )
                throw new EvaluationException("Cannot access array with negative index");
        case 't':
            index = *cast(ushort*)data.ptr;
            return true;
        case 'i':
            if ( *cast(int*)data.ptr < 0 )
                throw new EvaluationException("Cannot access array with negative index");
        case 'k':
            index = *cast(uint*)data.ptr;
            return true;
        case 'l':
            if ( *cast(long*)data.ptr < 0 )
                throw new EvaluationException("Cannot access array with negative index");
        case 'm':
            index = cast(size_t)*cast(ulong*)data.ptr;
            return true;
        default:
    }
    return false;
}

/**********************************************************************************************

**********************************************************************************************/
//    debug = parser;
unittest
{
    bool test(string expr)
    {
        SyntaxTree* root;
        bool success;
        try success = parse(expr, root);
        catch ( ParserException e ) {
            debug(parser) writefln("%s", e.toString);
            return false;
        }
        return success;
    }

    assert(test("a.bc"));
    assert(test("bc[def..ghij]"));
    assert(!test("\"a\\\"\\\u2f85qwe '\""));
    assert(test("a.bc[def..ghij].klmno.pqrstu[0..'a'][\"a\\\"\\u2f85qwe '\"]"));
    assert(!test("a.bc.[def..ghij]"));
    assert(!test("[def..ghij]"));
    assert(!test("a."));
    assert(test("asdf[0][i].qwer"));
    assert(test("cast(uint)asdf"));
    assert(test("(cast(mystruct)asdf).qwer"));
    assert(test("(cast(string[])asdf)[0][2..13]"));
    assert(test("(cast(char[string])asdf)[\"qwer\"]"));
    assert(!test("(cast(mystruct)asdf).(cast(char[][])qwer)[0]"));
    assert(test("cast(float)asdf.qwer"));
    assert(!test("cast.qwer"));
    assert(!test("cast(uint).qwer"));
    assert(!test("cast(asdf.qwer).qwer"));
    assert(test("(cast(string)mystruct.tzui)[0..4]"));
    assert(test("cast(Vec!(float,3))mystruct"));
    assert(test("cast(Vec!(float,3,\"asdf\",Vec!(float)))mystruct"));
    assert(test("vertices[inds[10193]].y"));
    assert(test("*cast(uint*)#eax"));
}
// generated code end

version(Tango)
{
  
}
else
{
    import std.string;
    debug import std.stdio;
}

/**************************************************************************************************
    Semantic Analyzer
**************************************************************************************************/

class SemanticException : Exception
{
    this(string msg)
    {
        super(msg);
    }
}

struct SyntaxTree
{
    uint            _ST_rule,
                    _ST_line_number,
                    _ST_column_number;
    debug
    {
        string          _ST_node_name,
                        _ST_match,
                        _ST_match_ws;
        SyntaxTree*[]   _ST_children;
    }
    else
    {
        union
        {
            struct {
                string      _ST_match,
                            _ST_match_ws;
            }
            SyntaxTree*[]   _ST_children;
        }
    }

    debug
    {
        SyntaxTree* parent;

        string indent()
        {
            string str;
            for ( SyntaxTree* n = parent; n !is null; n = n.parent )
                str ~= "  ";
            return str;
        }

        void print(string indent = "")
        {
            version(Tango)
                Stdout.format("{}{}{}", indent, _ST_node_name, _ST_rule);
            else
                writef("%s%s%d", indent, _ST_node_name, _ST_rule);
            if ( _ST_children.length == 0 )
            {
                version(Tango)
                    Stdout.formatln(" (\"{}\")", _ST_match);
                else
                    writefln(" (\"%s\")", _ST_match);
            }
            else
            {
                version(Tango)
                    Stdout.newline;
                else
                    writefln;
            }
            foreach ( c; _ST_children )
                c.print(indent~"  ");
        }
    }

    void opCatAssign(SyntaxTree* n)
    {
        _ST_children ~= n;
    }

    // augmented semantic code
// generated code start
    alias _S_Expr Expr;
void _S_Expr(EvaluationContext ctx, out SymbolData symdata)
{

    switch ( _ST_rule )
    {
    case 0:
        debug assert(_ST_children.length == 3);
        void delegate(EvaluationContext ctx, ref SymbolData symdata) Deref = &_ST_children[0]._S_Deref;
        void delegate(EvaluationContext ctx, ref SymbolData symdata) Cast = &_ST_children[1]._S_Cast;
        void delegate(EvaluationContext ctx, out SymbolData symdata) DotChain = &_ST_children[2]._S_DotChain;

#line 136 "D:\src\ddbg_continued\src\expression\expression.apd"

        DotChain(ctx, symdata);
        Cast(ctx, symdata);
        Deref(ctx, symdata);
        break;

    default:
        assert(0);
    }
}
void _S_Deref(EvaluationContext ctx, ref SymbolData symdata)
{

    switch ( _ST_rule )
    {
    case 1:
        debug assert(_ST_children.length == 1);
        void delegate(EvaluationContext ctx, ref SymbolData symdata) Deref = &_ST_children[0]._S_Deref;

#line 146 "D:\src\ddbg_continued\src\expression\expression.apd"

        if ( symdata is null )
            throw new EvaluationException("Invalid data for dereferencing");
        if ( symdata.type[0] != 'P' )
            throw new EvaluationException("Cannot dereference non-pointer of type "~demangleType(symdata.type));
        symdata.type = symdata.type[1..$];
        assert(symdata.type.length>0);
        ubyte[] data = symdata.getData(ctx);
        if ( data.length != size_t.sizeof ) {
            throw new EvaluationException("Invalid pointer data size = "~.toString(data.length));
        }
        symdata.ptr = (cast(size_t[])data)[0];
        symdata.len = ctx.codeView.sizeofMangled(symdata.type);
        symdata.defered_load = true;

        Deref(ctx, symdata);
        break;
    case 2:
        debug assert(_ST_children.length == 0);
        break;

    default:
        assert(0);
    }
}
void _S_DotChain(EvaluationContext ctx, out SymbolData symdata)
{

    switch ( _ST_rule )
    {
    case 3:
        debug assert(_ST_children.length == 1);
        void delegate(EvaluationContext ctx, out SymbolData symdata) Register = &_ST_children[0]._S_Register;

#line 170 "D:\src\ddbg_continued\src\expression\expression.apd"

        Register(ctx, symdata);
        break;
    case 4:
        debug assert(_ST_children.length == 2);
        void delegate(EvaluationContext ctx, out SymbolData symdata) Expr = &_ST_children[0]._S_Expr;
        void delegate(EvaluationContext ctx, NamedSymbol symbol, NamedSymbol[] symbols, string prefix, ref SymbolData symdata) RefExpr = &_ST_children[1]._S_RefExpr;

#line 178 "D:\src\ddbg_continued\src\expression\expression.apd"

        Expr(ctx, symdata);
        RefExpr(ctx, null, null, "", symdata);
        break;
    case 5:
        debug assert(_ST_children.length == 2);
        void delegate(out string id) Ident = &_ST_children[0]._S_Ident;
        void delegate(EvaluationContext ctx, NamedSymbol symbol, NamedSymbol[] symbols, string prefix, ref SymbolData symdata) RefExpr = &_ST_children[1]._S_RefExpr;

#line 185 "D:\src\ddbg_continued\src\expression\expression.apd"

        string id;
        Ident(id);

        NamedSymbol[] symbols;
        NamedSymbol symbol = ctx.findSymbol(id, symbols);
        if ( symbol !is null )
            symdata = ctx.loadSymbolData(symbol);
        else
            debug DbgIO.println("symbol %s not found", id);
        RefExpr(ctx, symbol, symbols, id, symdata);
        break;
    case 6:
        debug assert(_ST_children.length == 1);
        void delegate(out SymbolData litdata) Lit = &_ST_children[0]._S_Lit;

#line 199 "D:\src\ddbg_continued\src\expression\expression.apd"
 Lit(symdata);
        break;

    default:
        assert(0);
    }
}
void _S_RefExpr(EvaluationContext ctx, NamedSymbol symbol, NamedSymbol[] symbols, string prefix, ref SymbolData symdata)
{

    switch ( _ST_rule )
    {
    case 7:
        debug assert(_ST_children.length == 2);
        void delegate(out string id) Ident = &_ST_children[0]._S_Ident;
        void delegate(EvaluationContext ctx, NamedSymbol symbol, NamedSymbol[] symbols, string prefix, ref SymbolData symdata) RefExpr = &_ST_children[1]._S_RefExpr;

#line 208 "D:\src\ddbg_continued\src\expression\expression.apd"

        string id;
        Ident(id);
        prefix ~= "."~id;

        if ( symdata is null )
        {
            symbol = ctx.findSymbol(prefix, symbols);
            if ( symbol !is null )
                symdata = ctx.loadSymbolData(symbol);
        }
        else
        {
			switch ( symdata.type[0] )
			{
				//---------------------------------------------------------------------------------
				// primitive types
				case 'v': case 'b': case 'x': case 'g': case 'h': case 's':	case 't': case 'i': case 'k': case 'l': case 'm': case 'f':
				case 'd': case 'e': case 'o': case 'p': case 'j': case 'q': case 'r': case 'c': case 'a': case 'u': case 'w':
					throw new EvaluationException(
						"Type mismatch - unexpected . operator in expression of type "~demangleType(symdata.type)
					);
				//---------------------------------------------------------------------------------
                // array properties
				case 'G':
                    switch ( id )
                    {
                        case "length":
                            symdata.type = symdata.type[1..$];
                            size_t len = parseNumber(symdata.type);
                            symdata.type = "k";
                            symdata.data = (cast(ubyte*)&len)[0..size_t.sizeof].dup;
                            symdata.defered_load = false;
                            break;
                        case "ptr":
                            // TODO: can this always be guaranteed?
                            assert(symdata.defered_load);
                            size_t ptr = symdata.ptr;
                            symdata.data = (cast(ubyte*)&ptr)[0..size_t.sizeof];
                            symdata.defered_load = false;
                            symdata.type = symdata.type[1..$];
                            parseNumber(symdata.type);
                            symdata.type = "P"~symdata.type;
                            break;
                        default:
                            throw new EvaluationException(
                                "Type mismatch - invalid property "~id~" after expression of type "~demangleType(symdata.type)
                            );
                    }
                    break;
                case 'A':
                    switch ( id )
                    {
                        case "length":
                            ubyte[] data = symdata.getData(ctx);
                            symdata.type = "k";
                            size_t len = (cast(size_t[])data)[0];
                            symdata.data = (cast(ubyte*)&len)[0..size_t.sizeof].dup;
                            symdata.defered_load = false;
                            break;
                        case "ptr":
                            ubyte[] data = symdata.getData(ctx);
                            symdata.type = "k";
                            size_t len = (cast(size_t[])data)[1];
                            symdata.data = (cast(ubyte*)&len)[0..size_t.sizeof].dup;
                            symdata.defered_load = false;
                            break;
                        default:
                            throw new EvaluationException(
                                "Type mismatch - invalid property "~id~" after expression of type "~demangleType(symdata.type)
                            );
                    }
                    break;
                case 'H':
                    switch ( id )
                    {
                        case "length":
                            ubyte[] data = symdata.getData(ctx);
                            symdata.ptr = *cast(size_t*)data.ptr;
                            symdata.len = BB.sizeof;
                            symdata.defered_load = true;
                            data = symdata.getData(ctx);
                            BB* bb = cast(BB*)data.ptr;

                            symdata.type = "k";
                            symdata.data = (cast(ubyte*)&bb.nodes)[0..size_t.sizeof].dup;
                            symdata.defered_load = false;
                            break;
                        default:
                            throw new EvaluationException(
                                "Type mismatch - invalid property "~id~" after expression of type "~demangleType(symdata.type)
                            );
                    }
                    break;
				//---------------------------------------------------------------------------------
				// references to structs/classes
				case 'P':
                    symdata.type = symdata.type[1..$];
					if ( symdata.type[0] != 'C' && symdata.type[0] != 'S' )
					{
                        throw new EvaluationException(
                            "Type mismatch - unexpected . operator after expression of type "~demangleType("P"~symdata.type)
                        );
					}

                    ubyte[] data = symdata.getData(ctx);
                    if ( symdata.data.length <= 0 )
                        throw new EvaluationException("Subexpression evaluated to empty data");
					symdata.ptr = (cast(uint[])data)[0];
					symdata.len = ctx.codeView.sizeofMangled(symdata.type);
					symdata.defered_load = true;

					if ( symdata.ptr == 0 )
						throw new EvaluationException("pointer is null");
                    // fall through to struct handling

				//---------------------------------------------------------------------------------
				// classes/structs
				case 'C':
				case 'S':
                    symdata.type = symdata.type[1..$];
                    string	scu_name = demangleNameSkip(symdata.type);
                    assert ( symdata.type.length <= 0 );
                    if ( (scu_name in ctx.codeView.UDTsByName) is null )
                        throw new EvaluationException("unknown type \""~scu_name~"\"");

                    LeafClassStruc  lcs = cast(LeafClassStruc)ctx.codeView.UDTsByName[scu_name];
                    LeafUnion       lu;
                    LeafFieldList   lfl;
                    uint            type_length;

                    if ( lcs !is null && lcs.field-0x1000 < ctx.codeView.type_strings.length ) {
                        Leaf[] fields = ctx.codeView.type_strings[lcs.field-0x1000];
                        lfl = cast(LeafFieldList)fields[0];
                        type_length = lcs.length.getUint();
                    }
                    else
                    {
                        lu = cast(LeafUnion)ctx.codeView.UDTsByName[scu_name];
                        if ( lu !is null && lu.field-0x1000 < ctx.codeView.type_strings.length ) {
                            Leaf[] fields = ctx.codeView.type_strings[lu.field-0x1000];
                            lfl = cast(LeafFieldList)fields[0];
                            type_length = lu.length.getUint();
                        }
                    }
                    if ( lfl is null )
                        throw new EvaluationException("invalid struct/class debug symbols");

                    size_t  size,
                            offset;
                    if ( !ctx.findMember(id, lfl, size, offset, symdata.type) )
                        throw new EvaluationException("struct \""~scu_name~"\" has no element \""~id~"\"");
                    assert ( symdata.type.length > 0 );
                    debug(eval) DbgIO.println("member: type=%s size=%d offset=%d", symdata.type, size, offset);

                    if ( !symdata.loadByteSlice(offset, offset+size) )
                        throw new EvaluationException("invalid offset into struct for member \""~id~"\"");
					break;
				//---------------------------------------------------------------------------------
				// unsupported
				default:
					throw new EvaluationException("yet unsupported type "~demangleType(symdata.type)~" in expression");
			}
        }

        RefExpr(ctx, symbol, symbols, prefix, symdata);
        break;
    case 8:
        debug assert(_ST_children.length == 2);
        void delegate(EvaluationContext ctx, out SymbolData argdata, out size_t start, out size_t end) Args = &_ST_children[0]._S_Args;
        void delegate(EvaluationContext ctx, NamedSymbol symbol, NamedSymbol[] symbols, string prefix, ref SymbolData symdata) RefExpr = &_ST_children[1]._S_RefExpr;

#line 383 "D:\src\ddbg_continued\src\expression\expression.apd"

        if ( symdata is null )
            throw new EvaluationException("Unknown symbol "~prefix);

        SymbolData  argdata;
        size_t      start, end;
        Args(ctx, argdata, start, end);

        bool isIndex = argdata is null;
        if ( !isIndex && castArrayIndex(argdata.getData(ctx), argdata.type, start) ) {
            isIndex = true;
            end = start+1;
        }

        switch ( symdata.type[0] )
        {
            //---------------------------------------------------------------------------------
            // primitive types
            case 'v': case 'b': case 'x': case 'g': case 'h': case 's':	case 't': case 'i': case 'k': case 'l': case 'm': case 'f':
            case 'd': case 'e': case 'o': case 'p': case 'j': case 'q': case 'r': case 'c': case 'a': case 'u': case 'w':
            // pointers, classes/structs
            case 'P': case 'C': case 'S':
                throw new EvaluationException(
                    "Type mismatch - unexpected [] operator after expression of type "~demangleType(symdata.type)
                );
            //---------------------------------------------------------------------------------
            // static arrays
            case 'G':
                if ( !isIndex )
                    throw new EvaluationException("Cannot access static array with index type "~demangleType(argdata.type));

                symdata.type = symdata.type[1..$];
                size_t count = parseNumber(symdata.type);
                assert(symdata.type.length>0);

                if ( end-start > 1 )
                {
                    if ( end > count )
                        throw new EvaluationException("Array index out of bounds: "~.toString(start)~".."~.toString(end)~" ($="~.toString(count)~")");
                    size_t size = ctx.codeView.sizeofMangled(symdata.type);
                    if ( symdata.defered_load ) {
                        symdata.ptr += start * size;
                        symdata.len = (end-start) * size;
                    }
                    else
                        symdata.data = symdata.data[start*size .. end*size];
                    symdata.type = "G"~.toString(end-start)~symdata.type;
                }
                else
                {
                    if ( !symdata.loadElementSlice(start, end, ctx.codeView) )
                        throw new EvaluationException("Array index out of bounds: "~.toString(start)~".."~.toString(end)~" ($="~.toString(count)~")");
                }
                break;
            //---------------------------------------------------------------------------------
            // dynamic arrays
            case 'A':
                if ( !isIndex )
                    throw new EvaluationException("Cannot access dynamic array with index type "~demangleType(argdata.type));

                ubyte[] data = symdata.getData(ctx);
                if ( data.length < 8 )
                    throw new EvaluationException("Subexpression evaluated to empty data");

                if ( end-start > 1 )
                {
                    if ( end > (cast(size_t[])data)[0] )
                        throw new EvaluationException("Array index out of bounds: "~.toString(start)~".."~.toString(end)~" ($="~.toString(symdata.len)~")");
                    size_t size = ctx.codeView.sizeofMangled(symdata.type[1..$]);
                    (cast(size_t[])data)[1] += start * size,
                    (cast(size_t[])data)[0] = end-start;
                }
                else
                {
                    symdata.type = symdata.type[1..$];
                    assert(symdata.type.length>0);
                    symdata.ptr = (cast(size_t[])data)[1];
                    symdata.len = (cast(size_t[])data)[0] * ctx.codeView.sizeofMangled(symdata.type);
                    symdata.defered_load = true;

                    if ( !symdata.loadElementSlice(start, end, ctx.codeView) )
                        throw new EvaluationException("Array index out of bounds: "~.toString(start)~".."~.toString(end)~" ($="~.toString(symdata.len)~")");
                }
                break;
            //---------------------------------------------------------------------------------
            // associative arrays
            case 'H':
                int i;
                for ( i = 1; i < symdata.type.length && std.string.find(lowercase, symdata.type[i]) < 0; ++i ) {}
                string		key_type	= symdata.type[1..i+1],
                            val_type	= symdata.type[i+1..$];
                size_t      val_tsize   = ctx.codeView.sizeofMangled(val_type);
                TypeInfo	key_ti		= TypeInfoFromMangled(key_type);

                aaA* loadaaA(void* ptr)
                {
                    if ( ptr is null )
                        return null;
                    ubyte[] data;
                    data.length = aaA.sizeof+key_ti.tsize+val_tsize;
                    if ( data.length != ctx.process.readProcessMemory(cast(uint)ptr, data.ptr, data.length) )
                        return null;
                    aaA* a = cast(aaA*)data.ptr;
                    if ( std.string.find(lowercase, key_type[0]) < 0 )
                    switch ( key_type[0] )
                    {
                        case 'A':
                            ubyte[] tmp = *cast(ubyte[]*)(a+1);
                            if ( tmp.length > ctx.process.MEMCHECK_MIN && ctx.process.isInvalidMem(cast(size_t)tmp.ptr, tmp.length) )
                                return null;
                            data = new ubyte[tmp.length];
                            if ( data.length != ctx.process.readProcessMemory(cast(size_t)tmp.ptr, data.ptr, data.length) )
                                return null;
                            *cast(ubyte[]*)(a+1) = data;
                            break;
                        case 'P':
                            break;
                        default:
                            throw new EvaluationException("only basic, pointer and array key types are supported, yet");
                    }
                    return a;
                }

                ubyte[] findKey(size_t ptr, hash_t hash, ubyte[] key_data)
                {
                    ubyte[] data;
                    data.length = BB.sizeof;
                    if ( data.length != ctx.process.readProcessMemory(ptr, data.ptr, data.length) )
                        return null;
                    BB* bb = cast(BB*)data.ptr;
                    size_t blen = bb.b.length*size_t.sizeof;
                    debug(eval) DbgIO.println("%d nodes, bb.b.length=%d", bb.nodes, bb.b.length);

                    if ( blen > ctx.process.MEMCHECK_MIN && ctx.process.isInvalidMem(cast(size_t)bb.b.ptr, blen) )
                        return null;
                    data = new ubyte[blen];
                    if ( data.length != ctx.process.readProcessMemory(cast(uint)bb.b.ptr, data.ptr, data.length) )
                        return null;
                    bb.b = cast(aaA*[])data;

                    uint i = hash % bb.b.length;
                    debug(eval) DbgIO.println("start index=%d", i);
                    aaA* a = loadaaA(bb.b[i]);
                    while ( a !is null )
                    {
                        if ( hash == a.hash )
                        {
                            debug(eval) DbgIO.println("equal 0x%x", a.hash);
                            auto cmp = key_ti.compare(key_data.ptr, a+1);
                            debug(eval) DbgIO.println("%s: %d == %d -> %d", key_ti, *cast(uint*)key_data.ptr, *cast(uint*)(a+1), cmp);
                            if ( cmp == 0 )
                                return ((cast(ubyte*)(a+1))+key_ti.tsize)[0 .. val_tsize];
                            a = cmp < 0 ? loadaaA(a.left) : loadaaA(a.right);
                        }
                        else {
                            debug(eval) DbgIO.println("not equal 0x%x", a.hash);
                            a = hash < a.hash ? loadaaA(a.left) : loadaaA(a.right);
                        }
                    }
                    return null;
                }

                if ( key_type != argdata.type )
                    throw new EvaluationException("Invalid key type for associative array. Expected "~demangleType(key_type)~" found "~demangleType(argdata.type));
                TypeInfo ti = TypeInfoFromMangled(argdata.type);
                hash_t index_hash = ti.getHash(argdata.data.ptr);

                debug(eval) DbgIO.println("searching, hash=0x%x", index_hash);
                ubyte[] data = symdata.getData(ctx);
                symdata.data = findKey((cast(size_t[])data)[0], index_hash, argdata.getData(ctx));
                symdata.type = val_type;
                break;
            //---------------------------------------------------------------------------------
            // unsupported
            default:
                throw new EvaluationException("yet unsupported type "~demangleType(symdata.type)~" in expression");
        }

        RefExpr(ctx, symbol, null, null, symdata);
        break;
    case 9:
        debug assert(_ST_children.length == 0);

#line 568 "D:\src\ddbg_continued\src\expression\expression.apd"

        if ( symdata is null )
            throw new EvaluationException("Unknown symbol "~prefix);
        break;

    default:
        assert(0);
    }
}
void _S_Args(EvaluationContext ctx, out SymbolData argdata, out size_t start, out size_t end)
{

    switch ( _ST_rule )
    {
    case 10:
        debug assert(_ST_children.length == 2);
        void delegate(EvaluationContext ctx, out SymbolData symdata) Expr = &_ST_children[0]._S_Expr;
        void delegate(EvaluationContext ctx, out SymbolData symdata) Expr2 = &_ST_children[1]._S_Expr;

#line 579 "D:\src\ddbg_continued\src\expression\expression.apd"

        SymbolData arg1, arg2;
        Expr(ctx, arg1);
        Expr2(ctx, arg2);

        bool isIndex = castArrayIndex(arg1.getData(ctx), arg1.type, start);
        isIndex = isIndex && castArrayIndex(arg2.getData(ctx), arg2.type, end);
        if ( !isIndex )
            throw new EvaluationException("Slices may only have integer indeces, not "~demangleType(arg1.type)~".."~demangleType(arg2.type));
        break;
    case 11:
        debug assert(_ST_children.length == 1);
        void delegate(EvaluationContext ctx, out SymbolData symdata) Expr = &_ST_children[0]._S_Expr;

#line 591 "D:\src\ddbg_continued\src\expression\expression.apd"
 Expr(ctx, argdata);
        break;

    default:
        assert(0);
    }
}
void _S_Register(EvaluationContext ctx, out SymbolData symdata)
{

    switch ( _ST_rule )
    {
    case 12:
        debug assert(_ST_children.length == 1);
        void delegate(out string name, out ubyte width) RegName = &_ST_children[0]._S_RegName;

#line 601 "D:\src\ddbg_continued\src\expression\expression.apd"

        string  name;
        ubyte   width;
        RegName(name, width);

		CONTEXT threadCtx;
		uint context_flags;
        context_flags |= CONTEXT_FULL;
        context_flags |= CONTEXT_FLOATING_POINT;
        context_flags |= CONTEXT_EXTENDED_REGISTERS;
		if ( !ctx.getContext(threadCtx, context_flags) )
			throw new EvaluationException("Couldn't get main thread's context");

        ubyte* ptr;
        switch ( name[1..$] )
        {
            case "ax":
            case "eax":
            case "al":  ptr = cast(ubyte*)&threadCtx.Eax;   break;
            case "ah":  ptr = (cast(ubyte*)&threadCtx.Eax)+1;   break;
            case "bx":
            case "ebx":
            case "bl":  ptr = cast(ubyte*)&threadCtx.Ebx;   break;
            case "bh":  ptr = (cast(ubyte*)&threadCtx.Ebx)+1;   break;
            case "cx":
            case "ecx":
            case "cl":  ptr = cast(ubyte*)&threadCtx.Ecx;   break;
            case "ch":  ptr = (cast(ubyte*)&threadCtx.Ecx)+1;   break;
            case "dx":
            case "edx":
            case "dl":  ptr = cast(ubyte*)&threadCtx.Edx;   break;
            case "dh":  ptr = (cast(ubyte*)&threadCtx.Edx)+1;   break;
            case "edi":
            case "di":  ptr = cast(ubyte*)&threadCtx.Edi;   break;
            case "esi":
            case "si":  ptr = cast(ubyte*)&threadCtx.Esi;   break;
            case "ebp":
            case "bp":  ptr = cast(ubyte*)&threadCtx.Ebp;   break;
            case "esp":
            case "sp":  ptr = cast(ubyte*)&threadCtx.Esp;   break;
            case "eip": ptr = cast(ubyte*)&threadCtx.Eip;   break;
            case "efl": ptr = cast(ubyte*)&threadCtx.EFlags;    break;
            case "cs":  ptr = cast(ubyte*)&threadCtx.SegCs; break;
            case "ds":  ptr = cast(ubyte*)&threadCtx.SegDs; break;
            case "es":  ptr = cast(ubyte*)&threadCtx.SegEs; break;
            case "fs":  ptr = cast(ubyte*)&threadCtx.SegFs; break;
            case "gs":  ptr = cast(ubyte*)&threadCtx.SegGs; break;
            default:
                int i = name[$-1]-'0';
                if ( name[0..2] == "st" )
                    ptr = cast(ubyte*)&((cast(real[])threadCtx.FloatSave.RegisterArea)[i]);
                else if ( name[0..2] == "mm" )
                    ptr = cast(ubyte*)&((cast(long[])threadCtx.ExtendedRegisters)[4+i*2]);
                else if ( name[0..3] == "xmm" )
                    ptr = cast(ubyte*)&((cast(long[])threadCtx.ExtendedRegisters)[20+i*2]);
                else
                    assert(0);
        }

        symdata = new SymbolData;
        switch ( width )
        {
            case 8:
                symdata.type = "h";
                symdata.data = ptr[0..1].dup;
                break;
            case 16:
                symdata.type = "t";
                symdata.data = ptr[0..2].dup;
                break;
            case 32:
                symdata.type = "k";
                symdata.data = ptr[0..4].dup;
                break;
            case 64:
                symdata.type = "m";
                symdata.data = ptr[0..8].dup;
                break;
            case 80:
                symdata.type = "e";
                symdata.data = ptr[0..10].dup;
                break;
            case 128:
                symdata.type = "G4k";
                symdata.data = ptr[0..16].dup;
                break;
            default:
                assert(0, "unhandled register width "~.toString(width));
        }
        break;

    default:
        assert(0);
    }
}
void _S_RegName(out string name, out ubyte width)
{

    switch ( _ST_rule )
    {
    case 13:
        debug assert(_ST_children.length == 0);

#line 696 "D:\src\ddbg_continued\src\expression\expression.apd"
 name = _ST_match; width = 32;
        break;
    case 14:
        debug assert(_ST_children.length == 0);

#line 699 "D:\src\ddbg_continued\src\expression\expression.apd"
 name = _ST_match; width = 16;
        break;
    case 15:
        debug assert(_ST_children.length == 0);

#line 702 "D:\src\ddbg_continued\src\expression\expression.apd"
 name = _ST_match; width = 8;
        break;
    case 16:
        debug assert(_ST_children.length == 0);

#line 705 "D:\src\ddbg_continued\src\expression\expression.apd"
 name = _ST_match; width = 8*real.sizeof;
        break;
    case 17:
        debug assert(_ST_children.length == 0);

#line 708 "D:\src\ddbg_continued\src\expression\expression.apd"
 name = _ST_match; width = 64;
        break;
    case 18:
        debug assert(_ST_children.length == 0);

#line 711 "D:\src\ddbg_continued\src\expression\expression.apd"
 name = _ST_match; width = 128;
        break;

    default:
        assert(0);
    }
}
void _S_Cast(EvaluationContext ctx, ref SymbolData symdata)
{

    switch ( _ST_rule )
    {
    case 19:
        debug assert(_ST_children.length == 1);
        void delegate(EvaluationContext ctx, ref string mangled) Type = &_ST_children[0]._S_Type;

#line 724 "D:\src\ddbg_continued\src\expression\expression.apd"

        symdata.type = "";
        Type(ctx, symdata.type);
        if ( symdata.type.length <= 0 )
            throw new EvaluationException("Unknown type in cast");
        break;
    case 20:
        debug assert(_ST_children.length == 0);
        break;

    default:
        assert(0);
    }
}
void _S_Type(EvaluationContext ctx, ref string mangled)
{

    switch ( _ST_rule )
    {
    case 21:
        debug assert(_ST_children.length == 2);
        void delegate(EvaluationContext ctx, out string type) BaseType = &_ST_children[0]._S_BaseType;
        void delegate(EvaluationContext ctx, ref string mangled) QuantList = &_ST_children[1]._S_QuantList;

#line 737 "D:\src\ddbg_continued\src\expression\expression.apd"

        string  unmangled;
        BaseType(ctx, unmangled);

		switch ( unmangled )
		{
			case "void":	mangled = "v";	break;
			case "bool":	mangled = "b";	break;
			case "byte":	mangled = "g";	break;
			case "ubyte":	mangled = "h";	break;
			case "char":	mangled = "a";	break;
			case "wchar":	mangled = "u";	break;
			case "dchar":	mangled = "w";	break;
			case "short":	mangled = "s";	break;
			case "ushort":	mangled = "t";	break;
			case "int":		mangled = "i";	break;
			case "uint":	mangled = "k";	break;
			case "long":	mangled = "l";	break;
			case "ulong":	mangled = "m";	break;
			case "float":	mangled = "f";	break;
			case "double":	mangled = "d";	break;
			case "real":	mangled = "e";	break;
			default:
				Leaf lf;
				if ( (unmangled in ctx.codeView.UDTsByName) is null )
				{
					foreach ( un, l; ctx.codeView.UDTsByName )
					{
						if ( std.string.find(un, "."~unmangled) > 0 ) {
							lf = l;
							break;
						}
					}
				}
				else
					lf = ctx.codeView.UDTsByName[unmangled];

				if ( lf !is null )
				{
					string fqn;
					switch ( lf.leaf_index )
					{
						case LF_CLASS_16t:
							mangled = "C";
							fqn = (cast(LeafClassStruc)lf).name;
							break;
						case LF_STRUCTURE_16t:
							mangled = "S";
							fqn = (cast(LeafClassStruc)lf).name;
							break;
						case LF_ENUM_16t:
							mangled = "E";
							fqn = (cast(LeafEnum)lf).name;
							break;
						default:
							assert(0);
					}
					string[] parts = std.string.split(fqn, ".");
					foreach ( p; parts ) {
						mangled ~= .toString(p.length);
						mangled ~= p;
					}
				}
                else
                    throw new EvaluationException("Unknown BaseType "~unmangled);
				break;
		}

		QuantList(ctx, mangled);
        break;

    default:
        assert(0);
    }
}
void _S_BaseType(EvaluationContext ctx, out string type)
{

    switch ( _ST_rule )
    {
    case 22:
        debug assert(_ST_children.length == 2);
        void delegate(out string id) FQNIdent = &_ST_children[0]._S_FQNIdent;
        void delegate(EvaluationContext ctx, out string str) TplParams = &_ST_children[1]._S_TplParams;

#line 812 "D:\src\ddbg_continued\src\expression\expression.apd"

        FQNIdent(type);
        string str;
        TplParams(ctx, str);
        type ~= str;
        break;

    default:
        assert(0);
    }
}
void _S_QuantList(EvaluationContext ctx, ref string mangled)
{

    switch ( _ST_rule )
    {
    case 23:
        debug assert(_ST_children.length == 2);
        void delegate(EvaluationContext ctx, ref string mangled) Quantifier = &_ST_children[0]._S_Quantifier;
        void delegate(EvaluationContext ctx, ref string mangled) QuantList = &_ST_children[1]._S_QuantList;

#line 823 "D:\src\ddbg_continued\src\expression\expression.apd"

        Quantifier(ctx, mangled);
        QuantList(ctx, mangled);
        break;
    case 24:
        debug assert(_ST_children.length == 0);
        break;

    default:
        assert(0);
    }
}
void _S_Quantifier(EvaluationContext ctx, ref string mangled)
{

    switch ( _ST_rule )
    {
    case 25:
        debug assert(_ST_children.length == 0);

#line 834 "D:\src\ddbg_continued\src\expression\expression.apd"
 mangled = "P"~mangled;
        break;
    case 26:
        debug assert(_ST_children.length == 0);

#line 837 "D:\src\ddbg_continued\src\expression\expression.apd"
 mangled = "A"~mangled;
        break;
    case 27:
        debug assert(_ST_children.length == 1);
        void delegate(out ulong val) Integer = &_ST_children[0]._S_Integer;

#line 842 "D:\src\ddbg_continued\src\expression\expression.apd"

        ulong len;
        Integer(len);
        mangled = "G"~.toString(len)~mangled;
        break;
    case 28:
        debug assert(_ST_children.length == 1);
        void delegate(EvaluationContext ctx, ref string mangled) Type = &_ST_children[0]._S_Type;

#line 851 "D:\src\ddbg_continued\src\expression\expression.apd"

        string index_mangled;
        Type(ctx, index_mangled);
        mangled = "H"~index_mangled~mangled;
        break;

    default:
        assert(0);
    }
}
void _S_TplParams(EvaluationContext ctx, out string str)
{

    switch ( _ST_rule )
    {
    case 29:
        debug assert(_ST_children.length == 2);
        void delegate(EvaluationContext ctx, out string str) TplParam = &_ST_children[0]._S_TplParam;
        void delegate(EvaluationContext ctx, out string str) TplParams2 = &_ST_children[1]._S_TplParams2;

#line 865 "D:\src\ddbg_continued\src\expression\expression.apd"

        string tmp;
        TplParam(ctx, tmp);
        str = "!("~tmp;
        TplParams2(ctx, tmp);
        str ~= tmp~")";
        break;
    case 30:
        debug assert(_ST_children.length == 0);
        break;

    default:
        assert(0);
    }
}
void _S_TplParams2(EvaluationContext ctx, out string str)
{

    switch ( _ST_rule )
    {
    case 31:
        debug assert(_ST_children.length == 2);
        void delegate(EvaluationContext ctx, out string str) TplParam = &_ST_children[0]._S_TplParam;
        void delegate(EvaluationContext ctx, out string str) TplParams2 = &_ST_children[1]._S_TplParams2;

#line 881 "D:\src\ddbg_continued\src\expression\expression.apd"

        TplParam(ctx, str);
        string tmp;
        TplParams2(ctx, tmp);
        str ~= tmp;
        break;
    case 32:
        debug assert(_ST_children.length == 0);
        break;

    default:
        assert(0);
    }
}
void _S_TplParam(EvaluationContext ctx, out string str)
{

    switch ( _ST_rule )
    {
    case 33:
        debug assert(_ST_children.length == 1);
        void delegate(EvaluationContext ctx, ref string mangled) Type = &_ST_children[0]._S_Type;

#line 893 "D:\src\ddbg_continued\src\expression\expression.apd"
 Type(ctx, str);
        break;
    case 34:
        debug assert(_ST_children.length == 1);
        void delegate(out string str) StrLit = &_ST_children[0]._S_StrLit;

#line 894 "D:\src\ddbg_continued\src\expression\expression.apd"
 StrLit(str);
        break;

    default:
        assert(0);
    }
}
void _S_Lit(out SymbolData litdata)
{

    switch ( _ST_rule )
    {
    case 35:
        debug assert(_ST_children.length == 3);
        void delegate(ref SymbolData symdata) Sign = &_ST_children[0]._S_Sign;
        void delegate(out ulong val) Integer = &_ST_children[1]._S_Integer;
        void delegate(out string type) IntegerSuffix = &_ST_children[2]._S_IntegerSuffix;

#line 904 "D:\src\ddbg_continued\src\expression\expression.apd"

        litdata = new SymbolData;
        IntegerSuffix(litdata.type);
        ulong val;
        Integer(val);

        if ( val > 0x7fffffffffffffff )
            litdata.type = "m";
        else if ( val > 0xffffffff )
            litdata.type = litdata.type[0]=='i'||litdata.type[0]=='l'?"l":"m";
        else if ( val > 0x7fffffff && litdata.type[0] == 'i' )
            litdata.type = "k";

        litdata.data = (cast(ubyte*)&val)[0 .. (litdata.type[0] == 'k' || litdata.type[0] == 'i')?uint.sizeof:ulong.sizeof].dup;
        Sign(litdata);
        break;
    case 36:
        debug assert(_ST_children.length == 0);

#line 923 "D:\src\ddbg_continued\src\expression\expression.apd"

        litdata = new SymbolData;
        litdata.type = "Aa";
        litdata.data = cast(ubyte[])_ST_match;
        break;
    case 37:
        debug assert(_ST_children.length == 0);

#line 931 "D:\src\ddbg_continued\src\expression\expression.apd"

        litdata = new SymbolData;
        litdata.type = "a";
        litdata.data = cast(ubyte[])_ST_match[0..1];
        break;

    default:
        assert(0);
    }
}
void _S_StrLit(out string str)
{

    switch ( _ST_rule )
    {
    case 38:
        debug assert(_ST_children.length == 1);
        void delegate(out ulong val) Integer = &_ST_children[0]._S_Integer;

#line 942 "D:\src\ddbg_continued\src\expression\expression.apd"

        ulong val;
        Integer(val);
        str = .toString(val);
        break;
    case 39:
        debug assert(_ST_children.length == 0);

#line 950 "D:\src\ddbg_continued\src\expression\expression.apd"
 str = _ST_match;
        break;
    case 40:
        debug assert(_ST_children.length == 0);

#line 954 "D:\src\ddbg_continued\src\expression\expression.apd"
 str = _ST_match;
        break;

    default:
        assert(0);
    }
}
void _S_Ident(out string id)
{

    switch ( _ST_rule )
    {
    case 41:
        debug assert(_ST_children.length == 0);

#line 960 "D:\src\ddbg_continued\src\expression\expression.apd"
 id = _ST_match;
        break;

    default:
        assert(0);
    }
}
void _S_FQNIdent(out string id)
{

    switch ( _ST_rule )
    {
    case 42:
        debug assert(_ST_children.length == 1);
        void delegate(out string id) Ident = &_ST_children[0]._S_Ident;

#line 966 "D:\src\ddbg_continued\src\expression\expression.apd"
 Ident(id);
        break;
    case 43:
        debug assert(_ST_children.length == 2);
        void delegate(out string id) FQNIdent = &_ST_children[0]._S_FQNIdent;
        void delegate(out string id) Ident = &_ST_children[1]._S_Ident;

#line 969 "D:\src\ddbg_continued\src\expression\expression.apd"

        FQNIdent(id);
        string tmp;
        Ident(tmp);
        id ~= "."~tmp;
        break;

    default:
        assert(0);
    }
}
void _S_Integer(out ulong val)
{

    switch ( _ST_rule )
    {
    case 44:
        debug assert(_ST_children.length == 0);

#line 984 "D:\src\ddbg_continued\src\expression\expression.apd"

        foreach ( b; _ST_match[2..$] )
        {
            val <<= 4;
            if ( b > 'F' )
                val |= b-'W';
            else if ( b > '9' )
                val |= b-'7';
            else
                val |= b-'0';
        }
        break;
    case 45:
        debug assert(_ST_children.length == 0);

#line 999 "D:\src\ddbg_continued\src\expression\expression.apd"

        foreach ( b; _ST_match[2..$] )
        {
            val <<= 1;
            if ( b == '1' )
                val |= 1;
        }
        break;
    case 46:
        debug assert(_ST_children.length == 0);

#line 1010 "D:\src\ddbg_continued\src\expression\expression.apd"

        foreach ( b; _ST_match[1..$] ) {
            val <<= 3;
            val |= b-'0';
        }
        break;
    case 47:
        debug assert(_ST_children.length == 0);

#line 1019 "D:\src\ddbg_continued\src\expression\expression.apd"

        foreach ( b; _ST_match ) {
            val *= 10;
            val += b-'0';
        }
        break;

    default:
        assert(0);
    }
}
void _S_IntegerSuffix(out string type)
{

    switch ( _ST_rule )
    {
    case 48:
        debug assert(_ST_children.length == 0);

#line 1030 "D:\src\ddbg_continued\src\expression\expression.apd"
 type = "m";
        break;
    case 49:
        debug assert(_ST_children.length == 0);

#line 1033 "D:\src\ddbg_continued\src\expression\expression.apd"
 type = "m";
        break;
    case 50:
        debug assert(_ST_children.length == 0);

#line 1036 "D:\src\ddbg_continued\src\expression\expression.apd"
 type = "m";
        break;
    case 51:
        debug assert(_ST_children.length == 0);

#line 1039 "D:\src\ddbg_continued\src\expression\expression.apd"
 type = "m";
        break;
    case 52:
        debug assert(_ST_children.length == 0);

#line 1042 "D:\src\ddbg_continued\src\expression\expression.apd"
 type = "l";
        break;
    case 53:
        debug assert(_ST_children.length == 0);

#line 1045 "D:\src\ddbg_continued\src\expression\expression.apd"
 type = "k";
        break;
    case 54:
        debug assert(_ST_children.length == 0);

#line 1048 "D:\src\ddbg_continued\src\expression\expression.apd"
 type = "i";
        break;

    default:
        assert(0);
    }
}
void _S_Sign(ref SymbolData symdata)
{

    switch ( _ST_rule )
    {
    case 55:
        debug assert(_ST_children.length == 0);

#line 1054 "D:\src\ddbg_continued\src\expression\expression.apd"

        switch ( symdata.type[0] )
        {
            case 'i':
                *cast(int*)symdata.data.ptr = 0-*cast(int*)symdata.data.ptr;
                break;
            case 'k':
                *cast(uint*)symdata.data.ptr = 0-*cast(uint*)symdata.data.ptr;
                break;
            case 'l':
                *cast(long*)symdata.data.ptr = 0-*cast(long*)symdata.data.ptr;
                break;
            case 'm':
                *cast(ulong*)symdata.data.ptr = 0-*cast(ulong*)symdata.data.ptr;
                break;
            default:
                assert(0);
        }
        break;
    case 56:
        debug assert(_ST_children.length == 0);
        break;

    default:
        assert(0);
    }
}

// generated code end
}

#line 1443 "D:\src\ddbg_continued\src\expression\expression_apd.d"
// Written in the D programming language

/*
 *  This file has been automatically generated by APaGeD v0.4.2 beta - Attributed Parser Generator for D.
 *
 *  Sections generated from custom input are marked as "generated code" and
 *  are subject to the terms and conditions stated in one of these sections.
 *  The remaining sections are part of the APaGeD package and subject
 *  to the terms and conditions of the corresponding license.
 *
 *  Attributed Parser Generator for D
 *  Copyright (c) 2007 Jascha Wetzel. All rights reserved
 *  License: Artistic License 2.0
 */

/**************************************************************************************************
    Lexer
**************************************************************************************************/

version(Tango)
// the following block is stolen from phobos.
// the copyright notice applies for this block only.
{
/*
 *  Copyright (C) 2003-2004 by Digital Mars, www.digitalmars.com
 *  Written by Walter Bright
 *
 *  This software is provided 'as-is', without any express or implied
 *  warranty. In no event will the authors be held liable for any damages
 *  arising from the use of this software.
 *
 *  Permission is granted to anyone to use this software for any purpose,
 *  including commercial applications, and to alter it and redistribute it
 *  freely, subject to the following restrictions:
 *
 *  o  The origin of this software must not be misrepresented; you must not
 *     claim that you wrote the original software. If you use this software
 *     in a product, an acknowledgment in the product documentation would be
 *     appreciated but is not required.
 *  o  Altered source versions must be plainly marked as such, and must not
 *     be misrepresented as being the original software.
 *  o  This notice may not be removed or altered from any source
 *     distribution.
 */

bool isValidDchar(dchar c)
{
    /* Note: FFFE and FFFF are specifically permitted by the
     * Unicode standard for application internal use, but are not
     * allowed for interchange.
     * (thanks to Arcane Jill)
     */

    return c < 0xD800 ||
	(c > 0xDFFF && c <= 0x10FFFF /*&& c != 0xFFFE && c != 0xFFFF*/);
}

/***************
 * Decodes and returns character starting at s[idx]. idx is advanced past the
 * decoded character. If the character is not well formed, a UtfException is
 * thrown and idx remains unchanged.
 */

dchar decode(in char[] s, inout size_t idx)
    {
	size_t len = s.length;
	dchar V;
	size_t i = idx;
	char u = s[i];

	if (u & 0x80)
	{   uint n;
	    char u2;

	    /* The following encodings are valid, except for the 5 and 6 byte
	     * combinations:
	     *	0xxxxxxx
	     *	110xxxxx 10xxxxxx
	     *	1110xxxx 10xxxxxx 10xxxxxx
	     *	11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
	     *	111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
	     *	1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
	     */
	    for (n = 1; ; n++)
	    {
		if (n > 4)
		    goto Lerr;		// only do the first 4 of 6 encodings
		if (((u << n) & 0x80) == 0)
		{
		    if (n == 1)
			goto Lerr;
		    break;
		}
	    }

	    // Pick off (7 - n) significant bits of B from first byte of octet
	    V = cast(dchar)(u & ((1 << (7 - n)) - 1));

	    if (i + (n - 1) >= len)
		goto Lerr;			// off end of string

	    /* The following combinations are overlong, and illegal:
	     *	1100000x (10xxxxxx)
	     *	11100000 100xxxxx (10xxxxxx)
	     *	11110000 1000xxxx (10xxxxxx 10xxxxxx)
	     *	11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
	     *	11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
	     */
	    u2 = s[i + 1];
	    if ((u & 0xFE) == 0xC0 ||
		(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
		(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
		(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
		(u == 0xFC && (u2 & 0xFC) == 0x80))
		goto Lerr;			// overlong combination

	    for (uint j = 1; j != n; j++)
	    {
		u = s[i + j];
		if ((u & 0xC0) != 0x80)
		    goto Lerr;			// trailing bytes are 10xxxxxx
		V = (V << 6) | (u & 0x3F);
	    }
	    if (!isValidDchar(V))
		goto Lerr;
	    i += n;
	}
	else
	{
	    V = cast(dchar) u;
	    i++;
	}

	idx = i;
	return V;

      Lerr:
	throw new Exception("4invalid UTF-8 sequence");
    }
}
else
{
    import std.utf;
}

// lexer code
// generated code start
// ((?\*)|(?\()|(?\))|(?\.)|(?\[)|(?\])|(?\.\.)|(?#(e[abcd]x|e[ds]i|e[bs]p|eip|efl))|(?#([abcd]x|[ds]i|[bs]p|(cdefgs)s))|(?#[abcd][hl])|(?#st[0-7])|(?#mm[0-7])|(?#xmm[0-7])|(?cast)|(?!)|(?,)|(?"(([^"\\]*(\\(['"\?\\abfnrtv]|(x[0-9a-fA-F]{2})|(u[0-9a-fA-F]{4})|(U[0-9a-fA-F]{8})))?)*)")|(?'(([^'\\]|(\\(['"\?\\abfnrtv]|(x[0-9a-fA-F]{2})|(u[0-9a-fA-F]{4})|(U[0-9a-fA-F]{8})))))')|(?[a-zA-Z_][_a-zA-Z0-9]*)|(?0[xX][0-9a-fA-F_]+)|(?0[bB][01_]+)|(?0[0-7_]+)|(?0|([1-9][0-9_]*))|(?L)|(?u)|(?U)|(?[uU])|(?\-)).*?
bool mainLexer(string input, out uint token, out string match)
{
    uint s = 0;
    static int r56=-1, r57=-1, r58=-1, r59=-1, r60=-1, r61=-1, r62=-1, r63=-1, r64=-1, r65=-1, 
        r66=-1, r67=-1, r68=-1, r69=-1, r70=-1, r71=-1, r72=-1, r73=-1, r74=-1, r75=-1, 
        r76=-1, r77=-1, r78=-1, r79=-1, r80=-1, r81=-1, r82=-1, r83=-1, r84=-1, r85=-1, 
        r86=-1;

    for ( size_t p = 0, q = 0, p_end = input.length; p < p_end; q = p )
    {
        dchar c = cast(dchar)input[p];
        if ( c & 0x80 )
            decode(input, p);
        else
            ++p;
        switch ( s )
        {
            case 0:
                if ( c == 0x4c ) {
                    s = 14;
                    r66 = p;
                }
                else if ( c == 0x28 ) {
                    s = 2;
                    r57 = p;
                }
                else if ( c == 0x63 ) {
                    s = 13;
                    r66 = p;
                }
                else if ( c == 0x75 ) {
                    s = 16;
                    r66 = p;
                }
                else if ( c == 0x2d ) {
                    s = 11;
                    r64 = p;
                }
                else if ( c == 0x55 ) {
                    s = 17;
                    r66 = p;
                }
                else if ( c == 0x23 ) {
                    s = 18;
                }
                else if ( c == 0x2e ) {
                    s = 12;
                    r65 = p;
                }
                else if ( c == 0x2c ) {
                    s = 10;
                    r63 = p;
                }
                else if ( c == 0x2a ) {
                    s = 1;
                    r56 = p;
                }
                else if ( c == 0x5d ) {
                    s = 5;
                    r60 = p;
                }
                else if ( c == 0x21 ) {
                    s = 8;
                    r61 = p;
                }
                else if ( c == 0x29 ) {
                    s = 3;
                    r58 = p;
                }
                else if ( c == 0x5b ) {
                    s = 4;
                    r59 = p;
                }
                else if ( c == 0x30 ) {
                    s = 19;
                    r62 = p;
                }
                else if ( c >= 0x31 && c <= 0x39 ) {
                    s = 9;
                    r62 = p;
                }
                else if ( c == 0x22 ) {
                    s = 6;
                }
                else if ( c == 0x27 ) {
                    s = 7;
                }
                else if ( c >= 0x41 && c <= 0x4b || c >= 0x4d && c <= 0x54 || c >= 0x56 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x62 || c >= 0x64 && c <= 0x74 || c >= 0x76 && c <= 0x7a ) {
                    s = 15;
                    r66 = p;
                }
                else
                    return false;
                break;
            case 1:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 129;
                }
                else
                    goto finish1;
                break;
            case 2:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 128;
                }
                else
                    goto finish2;
                break;
            case 3:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 127;
                }
                else
                    goto finish3;
                break;
            case 4:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 126;
                }
                else
                    goto finish4;
                break;
            case 5:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 125;
                }
                else
                    goto finish5;
                break;
            case 6:
                if ( c == 0x5c ) {
                    s = 103;
                }
                else if ( c == 0x22 ) {
                    s = 104;
                    r67 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 105;
                }
                else
                    return false;
                break;
            case 7:
                if ( c == 0x5c ) {
                    s = 81;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x26 || c >= 0x28 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 82;
                }
                else
                    return false;
                break;
            case 8:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 80;
                }
                else
                    goto finish8;
                break;
            case 9:
                if ( c >= 0x30 && c <= 0x39 || c == 0x5f ) {
                    s = 79;
                    r68 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 20;
                }
                else
                    goto finish9;
                break;
            case 10:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 78;
                }
                else
                    goto finish10;
                break;
            case 11:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 77;
                }
                else
                    goto finish11;
                break;
            case 12:
                if ( c == 0x2e ) {
                    s = 75;
                    r69 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 74;
                }
                else
                    goto finish12;
                break;
            case 13:
                if ( c == 0x61 ) {
                    s = 69;
                    r70 = p;
                }
                else if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                }
                else
                    goto finish13;
                break;
            case 14:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                }
                else
                    goto finish14;
                break;
            case 15:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                }
                else
                    goto finish15;
                break;
            case 16:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                }
                else
                    goto finish16;
                break;
            case 17:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                }
                else
                    goto finish17;
                break;
            case 18:
                if ( c == 0x62 ) {
                    s = 37;
                }
                else if ( c == 0x78 ) {
                    s = 33;
                }
                else if ( c == 0x73 ) {
                    s = 38;
                }
                else if ( c == 0x64 ) {
                    s = 36;
                }
                else if ( c == 0x6d ) {
                    s = 32;
                }
                else if ( c == 0x63 ) {
                    s = 35;
                }
                else if ( c == 0x61 ) {
                    s = 34;
                }
                else if ( c == 0x65 ) {
                    s = 39;
                }
                else
                    return false;
                break;
            case 19:
                if ( c == 0x58 || c == 0x78 ) {
                    s = 21;
                }
                else if ( c == 0x42 || c == 0x62 ) {
                    s = 22;
                }
                else if ( c >= 0x30 && c <= 0x37 || c == 0x5f ) {
                    s = 23;
                    r71 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 20;
                }
                else
                    goto finish19;
                break;
            case 20:
                goto finish20;
            case 21:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c == 0x5f || c >= 0x61 && c <= 0x66 ) {
                    s = 29;
                    r72 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 20;
                }
                else
                    goto finish21;
                break;
            case 22:
                if ( c >= 0x30 && c <= 0x31 || c == 0x5f ) {
                    s = 26;
                    r73 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 20;
                }
                else
                    goto finish22;
                break;
            case 23:
                if ( c >= 0x30 && c <= 0x37 || c == 0x5f ) {
                    s = 25;
                    r74 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 24;
                }
                else
                    goto finish23;
                break;
            case 24:
                goto finish24;
            case 25:
                if ( c >= 0x30 && c <= 0x37 || c == 0x5f ) {
                    s = 25;
                    r71 = r74;
                    r74 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 24;
                    r71 = r74;
                }
                else
                    goto finish25;
                break;
            case 26:
                if ( c >= 0x30 && c <= 0x31 || c == 0x5f ) {
                    s = 28;
                    r75 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 27;
                }
                else
                    goto finish26;
                break;
            case 27:
                goto finish27;
            case 28:
                if ( c >= 0x30 && c <= 0x31 || c == 0x5f ) {
                    s = 28;
                    r73 = r75;
                    r75 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 27;
                    r73 = r75;
                }
                else
                    goto finish28;
                break;
            case 29:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c == 0x5f || c >= 0x61 && c <= 0x66 ) {
                    s = 31;
                    r76 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 30;
                }
                else
                    goto finish29;
                break;
            case 30:
                goto finish30;
            case 31:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c == 0x5f || c >= 0x61 && c <= 0x66 ) {
                    s = 31;
                    r72 = r76;
                    r76 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 30;
                    r72 = r76;
                }
                else
                    goto finish31;
                break;
            case 32:
                if ( c == 0x6d ) {
                    s = 64;
                }
                else
                    return false;
                break;
            case 33:
                if ( c == 0x6d ) {
                    s = 60;
                }
                else
                    return false;
                break;
            case 34:
                if ( c == 0x78 ) {
                    s = 48;
                    r77 = p;
                }
                else if ( c == 0x68 || c == 0x6c ) {
                    s = 53;
                    r78 = p;
                }
                else
                    return false;
                break;
            case 35:
                if ( c == 0x78 ) {
                    s = 48;
                    r77 = p;
                }
                else if ( c == 0x64 ) {
                    s = 55;
                }
                else if ( c == 0x68 || c == 0x6c ) {
                    s = 53;
                    r78 = p;
                }
                else
                    return false;
                break;
            case 36:
                if ( c == 0x78 ) {
                    s = 48;
                    r77 = p;
                }
                else if ( c == 0x69 ) {
                    s = 48;
                    r77 = p;
                }
                else if ( c == 0x68 || c == 0x6c ) {
                    s = 53;
                    r78 = p;
                }
                else
                    return false;
                break;
            case 37:
                if ( c == 0x78 ) {
                    s = 48;
                    r77 = p;
                }
                else if ( c == 0x70 ) {
                    s = 48;
                    r77 = p;
                }
                else if ( c == 0x68 || c == 0x6c ) {
                    s = 53;
                    r78 = p;
                }
                else
                    return false;
                break;
            case 38:
                if ( c == 0x69 ) {
                    s = 48;
                    r77 = p;
                }
                else if ( c == 0x70 ) {
                    s = 48;
                    r77 = p;
                }
                else if ( c == 0x74 ) {
                    s = 49;
                }
                else
                    return false;
                break;
            case 39:
                if ( c == 0x69 ) {
                    s = 40;
                }
                else if ( c == 0x66 ) {
                    s = 41;
                }
                else if ( c == 0x64 ) {
                    s = 42;
                }
                else if ( c == 0x62 ) {
                    s = 43;
                }
                else if ( c == 0x73 ) {
                    s = 45;
                }
                else if ( c == 0x61 || c == 0x63 ) {
                    s = 44;
                }
                else
                    return false;
                break;
            case 40:
                if ( c == 0x70 ) {
                    s = 46;
                    r79 = p;
                }
                else
                    return false;
                break;
            case 41:
                if ( c == 0x6c ) {
                    s = 46;
                    r79 = p;
                }
                else
                    return false;
                break;
            case 42:
                if ( c == 0x78 ) {
                    s = 46;
                    r79 = p;
                }
                else if ( c == 0x69 ) {
                    s = 46;
                    r79 = p;
                }
                else
                    return false;
                break;
            case 43:
                if ( c == 0x78 ) {
                    s = 46;
                    r79 = p;
                }
                else if ( c == 0x70 ) {
                    s = 46;
                    r79 = p;
                }
                else
                    return false;
                break;
            case 44:
                if ( c == 0x78 ) {
                    s = 46;
                    r79 = p;
                }
                else
                    return false;
                break;
            case 45:
                if ( c == 0x69 ) {
                    s = 46;
                    r79 = p;
                }
                else if ( c == 0x70 ) {
                    s = 46;
                    r79 = p;
                }
                else
                    return false;
                break;
            case 46:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 47;
                }
                else
                    goto finish46;
                break;
            case 47:
                goto finish47;
            case 48:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 52;
                }
                else
                    goto finish48;
                break;
            case 49:
                if ( c >= 0x30 && c <= 0x37 ) {
                    s = 50;
                    r80 = p;
                }
                else
                    return false;
                break;
            case 50:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 51;
                }
                else
                    goto finish50;
                break;
            case 51:
                goto finish51;
            case 52:
                goto finish52;
            case 53:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 54;
                }
                else
                    goto finish53;
                break;
            case 54:
                goto finish54;
            case 55:
                if ( c == 0x65 ) {
                    s = 56;
                }
                else
                    return false;
                break;
            case 56:
                if ( c == 0x66 ) {
                    s = 57;
                }
                else
                    return false;
                break;
            case 57:
                if ( c == 0x67 ) {
                    s = 58;
                }
                else
                    return false;
                break;
            case 58:
                if ( c == 0x73 ) {
                    s = 59;
                }
                else
                    return false;
                break;
            case 59:
                if ( c == 0x73 ) {
                    s = 48;
                    r77 = p;
                }
                else
                    return false;
                break;
            case 60:
                if ( c == 0x6d ) {
                    s = 61;
                }
                else
                    return false;
                break;
            case 61:
                if ( c >= 0x30 && c <= 0x37 ) {
                    s = 62;
                    r81 = p;
                }
                else
                    return false;
                break;
            case 62:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 63;
                }
                else
                    goto finish62;
                break;
            case 63:
                goto finish63;
            case 64:
                if ( c >= 0x30 && c <= 0x37 ) {
                    s = 65;
                    r82 = p;
                }
                else
                    return false;
                break;
            case 65:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 66;
                }
                else
                    goto finish65;
                break;
            case 66:
                goto finish66;
            case 67:
                goto finish67;
            case 68:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r66 = r70;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                    r66 = r70;
                }
                else
                    goto finish68;
                break;
            case 69:
                if ( c == 0x73 ) {
                    s = 70;
                    r83 = p;
                }
                else if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r66 = r70;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                    r66 = r70;
                }
                else
                    goto finish69;
                break;
            case 70:
                if ( c == 0x74 ) {
                    s = 71;
                    r84 = p;
                }
                else if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r66 = r83;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                    r66 = r83;
                }
                else
                    goto finish70;
                break;
            case 71:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 73;
                    r85 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 72;
                }
                else
                    goto finish71;
                break;
            case 72:
                goto finish72;
            case 73:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5a || c == 0x5f || c >= 0x61 && c <= 0x7a ) {
                    s = 68;
                    r66 = r85;
                    r70 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 67;
                    r66 = r85;
                }
                else
                    goto finish73;
                break;
            case 74:
                goto finish74;
            case 75:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 76;
                }
                else
                    goto finish75;
                break;
            case 76:
                goto finish76;
            case 77:
                goto finish77;
            case 78:
                goto finish78;
            case 79:
                if ( c >= 0x30 && c <= 0x39 || c == 0x5f ) {
                    s = 79;
                    r62 = r68;
                    r68 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 20;
                    r62 = r68;
                }
                else
                    goto finish79;
                break;
            case 80:
                goto finish80;
            case 81:
                if ( c == 0x78 ) {
                    s = 85;
                }
                else if ( c == 0x75 ) {
                    s = 86;
                }
                else if ( c == 0x55 ) {
                    s = 87;
                }
                else if ( c == 0x22 || c == 0x27 || c == 0x3f || c == 0x5c || c >= 0x61 && c <= 0x62 || c == 0x66 || c == 0x6e || c == 0x72 || c == 0x74 || c == 0x76 ) {
                    s = 88;
                }
                else
                    return false;
                break;
            case 82:
                if ( c == 0x27 ) {
                    s = 83;
                    r86 = p;
                }
                else
                    return false;
                break;
            case 83:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 84;
                }
                else
                    goto finish83;
                break;
            case 84:
                goto finish84;
            case 85:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 101;
                }
                else
                    return false;
                break;
            case 86:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 97;
                }
                else
                    return false;
                break;
            case 87:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 89;
                }
                else
                    return false;
                break;
            case 88:
                if ( c == 0x27 ) {
                    s = 83;
                    r86 = p;
                }
                else
                    return false;
                break;
            case 89:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 90;
                }
                else
                    return false;
                break;
            case 90:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 91;
                }
                else
                    return false;
                break;
            case 91:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 92;
                }
                else
                    return false;
                break;
            case 92:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 93;
                }
                else
                    return false;
                break;
            case 93:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 94;
                }
                else
                    return false;
                break;
            case 94:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 95;
                }
                else
                    return false;
                break;
            case 95:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 96;
                }
                else
                    return false;
                break;
            case 96:
                if ( c == 0x27 ) {
                    s = 83;
                    r86 = p;
                }
                else
                    return false;
                break;
            case 97:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 98;
                }
                else
                    return false;
                break;
            case 98:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 99;
                }
                else
                    return false;
                break;
            case 99:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 100;
                }
                else
                    return false;
                break;
            case 100:
                if ( c == 0x27 ) {
                    s = 83;
                    r86 = p;
                }
                else
                    return false;
                break;
            case 101:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 102;
                }
                else
                    return false;
                break;
            case 102:
                if ( c == 0x27 ) {
                    s = 83;
                    r86 = p;
                }
                else
                    return false;
                break;
            case 103:
                if ( c == 0x78 ) {
                    s = 108;
                }
                else if ( c == 0x75 ) {
                    s = 109;
                }
                else if ( c == 0x55 ) {
                    s = 110;
                }
                else if ( c == 0x22 || c == 0x27 || c == 0x3f || c == 0x5c || c >= 0x61 && c <= 0x62 || c == 0x66 || c == 0x6e || c == 0x72 || c == 0x74 || c == 0x76 ) {
                    s = 107;
                }
                else
                    return false;
                break;
            case 104:
                if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 106;
                }
                else
                    goto finish104;
                break;
            case 105:
                if ( c == 0x5c ) {
                    s = 103;
                }
                else if ( c == 0x22 ) {
                    s = 104;
                    r67 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 105;
                }
                else
                    return false;
                break;
            case 106:
                goto finish106;
            case 107:
                if ( c == 0x5c ) {
                    s = 103;
                }
                else if ( c == 0x22 ) {
                    s = 104;
                    r67 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 105;
                }
                else
                    return false;
                break;
            case 108:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 123;
                }
                else
                    return false;
                break;
            case 109:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 119;
                }
                else
                    return false;
                break;
            case 110:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 111;
                }
                else
                    return false;
                break;
            case 111:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 112;
                }
                else
                    return false;
                break;
            case 112:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 113;
                }
                else
                    return false;
                break;
            case 113:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 114;
                }
                else
                    return false;
                break;
            case 114:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 115;
                }
                else
                    return false;
                break;
            case 115:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 116;
                }
                else
                    return false;
                break;
            case 116:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 117;
                }
                else
                    return false;
                break;
            case 117:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 118;
                }
                else
                    return false;
                break;
            case 118:
                if ( c == 0x5c ) {
                    s = 103;
                }
                else if ( c == 0x22 ) {
                    s = 104;
                    r67 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 105;
                }
                else
                    return false;
                break;
            case 119:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 120;
                }
                else
                    return false;
                break;
            case 120:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 121;
                }
                else
                    return false;
                break;
            case 121:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 122;
                }
                else
                    return false;
                break;
            case 122:
                if ( c == 0x5c ) {
                    s = 103;
                }
                else if ( c == 0x22 ) {
                    s = 104;
                    r67 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 105;
                }
                else
                    return false;
                break;
            case 123:
                if ( c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x46 || c >= 0x61 && c <= 0x66 ) {
                    s = 124;
                }
                else
                    return false;
                break;
            case 124:
                if ( c == 0x5c ) {
                    s = 103;
                }
                else if ( c == 0x22 ) {
                    s = 104;
                    r67 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 105;
                }
                else
                    return false;
                break;
            case 125:
                goto finish125;
            case 126:
                goto finish126;
            case 127:
                goto finish127;
            case 128:
                goto finish128;
            case 129:
                goto finish129;
            default:
                assert(0);
        }
    }

    switch ( s )
    {
        case 1: finish1:
        case 129: finish129:
            match = input[0 .. r56];
            token = 0;
            break;
        case 2: finish2:
        case 128: finish128:
            match = input[0 .. r57];
            token = 1;
            break;
        case 3: finish3:
        case 127: finish127:
            match = input[0 .. r58];
            token = 2;
            break;
        case 4: finish4:
        case 126: finish126:
            match = input[0 .. r59];
            token = 4;
            break;
        case 5: finish5:
        case 125: finish125:
            match = input[0 .. r60];
            token = 5;
            break;
        case 104: finish104:
        case 106: finish106:
            match = input[0 .. r67];
            token = 16;
            break;
        case 8: finish8:
        case 80: finish80:
            match = input[0 .. r61];
            token = 14;
            break;
        case 9: finish9:
        case 19: finish19:
        case 20: finish20:
        case 21: finish21:
        case 22: finish22:
            match = input[0 .. r62];
            token = 22;
            break;
        case 10: finish10:
        case 78: finish78:
            match = input[0 .. r63];
            token = 15;
            break;
        case 11: finish11:
        case 77: finish77:
            match = input[0 .. r64];
            token = 27;
            break;
        case 12: finish12:
        case 74: finish74:
            match = input[0 .. r65];
            token = 3;
            break;
        case 13: finish13:
        case 14: finish14:
        case 15: finish15:
        case 16: finish16:
        case 17: finish17:
        case 67: finish67:
            match = input[0 .. r66];
            token = 18;
            break;
        case 23: finish23:
        case 24: finish24:
            match = input[0 .. r71];
            token = 21;
            break;
        case 25: finish25:
            match = input[0 .. r74];
            token = 21;
            break;
        case 26: finish26:
        case 27: finish27:
            match = input[0 .. r73];
            token = 20;
            break;
        case 28: finish28:
            match = input[0 .. r75];
            token = 20;
            break;
        case 29: finish29:
        case 30: finish30:
            match = input[0 .. r72];
            token = 19;
            break;
        case 31: finish31:
            match = input[0 .. r76];
            token = 19;
            break;
        case 46: finish46:
        case 47: finish47:
            match = input[0 .. r79];
            token = 7;
            break;
        case 48: finish48:
        case 52: finish52:
            match = input[0 .. r77];
            token = 8;
            break;
        case 50: finish50:
        case 51: finish51:
            match = input[0 .. r80];
            token = 10;
            break;
        case 53: finish53:
        case 54: finish54:
            match = input[0 .. r78];
            token = 9;
            break;
        case 62: finish62:
        case 63: finish63:
            match = input[0 .. r81];
            token = 12;
            break;
        case 65: finish65:
        case 66: finish66:
            match = input[0 .. r82];
            token = 11;
            break;
        case 68: finish68:
        case 69: finish69:
            match = input[0 .. r70];
            token = 18;
            break;
        case 70: finish70:
            match = input[0 .. r83];
            token = 18;
            break;
        case 71: finish71:
        case 72: finish72:
            match = input[0 .. r84];
            token = 13;
            break;
        case 73: finish73:
            match = input[0 .. r85];
            token = 18;
            break;
        case 75: finish75:
        case 76: finish76:
            match = input[0 .. r69];
            token = 6;
            break;
        case 79: finish79:
            match = input[0 .. r68];
            token = 22;
            break;
        case 83: finish83:
        case 84: finish84:
            match = input[0 .. r86];
            token = 17;
            break;
        default:
            return false;
    }
    return true;
}
// ((?[\t\n\r ]+)).*?
bool wsLexer(string input, out uint token, out string match)
{
    uint s = 0;
    static int r2=-1, r3=-1;

    for ( size_t p = 0, q = 0, p_end = input.length; p < p_end; q = p )
    {
        dchar c = cast(dchar)input[p];
        if ( c & 0x80 )
            decode(input, p);
        else
            ++p;
        switch ( s )
        {
            case 0:
                if ( c >= 0x9 && c <= 0xa || c == 0xd || c == 0x20 ) {
                    s = 1;
                    r2 = p;
                }
                else
                    return false;
                break;
            case 1:
                if ( c >= 0x9 && c <= 0xa || c == 0xd || c == 0x20 ) {
                    s = 3;
                    r3 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 2;
                }
                else
                    goto finish1;
                break;
            case 2:
                goto finish2;
            case 3:
                if ( c >= 0x9 && c <= 0xa || c == 0xd || c == 0x20 ) {
                    s = 3;
                    r2 = r3;
                    r3 = p;
                }
                else if ( c >= 0x9 && c <= 0x13 || c >= 0x20 && c <= 0x7e || c >= 0xa0 && c <= 0x24f || c >= 0x20a3 && c <= 0x20b5 ) {
                    s = 2;
                    r2 = r3;
                }
                else
                    goto finish3;
                break;
            default:
                assert(0);
        }
    }

    switch ( s )
    {
        case 1: finish1:
        case 2: finish2:
            match = input[0 .. r2];
            token = 0;
            break;
        case 3: finish3:
            match = input[0 .. r3];
            token = 0;
            break;
        default:
            return false;
    }
    return true;
}
// generated code end

#line 2996 "D:\src\ddbg_continued\src\expression\expression_apd.d"
// Written in the D programming language

/*
 *  This file has been automatically generated by APaGeD v0.4.2 beta - Attributed Parser Generator for D.
 *
 *  Sections generated from custom input are marked as "generated code" and
 *  are subject to the terms and conditions stated in one of these sections.
 *  The remaining sections are part of the APaGeD package and subject
 *  to the terms and conditions of the corresponding license.
 *
 *  Attributed Parser Generator for D
 *  Copyright (c) 2007 Jascha Wetzel. All rights reserved
 *  License: Artistic License 2.0
 */


version(Tango)
{
    import tango.text.convert.Layout;
    import tango.text.Util;
    import tango.io.Stdout;

    private static Layout!(char) layout;

    static this()
    {
        layout = new Layout!(char);
    }

    string format(string fmt, ...)
    {
        return layout.convert(_arguments, _argptr, fmt);
    }

    alias char[] string;
}
else
{
    import std.string;
    import std.utf;
    debug import std.stdio;
}



/**************************************************************************************************
    Parser
**************************************************************************************************/

typedef uint Token;
alias Token Symbol;

const Token     EPSILON         = 1,
                ALTERN          = 2,
                EOS             = 3,
                FIRST_TOKEN     = 4,
                FIRST_NT        = 0x1000;

// generated code start
/*  Attributed Parser Generator for D
 *  Copyright (c) 2007 Jascha Wetzel. All rights reserved
 *  License: Artistic License 2.0, see license.txt
 */

const uint  MAX_INPUT_DUMP = 70,
            LR_STACK_RESERVE = 100,
            NODE_STACK_RESERVE = 20,
            BRANCH_STACK_RESERVE = 100;

/*******************************************************************************
    Stack based on dynamic array
*******************************************************************************/
struct Stack(T)
{
    size_t  _top;
    T[]     stack;

    void push(T v)
    {
        if ( _top >= stack.length )
            stack.length = stack.length*2+1;
        stack[_top] = v;
        ++_top;
    }

    void push(T[] vs)
    {
        size_t end = _top+vs.length;
        if ( end > stack.length )
            stack.length = end*2;
        stack[_top..end] = vs;
        _top = end;
    }
    alias push opCatAssign;

    void pop(size_t num)
    {
        assert(_top>=num);
        if ( num >= _top )
            _top = 0;
        else
            _top -= num;
    }

    T pop()
    {
        assert(_top>0);
        return stack[--_top];
    }

    T* popPtr()
    {
        assert(_top>0);
        return &stack[--_top];
    }

    T top()
    {
        assert(_top>0);
        return stack[_top-1];
    }

    T* topPtr()
    {
        assert(_top>0);
        return &stack[_top-1];
    }

    bool empty()
    {
        return _top == 0;
    }

    void clear()
    {
        _top = 0;
    }

    size_t length()
    {
        return _top;
    }

    T[] array()
    {
        return stack[0.._top];
    }

    Stack dup()
    {
        Stack s;
        s._top = _top;
        s.stack = stack.dup;
        return s;
    }
}

/**************************************************************************************************
    Information about rules needed for reduction and error handling
**************************************************************************************************/
align(1) struct RuleInfo
{
    bool    ast_node;
    uint    symbol_count,
            nt_count,
            nt_index;
    Symbol[]  symbols;
}

/**************************************************************************************************
    Information about LALR(1) entries needed for debugging
**************************************************************************************************/
align(1) struct EntryInfo
{
    uint    rule_index,
            pos;
}

/**************************************************************************************************
    Exception thrown on parser error
**************************************************************************************************/
class ParserException : Exception
{
    uint    line,
            column;
    string  filename,
            error_message,
            detail;

    this(uint line_, uint column_, string fname, string msg, string dtl="detail")
    {
        version(Tango)
            super(format("{}({}:{}): {}{}", fname, line_, column_, msg, dtl !is null?"\n"~dtl:""));
        else
            super(format("%s(%d:%d): %s%s", fname, line_, column_, msg, dtl !is null?"\n"~dtl:""));
        filename = fname;
        error_message = msg;
        line = line_;
        column = column_;
        detail = dtl;
    }
}

/**************************************************************************************************
    Wraps instantiation of the GLR parser class and the parse call.
**************************************************************************************************/
bool parse(string filename, string input, out SyntaxTree* root, bool detailed=false, bool recover=false, uint tab_width=4)
{
    GLRParser   g, w;
    static if ( is(typeof(WhitespaceGrammar) : GLRParser) )
        w = new WhitespaceGrammar;
    g = new MainGrammar(w, tab_width);
    bool succ = g.parse(filename, input, &root, detailed, recover);
    return succ;
}

/**************************************************************************************************
    GLR parser
**************************************************************************************************/
abstract class GLRParser
{
    struct LRState
    {
        uint    index,
                line,
                column;
    }
    
    struct Node
    {
        SyntaxTree* node;
        bool        sync;
    }

    struct LRBranch
    {
        Stack!(LRState) stack;
        Stack!(Node)    node_stack;
        string          input,
                        lookahead,
                        lookahead_ws;
        uint            line,
                        column,
                        symbol;
        bool            fatal_errors;
        uint            action;
        version(ProfileConflicts)
            uint            last_conflict;
    }
    
    string          filename;
    uint            tab_width;
    
    // operational variables
    string              match,
                        match_ws,
                        lookahead,
                        lookahead_ws;
    SyntaxTree*         syntax_root;
    SyntaxTree[]        syntax_tree_pool;
    size_t              pool_top;
    Stack!(LRState)     stack;
    Stack!(Node)        node_stack;
    Stack!(LRBranch)    branch_stack;
    ParserException[]   recovered_errors;
    bool                recover_from_errors,
                        detailed_errors;

    version(ProfileConflicts) {
        uint[uint]      rr_conflict_counts,
                        sr_conflict_counts,
                        shift_failed_counts,
                        reduce_failed_counts;
        uint            branch_stack_max;
    }

    // grammar data
    GLRParser       ws_parser;
    uint            first_nt;
    RuleInfo[]      rule_infos;
    string[][]      error_message_lists;
    string[]        nt_names,
                    lexeme_names;
    EntryInfo[][]   entry_infos;

    this(GLRParser ws, uint tabw)
    {
        ws_parser = ws;
        tab_width = tabw;
        stack.stack.length = LR_STACK_RESERVE;
        node_stack.stack.length = NODE_STACK_RESERVE;
        branch_stack.stack.length = BRANCH_STACK_RESERVE;
    }

    /**************************************************************************************************
        Gets overridden with a first-longest-match lexical analizer.
    **************************************************************************************************/
    bool function(string, out uint, out string) lexer;

    /**************************************************************************************************
        Gets overridden with the main parser function.
    **************************************************************************************************/
    bool parse(string input) { return false; }
    bool parseWS(ref string input) { return false; }

    /**************************************************************************************************

    **************************************************************************************************/
    bool isErrorSynced(uint state);

    /**************************************************************************************************

    **************************************************************************************************/
    T APDmin(T)(T a, T b) { return a<b?a:b; }
    uint[] lookaheadForNT(uint nt_index, uint state);

    /**************************************************************************************************
        Count lines and columns in str
    **************************************************************************************************/
    uint countLocation(string str, ref uint col)
    {
        uint count;
        dchar linefeed;
        foreach ( c; str )
        {
            if ( c == 10 || c == 13 )
            {
                if ( linefeed == dchar.init || linefeed == c ) {
                    ++count;
                    col = 1;
                    linefeed = c;
                }
                else
                    linefeed = dchar.init;
            }
            else if ( c == 9 ) {
                col += tab_width;
                linefeed = dchar.init;
            }
            else {
                ++col;
                linefeed = dchar.init;
            }
        }
        return count;
    }

    /**************************************************************************************************
        Initiates the parse call.
    **************************************************************************************************/
    final bool parse(string fname, string input, SyntaxTree** root=null, bool detailed=false, bool recover=false)
    {
        filename = fname;
        recover_from_errors = recover;
        detailed_errors = detailed;

        stack.clear;
        node_stack.clear;
        branch_stack.clear;
        pool_top = 0;
        syntax_tree_pool = null;
        recovered_errors = null;

        if ( input.length > 1 )
        {
            if ( input[0 .. 2] == "\xfe\xff" ) {
                // UTF-16BE
                input = input[2 .. $];
            }
            else if ( input[0 .. 2] == "\xff\xfe" )
            {
                if ( input.length > 3 && input[2 .. 4] == "\x00\x00" ) {
                    // UTF-32LE
                    input = input[4 .. $];
                }
                else {
                    // UTF-16LE
                    input = input[2 .. $];
                }
            }
            else if ( input.length > 2 && input[0 .. 3] == "\xef\xbb\xbf" ) {
                // UTF-8
                input = input[3 .. $];
            }
            else if ( input.length > 3 && input[0 .. 4] == "\x00\x00\xfe\xff" ) {
                // UTF-32BE
                input = input[4 .. $];
            }
            else if ( input[0] > 0x7f )
                return false;
        }
        
        stack ~= LRState(0, 1, 1);
        if ( parse(input) )
        {
            if ( syntax_root !is null && root !is null )
            {
                *root = syntax_root;
                debug
                {
                    Stack!(SyntaxTree*) st;
                    st.push(*root);
                    while ( !st.empty )
                    {
                        SyntaxTree* pn = st.pop;
                        foreach ( c; pn._ST_children ) {
                            c.parent = pn;
                            st.push(c);
                        }
                    }
                }
            }
            return true;
        }
        return false;
    }

    /**************************************************************************************************
        Create a node for the syntax tree. Used by the main parse function.
    **************************************************************************************************/
    debug void createNode(uint line, uint column, uint rule_index, uint nt_count, uint nt_index)
    {
        if ( pool_top >= syntax_tree_pool.length )
            syntax_tree_pool.length = syntax_tree_pool.length*2+1;
        auto pn = &syntax_tree_pool[pool_top];
        ++pool_top;
        pn._ST_rule = rule_index;
        pn._ST_line_number = line;
        pn._ST_column_number = column;
        pn._ST_node_name = nt_names[nt_index];

        if ( nt_count > 0 )
        {
            pn._ST_children.length = nt_count;
            foreach ( i, n; node_stack.array[$-nt_count .. $] )
                pn._ST_children[i] = n.node;
            node_stack.pop(nt_count);
        }
        else {
            pn._ST_match = match;
            pn._ST_match_ws = match_ws;
        }
        node_stack ~= Node(pn, false);
    }

    else void createNode(uint line, uint column, uint rule_index, uint nt_count)
    {
        if ( pool_top >= syntax_tree_pool.length )
            syntax_tree_pool.length = syntax_tree_pool.length*2+1;
        auto pn = &syntax_tree_pool[pool_top];
        ++pool_top;
        pn._ST_rule = rule_index;
        pn._ST_line_number = line;
        pn._ST_column_number = column;

        if ( nt_count > 0 )
        {
            pn._ST_children.length = nt_count;
            foreach ( i, n; node_stack.array[$-nt_count .. $] )
                pn._ST_children[i] = n.node;
            node_stack.pop(nt_count);
        }
        else {
            pn._ST_match = match;
            pn._ST_match_ws = match_ws;
        }
        node_stack ~= Node(pn, false);
    }

    /**************************************************************************************************

    **************************************************************************************************/
    string ruleToString(RuleInfo* ri, int pos)
    {
        version(Tango)
            string str = format("{} ->", nt_names[ri.nt_index]);
        else
            string str = format("%s ->", nt_names[ri.nt_index]);
        
        foreach ( i, s; ri.symbols )
        {
            string name;
            if ( s == ALTERN )
                name = "ALTERN";
            else if ( s < FIRST_NT )
                name = lexeme_names[s-EOS];
            else
                name = nt_names[s-FIRST_NT];
            if ( i == pos )
                str ~= " .";
            version(Tango)
                str ~= format(" {}", name);
            else
                str ~= format(" %s", name);
        }
        if ( pos == ri.symbols.length )
            str ~= " .";
        return str;
    }

    /**************************************************************************************************
        Issue an error. Used by the main parse function.
    **************************************************************************************************/
    void error(string input, uint line, uint column, uint error_list, uint symbol, bool fatal=true)
    {
        // collect explicit error messages
        string errors;
        foreach ( i, err; error_message_lists[error_list] )
        {
            if ( i > 0 )
                errors ~= "\n";
            errors ~= err;
        }

        // construct automatic error message
        // if no explicit error message available
        if ( errors.length == 0 )
        {
            bool[string] expected_symbols;
            EntryInfo[] eis = entry_infos[stack.top.index];
            foreach ( ei; eis )
            {
                RuleInfo* ri = &rule_infos[ei.rule_index];
                if ( ei.pos < ri.symbols.length )
                {
                    auto s = ri.symbols[ei.pos];
                    if ( s < FIRST_NT )
                        expected_symbols["\""~lexeme_names[s-EOS]~"\""] = true;
                    else
                        expected_symbols[nt_names[s-FIRST_NT]] = true;
                }
                else
                {
                    foreach ( token; lookaheadForNT(ri.nt_index, stack.top.index) ) {
                        assert(token < FIRST_NT);
                        expected_symbols["\""~lexeme_names[token-EOS]~"\""] = true;
                    }
                }
            }

            string expected_str;
            auto last = expected_symbols.length-1;
            foreach ( i, symname; expected_symbols.keys )
            {
                if ( i > 0 )
                {
                    if ( i == last )
                        expected_str ~= " or ";
                    else 
                        expected_str ~= ", ";
                }
                expected_str ~= symname;
            }
            version(Tango)
                errors = format("found \"{}\", expected {}", lookahead, expected_str);
            else
                errors = format("found \"%s\", expected %s", lookahead, expected_str);
        }

        // construct detail message
        string detail;
        if ( detailed_errors )
        {
            string          lr_stack;
            foreach ( st; stack.array[1..$] )
            {
                version(Tango)
                    lr_stack ~= format("---- State {}{} ({}:{}) ----\n", st.index, isErrorSynced(st.index)?"*":"", st.line, st.column);
                else
                    lr_stack ~= format("---- State %d%s (%d:%d) ----\n", st.index, isErrorSynced(st.index)?"*":"", st.line, st.column);
                EntryInfo[] eis = entry_infos[st.index];
                foreach ( ei; eis )
                    lr_stack ~= ruleToString(&rule_infos[ei.rule_index], ei.pos)~"\n";
            }
            
            string node_stack_str;
            foreach ( i, n; node_stack.array )
            {
                if ( i > 0 )
                    node_stack_str ~= " ";
                node_stack_str ~= nt_names[rule_infos[n.node._ST_rule].nt_index];
                if ( n.sync )
                    node_stack_str ~= "*";
            }

            version(Tango)
                detail = format("input: {}\nlookahead: {}\nlexeme: {}\nAST node stack:\n{}\nLR stack:\n{}",
                    substitute(substitute(input[0..$>MAX_INPUT_DUMP?MAX_INPUT_DUMP:$], "\r", "\\r"), "\n", "\\n"),
                    lookahead, lexeme_names[symbol-EOS],
                    node_stack_str, lr_stack
                );
            else
                detail = format("input: %s\nlookahead: %s\nlexeme: %s\nAST node stack:\n%s\nLR stack:\n%s",
                    replace(replace(input[0..$>MAX_INPUT_DUMP?MAX_INPUT_DUMP:$], "\r", "\\r"), "\n", "\\n"),
                    lookahead, lexeme_names[symbol-EOS],
                    node_stack_str, lr_stack
                );
        }

        // throw error
        if ( fatal ) {
            version(Tango) Stdout.flush;
            throw new ParserException(line, column-lookahead.length, filename, errors, detail);
        }
        else
        {
            version(Tango)
                debug(nonfatal) Stdout.flush.format("\n{}({}:{}): {}\n{}\n", filename, line, column-lookahead.length, errors, detail);
            else
                debug(nonfatal) writefln("\n%s(%d:%d): %s\n%s", filename, line, column-lookahead.length, errors, detail);
        }
    }
}

/**************************************************************************************************
    Generated parsers
**************************************************************************************************/
class MainGrammar : public GLRParser
{
    const ushort[]  action_base =
    [
        0,23,45,0,67,96,125,154,171,198,222,228,245,273,277,291,305,319,347,375,381,389,7,397,414,
        443,0,36,45,67,472,198,1,219,221,501,529,535,552,580,279,586,284,595,624,653,236,8,333,682,
        0,711,9,740,543,769,771,779,781,789,791,799,801,809,811,819,821,829,831,71,839,844,852,142,
        854,862,864,883,5,891,6,893,901,903
    ];
    const ubyte[]  action_check =
    [
        3,0,0,26,32,84,50,50,0,0,0,0,0,0,0,52,26,0,0,0,0,0,0,0,1,1,22,47,0,78,80,1,1,1,1,1,1,1,84,
        27,1,1,1,1,1,1,1,2,28,84,84,1,27,2,2,2,2,2,2,2,84,28,2,2,2,2,2,2,2,4,29,84,84,2,84,4,4,4,4,
        4,4,4,84,29,4,4,4,4,4,4,4,69,69,69,69,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
        5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,84,7,7,7,7,7,73,73,
        73,73,84,84,84,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,31,84,84,84,
        84,9,9,9,9,9,9,84,84,31,9,9,9,9,9,9,9,33,10,34,10,9,10,10,11,84,11,84,11,11,33,46,34,10,46,
        46,46,46,46,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
        12,12,12,12,13,84,13,14,13,13,14,84,40,14,14,40,84,42,84,13,42,15,84,14,15,40,84,15,15,84,
        42,14,14,14,14,16,84,15,16,84,84,16,16,84,84,15,15,15,15,17,84,16,17,84,84,17,17,84,84,16,
        16,16,16,48,84,17,48,48,48,48,48,84,84,17,17,17,17,18,18,18,18,18,18,18,18,18,18,18,18,18,
        18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,19,84,19,84,19,19,20,84,20,20,20,20,84,84,
        21,19,21,21,21,21,20,20,23,84,23,23,23,23,21,21,84,84,84,84,84,84,23,23,24,24,24,24,24,24,
        24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,
        25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,30,30,30,30,30,30,30,30,
        30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,35,35,35,35,35,35,35,35,35,
        35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,36,84,36,84,36,36,37,84,37,84,
        37,37,84,54,84,36,54,54,54,54,54,37,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,
        38,38,38,38,38,38,38,38,38,38,38,39,84,39,84,39,39,41,84,41,84,41,41,84,84,84,39,43,84,84,
        84,84,41,43,43,43,43,43,43,84,84,84,43,43,43,43,43,43,43,84,84,84,84,43,44,44,44,44,44,44,
        44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,45,45,45,45,45,45,45,
        45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,49,49,49,49,49,49,49,49,
        49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,51,51,51,51,51,51,51,51,51,
        51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,53,53,53,53,53,53,53,53,53,53,
        53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,55,84,56,55,84,56,55,55,56,56,57,
        84,58,57,84,58,57,57,58,58,59,84,60,59,84,60,59,59,60,60,61,84,62,61,84,62,61,61,62,62,63,
        84,64,63,84,64,63,63,64,64,65,84,66,65,84,66,65,65,66,66,67,84,68,67,84,68,67,67,68,68,70,
        84,84,70,84,71,70,70,71,71,71,71,71,72,84,74,72,84,74,72,72,74,74,75,84,76,75,84,76,75,75,
        76,76,84,84,84,84,84,84,74,74,74,74,84,77,84,84,77,75,75,77,77,79,84,81,79,84,81,79,79,81,
        81,82,84,83,82,84,83,82,82,83,83
    ];
    const ushort[]  action_data =
    [
        0,129,258,295,287,384,267,179,258,258,258,258,258,258,258,266,295,258,258,258,258,258,258,
        258,129,258,135,135,258,207,209,258,258,258,258,258,258,258,384,296,258,258,258,258,258,
        258,258,257,289,384,384,258,296,257,257,257,257,257,257,257,384,289,257,257,257,257,257,
        257,257,276,288,384,384,257,384,276,276,276,276,276,276,133,384,158,276,276,276,276,276,
        276,276,311,311,311,311,276,385,385,134,385,385,385,385,385,385,385,385,385,385,385,385,
        385,385,385,385,385,385,385,385,385,385,385,385,385,385,386,386,386,386,386,386,386,386,
        386,386,386,386,386,386,386,386,386,386,386,135,386,386,386,386,386,386,386,386,386,297,
        297,384,297,297,297,297,297,142,143,144,145,384,384,384,297,297,387,387,387,137,387,387,
        387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
        387,275,288,384,384,384,384,275,275,275,275,275,275,384,384,158,275,275,275,275,275,275,
        275,290,139,294,280,275,140,280,281,384,281,384,281,281,290,265,294,280,265,175,177,265,
        265,281,388,388,388,388,388,388,141,388,388,388,388,388,388,388,388,388,388,388,388,135,
        142,143,144,145,388,388,388,388,388,282,384,282,300,282,282,300,384,277,300,300,277,384,
        279,384,282,279,301,384,300,301,277,384,301,301,384,279,300,300,300,300,302,384,301,302,
        384,384,302,302,384,384,301,301,301,301,303,384,302,303,384,384,303,303,384,384,302,302,
        302,302,265,384,303,265,175,177,265,265,384,384,303,303,303,303,389,389,389,389,389,389,
        147,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,
        389,284,384,284,384,284,284,298,384,298,298,298,298,384,384,286,284,286,150,286,286,298,
        298,299,384,299,299,299,299,152,286,384,384,384,384,384,384,299,299,385,385,153,385,385,
        385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,
        385,385,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,154,155,135,
        142,143,144,145,390,390,390,390,390,391,391,391,391,391,391,391,391,391,391,391,391,391,
        391,391,391,391,154,155,135,142,143,144,145,391,391,391,391,391,387,387,387,164,387,387,
        387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
        387,285,384,285,384,285,285,278,384,278,384,278,278,384,265,384,285,265,175,177,265,265,
        278,389,389,389,389,389,389,167,389,389,389,389,389,389,389,389,389,389,389,389,389,389,
        389,389,389,389,389,389,389,389,283,384,283,384,283,283,139,384,280,384,140,280,384,384,
        384,283,172,384,384,384,384,280,186,187,188,189,190,191,384,384,384,192,193,135,312,312,
        312,312,384,384,384,384,197,392,129,258,392,392,392,392,392,258,258,258,258,258,258,258,
        392,392,258,258,258,258,258,258,258,392,392,392,392,258,387,387,387,174,387,387,387,387,
        387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,393,
        129,258,393,393,393,393,393,258,258,258,258,258,258,258,393,393,258,258,258,258,258,258,
        258,393,393,393,393,258,394,129,258,394,394,394,394,394,258,258,258,258,258,258,258,394,
        394,258,258,258,258,258,258,258,394,394,394,394,258,389,389,389,389,389,389,182,389,389,
        389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,264,384,
        263,264,384,263,264,264,263,263,260,384,269,260,384,269,260,260,269,269,270,384,271,270,
        384,271,270,270,271,271,272,384,273,272,384,273,272,272,273,273,274,384,292,274,384,292,
        274,274,292,292,293,384,256,293,384,256,293,293,256,256,259,384,268,259,384,268,259,259,
        268,268,262,384,384,262,384,265,262,262,265,175,177,265,265,261,384,310,261,384,310,261,
        261,310,310,308,384,304,308,384,304,308,308,304,304,384,384,384,384,384,384,203,206,208,
        210,384,305,384,384,305,204,205,305,305,306,384,307,306,384,307,306,306,307,307,309,384,
        291,309,384,291,309,309,291,291
    ];
    const ubyte[]  goto_base =
    [
        0,1,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,2,2,0,0,16,0,0,0,2,28,3,0,0,0,0,0,0,0,0,0,16,0,46,
        3,0,2,3,3,39,0,28,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,22,29,0,0,0,0,0,0,0,0,0
    ];
    const ubyte[]  goto_check =
    [
        0,0,1,44,44,46,48,4,6,6,10,10,12,12,21,29,31,6,6,22,47,12,12,12,25,25,41,41,51,51,25,54,25,
        25,25,25,30,30,71,49,49,73,30,49,30,30,30,30,43,74,84,43,43,84,84,84,84,84,84,84,84,43,84,
        43,84,84,84,43
    ];
    const ubyte[]  goto_data =
    [
        3,4,2,45,4,57,56,43,8,10,40,41,18,10,37,35,32,20,21,23,48,20,21,38,28,10,42,41,52,4,29,55,
        33,20,21,34,28,10,72,50,4,74,31,53,33,20,21,34,66,83,84,67,68,84,84,84,84,84,84,84,84,70,
        84,71,84,84,84,73
    ];

    debug(parser) string indent;
    
    this(GLRParser ws=null, uint tab_width=4)
    {
        super(ws, tab_width);
        lexer = &mainLexer;
        first_nt = 32;
        nt_names =
        [
            "Expr","Deref","DotChain","RefExpr","Args","Register","RegName","Cast","Type",
            "BaseType","QuantList","Quantifier","TplParams","TplParams2","TplParam","Lit","StrLit",
            "Ident","FQNIdent","Integer","IntegerSuffix","Sign","!LRstart"
        ];
        lexeme_names =
        [
            "EOS","\\*","\\(","\\)","\\.","\\[","\\]","\\.\\.","#(e[abcd]x|e[ds]i|e[bs]p|eip|efl)",
            "#([abcd]x|[ds]i|[bs]p|(cdefgs)s)","#[abcd][hl]","#st[0-7]","#mm[0-7]","#xmm[0-7]",
            "cast","!",",",
            "\"(([^\"\\\\]*(\\\\(['\"\\?\\\\abfnrtv]|(x[0-9a-fA-F]{2})|(u[0-9a-fA-F]{4})|(U[0-9a-fA-F]{8})))?)*)\"",
            "'(([^'\\\\]|(\\\\(['\"\\?\\\\abfnrtv]|(x[0-9a-fA-F]{2})|(u[0-9a-fA-F]{4})|(U[0-9a-fA-F]{8})))))'",
            "[a-zA-Z_][_a-zA-Z0-9]*","0[xX][0-9a-fA-F_]+","0[bB][01_]+","0[0-7_]+",
            "0|([1-9][0-9_]*)","L","u","U","[uU]","\\-"
        ];
        entry_infos =
        [
            cast(EntryInfo[])[EntryInfo(2,0)],[EntryInfo(1,1),EntryInfo(2,0)],[EntryInfo(1,2)],[EntryInfo(57,1)],[
            EntryInfo(0,1),EntryInfo(20,0)],[EntryInfo(19,1)],[EntryInfo(19,2)],[EntryInfo(41,1)],[EntryInfo(19,3)],[
            EntryInfo(19,4)],[EntryInfo(21,1),EntryInfo(24,0)],[EntryInfo(25,1)],[EntryInfo(26,1),EntryInfo(27,1)
            ,EntryInfo(28,1)],[EntryInfo(26,2)],[EntryInfo(44,1)],[EntryInfo(45,1)],[EntryInfo(46,1)],[
            EntryInfo(47,1)],[EntryInfo(28,2)],[EntryInfo(28,3)],[EntryInfo(42,1)],[EntryInfo(22,1),EntryInfo(43,1)
            ,EntryInfo(30,0)],[EntryInfo(43,2)],[EntryInfo(43,3)],[EntryInfo(29,1)],[EntryInfo(29,2)],[
            EntryInfo(39,1)],[EntryInfo(40,1)],[EntryInfo(33,1)],[EntryInfo(29,3),EntryInfo(32,0)],[
            EntryInfo(31,1)],[EntryInfo(31,2),EntryInfo(32,0)],[EntryInfo(31,3)],[EntryInfo(34,1)],[
            EntryInfo(38,1)],[EntryInfo(29,4)],[EntryInfo(29,5)],[EntryInfo(22,2)],[EntryInfo(27,2)],[
            EntryInfo(27,3)],[EntryInfo(21,2)],[EntryInfo(23,1),EntryInfo(24,0)],[EntryInfo(23,2)],[
            EntryInfo(0,2),EntryInfo(56,0)],[EntryInfo(4,1),EntryInfo(2,0)],[EntryInfo(4,2)],[EntryInfo(4,3)
            ,EntryInfo(9,0)],[EntryInfo(7,1)],[EntryInfo(7,2),EntryInfo(9,0)],[EntryInfo(8,1),EntryInfo(2,0)],[
            EntryInfo(10,1),EntryInfo(11,1)],[EntryInfo(10,2),EntryInfo(2,0)],[EntryInfo(10,3)],[EntryInfo(8,2)],[
            EntryInfo(8,3),EntryInfo(9,0)],[EntryInfo(8,4)],[EntryInfo(7,3)],[EntryInfo(4,4)],[EntryInfo(13,1)],[
            EntryInfo(14,1)],[EntryInfo(15,1)],[EntryInfo(16,1)],[EntryInfo(17,1)],[EntryInfo(18,1)],[
            EntryInfo(36,1)],[EntryInfo(37,1)],[EntryInfo(0,3)],[EntryInfo(3,1)],[EntryInfo(12,1)],[
            EntryInfo(55,1)],[EntryInfo(6,1)],[EntryInfo(5,1),EntryInfo(9,0)],[EntryInfo(5,2)],[EntryInfo(35,1)],[
            EntryInfo(35,2),EntryInfo(54,0)],[EntryInfo(48,1),EntryInfo(49,1),EntryInfo(52,1)],[EntryInfo(48,2)],[
            EntryInfo(49,2)],[EntryInfo(50,1)],[EntryInfo(50,2)],[EntryInfo(51,1)],[EntryInfo(51,2)],[
            EntryInfo(53,1)],[EntryInfo(35,3)]
        ];
        rule_infos =
        [
            RuleInfo(true,3,3,0,[4097,4103,4098]),RuleInfo(true,2,1,1,[4,4097]),
            RuleInfo(true,0,0,1,[]),RuleInfo(true,1,1,2,[4101]),RuleInfo(true,4,2,2,[5,4096,6,4099]),
            RuleInfo(true,2,2,2,[4113,4099]),RuleInfo(true,1,1,2,[4111]),RuleInfo(true,3,2,3,[7,4113,4099]),
            RuleInfo(true,4,2,3,[8,4100,9,4099]),RuleInfo(true,0,0,3,[]),RuleInfo(true,3,2,4,[4096,10,4096]),
            RuleInfo(true,1,1,4,[4096]),RuleInfo(true,1,1,5,[4102]),RuleInfo(true,1,0,6,[11]),
            RuleInfo(true,1,0,6,[12]),RuleInfo(true,1,0,6,[13]),RuleInfo(true,1,0,6,[14]),
            RuleInfo(true,1,0,6,[15]),RuleInfo(true,1,0,6,[16]),RuleInfo(true,4,1,7,[17,5,4104,6]),
            RuleInfo(true,0,0,7,[]),RuleInfo(true,2,2,8,[4105,4106]),RuleInfo(true,2,2,9,[4114,4108]),
            RuleInfo(true,2,2,10,[4107,4106]),RuleInfo(true,0,0,10,[]),RuleInfo(true,1,0,11,[4]),
            RuleInfo(true,2,0,11,[8,9]),RuleInfo(true,3,1,11,[8,4115,9]),RuleInfo(true,3,1,11,[8,4104,9]),
            RuleInfo(true,5,2,12,[18,5,4110,4109,6]),RuleInfo(true,0,0,12,[]),
            RuleInfo(true,3,2,13,[19,4110,4109]),RuleInfo(true,0,0,13,[]),RuleInfo(true,1,1,14,[4104]),
            RuleInfo(true,1,1,14,[4112]),RuleInfo(true,3,3,15,[4117,4115,4116]),RuleInfo(true,1,0,15,[20]),
            RuleInfo(true,1,0,15,[21]),RuleInfo(true,1,1,16,[4115]),RuleInfo(true,1,0,16,[20]),
            RuleInfo(true,1,0,16,[21]),RuleInfo(true,1,0,17,[22]),RuleInfo(true,1,1,18,[4113]),
            RuleInfo(true,3,2,18,[4114,7,4113]),RuleInfo(true,1,0,19,[23]),RuleInfo(true,1,0,19,[24]),
            RuleInfo(true,1,0,19,[25]),RuleInfo(true,1,0,19,[26]),RuleInfo(true,2,0,20,[27,28]),
            RuleInfo(true,2,0,20,[27,29]),RuleInfo(true,2,0,20,[28,27]),RuleInfo(true,2,0,20,[29,27]),
            RuleInfo(true,1,0,20,[27]),RuleInfo(true,1,0,20,[30]),RuleInfo(true,0,0,20,[]),
            RuleInfo(true,1,0,21,[31]),RuleInfo(true,0,0,21,[]),RuleInfo(true,1,1,22,[4096])
        ];
        error_message_lists = [
            cast(string[])null,
            ["(%d) ( expected"],
            ["(%d) Type expected"],
            ["(%d) ) expected"],
            ["(%d) ], type or size expected"],
            ["(%d) ] expected"],
            ["(%d) Template parameters expected"],
            ["(%d) Template parameter expected"],
            ["(%d) Expression expected after ("],
            ["(%d) Arguments expected after ["],
            ["(%d) Second slice argument expected"]
        ];
    }

    uint[] lookaheadForNT(uint nt_index, uint state)
    {
        uint[] tokens;
        auto b = action_base[state];
        auto m = APDmin(action_check.length, cast(size_t)b+first_nt);
        foreach ( i, check; action_check[b .. m] )
        {
            if ( check == state && (action_data[b+i] & 384) == 256 )
                tokens ~= i+EOS;
        }
        return tokens;
    }

    override bool isErrorSynced(uint state)
    {
        switch ( state )
        {
            case 0:
                return true;
            default:
                break;
        }
        return false;
    }

    override bool parse(string input)
    {
        debug(parser) indent ~= " ";
        scope(exit) debug(parser) indent = indent[0..$-1];

        bool    fatal_errors = true;
        uint    line = 1,
                column = 1,
                symbol;

        void reduce(uint rule)
        {
            version(Tango)
                debug(parser) Stdout.format("{}reduce {} {}\n", indent, rule, ruleToString(&rule_infos[rule], -1));
            else
                debug(parser) writefln("%sreduce %d %s", indent, rule, ruleToString(&rule_infos[rule], -1));
            auto ri = &rule_infos[rule];
            uint    reduce_line,
                    reduce_column;
            if ( ri.symbol_count > 0 ) {
                reduce_line = stack.array[$-ri.symbol_count].line;
                reduce_column = stack.array[$-ri.symbol_count].column;
                stack.pop(ri.symbol_count);
            }
            else {
                reduce_line = stack.top.line;
                reduce_column = stack.top.column;
            }

            auto b = goto_base[stack.top.index];
            b += ri.nt_index;
            debug(parser)
            {
                if ( b < goto_check.length && goto_check[b] == stack.top.index ) {
                    stack ~= LRState(goto_data[b], reduce_line, reduce_column);

                version(Tango)
                    Stdout.format("{}goto {}\n", indent, stack.top.index);
                else
                    writefln("%sgoto %d", indent, stack.top.index);
                }
                else
                    assert(0);
            }
            else
                stack ~= LRState(goto_data[b], reduce_line, reduce_column);
            if ( ri.ast_node ) {
                debug createNode(reduce_line, reduce_column, rule, ri.nt_count, ri.nt_index);
                else createNode(reduce_line, reduce_column, rule, ri.nt_count);
            }
            else if ( ri.nt_count > 0 )
                node_stack.pop(ri.nt_count);
        }

        void branch(uint action)
        {
            version(ProfileConflicts)
            {
                if ( branch_stack.length > branch_stack_max )
                    branch_stack_max = branch_stack.length;
            }
            if ( (action & 128) > 0 )
            {
                version(ProfileConflicts)
                    sr_conflict_counts[stack.top.index]++;
                version(Tango) debug(parser) Stdout.format("{}branch shift conflict\n", indent);
                else debug(parser) writefln("%sbranch shift conflict", indent);
            }
            else
            {
                version(ProfileConflicts)
                    rr_conflict_counts[stack.top.index]++;
                version(Tango) debug(parser) Stdout.format("{}branch reduce conflict\n", indent);
                else debug(parser) writefln("%sbranch reduce conflict", indent);
            }
            version(ProfileConflicts)
                branch_stack ~= LRBranch(
                    stack.dup, node_stack.dup,
                    input, lookahead, lookahead_ws,
                    line, column, symbol, fatal_errors, 
                    action, stack.top.index | (action & 384)
                );
            else
                branch_stack ~= LRBranch(
                    stack.dup, node_stack.dup,
                    input, lookahead, lookahead_ws,
                    line, column, symbol, fatal_errors, 
                    action
                );
            fatal_errors = false;
        }

        string prev_input = input;
        parseLoop: while ( true )
        {
            if ( symbol == 0 )
            {
            readSymbol:
                match = lookahead;
                match_ws = lookahead_ws;
                lookahead_ws = input;
                static if ( is(typeof(WhitespaceGrammar) : GLRParser) )
                    ws_parser.parseWS(input);
                version(Tango)
                    debug(lexer) Stdout.format("WS: '{}'\n", lookahead_ws[0 .. $-input.length]);
                else
                    debug(lexer) writefln("WS: '%s'", lookahead_ws[0 .. $-input.length]);
                symbol = EOS;
                if ( input.length == 0 )
                    lookahead = null;
                else if ( lexer(input, symbol, lookahead) ) {
                    symbol += FIRST_TOKEN;
                    line += countLocation(lookahead_ws[0 .. $-input.length], column);
                    lookahead_ws = lookahead_ws[0 .. $-input.length+lookahead.length];
                }
                if ( symbol == 0 )
                    throw new ParserException(line, column, filename, "Invalid token", input[0..$>MAX_INPUT_DUMP?MAX_INPUT_DUMP:$]);
                prev_input = input;
                input = input[lookahead.length..$];
            }
            debug(parser)
            {
                string node_stack_str;
                foreach ( n; node_stack.array )
                    node_stack_str ~= " "~n.node._ST_node_name~(n.sync?"*":"");
                version(Tango)
                    Stdout.format("\n{}state {}\n{}nodes {}\n{}lkahd ({}) {}\n{}input ({}:{}) {}\n",
                        indent, stack.top.index,
                        indent, node_stack_str,
                        indent, symbol, lookahead,
                        indent, line, column,
                        substitute(substitute(input[0..$>MAX_INPUT_DUMP?MAX_INPUT_DUMP:$], "\r", "\\r"), "\n", "\\n")
                    );
                else
                    writefln("\n%sstate %d\n%snodes %s\n%slkahd (%d) %s\n%sinput (%d:%d) %s",
                        indent, stack.top.index,
                        indent, node_stack_str,
                        indent, symbol, lookahead,
                        indent, line, column,
                        replace(replace(input[0..$>MAX_INPUT_DUMP?MAX_INPUT_DUMP:$], "\r", "\\r"), "\n", "\\n")
                    );
            }

            auto state = stack.top.index;
            auto b = action_base[state];
            uint action = 384;
            b += symbol-EOS;
            if ( b < action_check.length && action_check[b] == state )
                action = action_data[b];

            actionSwitch: switch ( action & 384 )
            {
                case 128:
                    action &= 127;
                    version(Tango) debug(parser) Stdout.format("{}shift {}\n", indent, action);
                    else debug(parser) writefln("%sshift %d", indent, action);
                    stack ~= LRState(action, line, column);
                    symbol = 0;
                    continue parseLoop;
                case 256:
                    action &= 127;
                    version(Tango) debug(parser) Stdout.format("{}reduce {} {}\n", indent, action, ruleToString(&rule_infos[action], -1));
                    else debug(parser) writefln("%sreduce %d %s", indent, action, ruleToString(&rule_infos[action], -1));
                    auto ri = &rule_infos[action];
                    uint    reduce_line,
                            reduce_column;
                    if ( ri.symbol_count > 0 ) {
                        reduce_line = stack.array[$-ri.symbol_count].line;
                        reduce_column = stack.array[$-ri.symbol_count].column;
                        stack.pop(ri.symbol_count);
                    }
                    else {
                        reduce_line = stack.array[$-1].line;
                        reduce_column = stack.array[$-1].column;
                    }

                    state = stack.top.index;
                    b = goto_base[state];
                    b += ri.nt_index;
                    debug(parser)
                    {
                        if ( b < goto_check.length && goto_check[b] == state ) {
                            stack ~= LRState(goto_data[b], reduce_line, reduce_column);
                        version(Tango)
                            Stdout.format("{}goto {}\n", indent, stack.top.index);
                        else
                            writefln("%sgoto %d", indent, stack.top.index);
                        }
                        else
                            assert(0);
                    }
                    else
                        stack ~= LRState(goto_data[b], reduce_line, reduce_column);
                    if ( ri.ast_node ) {
                        debug createNode(reduce_line, reduce_column, action, ri.nt_count, ri.nt_index);
                        else createNode(reduce_line, reduce_column, action, ri.nt_count);
                    }
                    else if ( ri.nt_count > 0 )
                        node_stack.pop(ri.nt_count);

                    continue parseLoop;
                case 384:
                    action &= 127;
                    if ( fatal_errors || action > 0 )
                    {
                        if ( recover_from_errors )
                        {
                            try error(prev_input, line, column, action, symbol);
                            catch ( ParserException e )
                                recovered_errors ~= e;
                            version(Tango)
                                debug(nonfatal) Stdout.format("recovering from error:\n{}\n", recovered_errors[$-1]);
                            else
                                debug(nonfatal) writefln("recovering from error:\n%s", recovered_errors[$-1]);
                            while ( !stack.empty && !isErrorSynced(stack.top.index) )
                                stack.pop;
                            while ( !node_stack.empty && !node_stack.top.sync )
                                node_stack.pop;
                            symbol = 0;
                            continue parseLoop;
                        }
                        else {
                            input = prev_input;
                            error(input, line, column, action, symbol);
                        }
                    }
                    else
                    {
                        debug(nonfatal) {
                            input = prev_input;
                            error(input, line, column, action, symbol, false);
                        }
                    }
                    if ( branch_stack.length == 0 ) {
                        input = prev_input;
                        return false;
                    }
                    auto prev = branch_stack.popPtr;
                    stack           = prev.stack;
                    node_stack      = prev.node_stack;
                    input           = prev.input;
                    prev_input      = input;
                    lookahead       = prev.lookahead;
                    lookahead_ws    = prev.lookahead_ws;
                    line            = prev.line;
                    column          = prev.column;
                    symbol          = prev.symbol;
                    fatal_errors    = prev.fatal_errors;
                    action          = prev.action;

                    version(ProfileConflicts)
                    {
                        if ( (prev.last_conflict & 128) > 0 )
                            shift_failed_counts[prev.last_conflict & 127]++;
                        else
                            reduce_failed_counts[prev.last_conflict & 127]++;
                    }
                    goto actionSwitch;
                default:
                    break;
            }

            switch ( action )
            {
                case 0:
                    version(Tango)
                        debug(parser) Stdout.format("{}accept\n", indent);
                    else
                        debug(parser) writefln("%saccept", indent);
                    syntax_root = node_stack.top.node;
                    input = prev_input;
                    return true;
                default:
                    assert(0);
            }
        }
        assert(0);
    }
}

class WhitespaceGrammar : public GLRParser
{
    const ubyte[]  action_base =
    [
        0,0,2
    ];
    const ubyte[]  action_check =
    [
        1,0,2
    ];
    const ubyte[]  action_data =
    [
        4,3,0
    ];
    const ubyte[]  goto_base =
    [
        0,0,0
    ];
    const ubyte[]  goto_check =
    [
        0
    ];
    const ubyte[]  goto_data =
    [
        2
    ];

    debug(parser) string indent;
    
    this(GLRParser ws=null, uint tab_width=4)
    {
        super(ws, tab_width);
        lexer = &wsLexer;
        first_nt = 5;
        nt_names =
        [
            "Whitespace","!LRstart"
        ];
        lexeme_names =
        [
            "EOS","[\\t\\n\\r ]+"
        ];
        entry_infos =
        [
            cast(EntryInfo[])[],[EntryInfo(0,1)],[EntryInfo(1,1)]
        ];
        rule_infos =
        [
            RuleInfo(true,1,0,0,[4]),RuleInfo(true,1,1,1,[4096])
        ];
        error_message_lists = [
            cast(string[])null
        ];
    }

    uint[] lookaheadForNT(uint nt_index, uint state)
    {
        uint[] tokens;
        auto b = action_base[state];
        auto m = APDmin(action_check.length, cast(size_t)b+first_nt);
        foreach ( i, check; action_check[b .. m] )
        {
            if ( check == state && (action_data[b+i] & 6) == 4 )
                tokens ~= i+EOS;
        }
        return tokens;
    }

    override bool isErrorSynced(uint state)
    {
        switch ( state )
        {
            case 0:
                return true;
            default:
                break;
        }
        return false;
    }

    override bool parseWS(ref string input)
    {
        stack.clear;
        stack ~= LRState(0, 1, 1);

        debug(parser) indent ~= " ";
        scope(exit) debug(parser) indent = indent[0..$-1];

        bool    fatal_errors = true;
        uint    line = 1,
                column = 1,
                symbol;

        void reduce(uint rule)
        {
            version(Tango)
                debug(parser) Stdout.format("{}reduce {} {}\n", indent, rule, ruleToString(&rule_infos[rule], -1));
            else
                debug(parser) writefln("%sreduce %d %s", indent, rule, ruleToString(&rule_infos[rule], -1));
            auto ri = &rule_infos[rule];
            uint    reduce_line,
                    reduce_column;
            if ( ri.symbol_count > 0 ) {
                reduce_line = stack.array[$-ri.symbol_count].line;
                reduce_column = stack.array[$-ri.symbol_count].column;
                stack.pop(ri.symbol_count);
            }
            else {
                reduce_line = stack.top.line;
                reduce_column = stack.top.column;
            }

            auto b = goto_base[stack.top.index];
            b += ri.nt_index;
            debug(parser)
            {
                if ( b < goto_check.length && goto_check[b] == stack.top.index ) {
                    stack ~= LRState(goto_data[b], reduce_line, reduce_column);
                }
                else
                    assert(0);
            }
            else
                stack ~= LRState(goto_data[b], reduce_line, reduce_column);
        }

        void branch(uint action)
        {
            version(ProfileConflicts)
            {
                if ( branch_stack.length > branch_stack_max )
                    branch_stack_max = branch_stack.length;
            }
            if ( (action & 2) > 0 )
            {
                version(ProfileConflicts)
                    sr_conflict_counts[stack.top.index]++;
            }
            else
            {
                version(ProfileConflicts)
                    rr_conflict_counts[stack.top.index]++;
            }
            version(ProfileConflicts)
                branch_stack ~= LRBranch(
                    stack.dup, node_stack.dup,
                    input, lookahead, lookahead_ws,
                    line, column, symbol, fatal_errors, 
                    action, stack.top.index | (action & 6)
                );
            else
                branch_stack ~= LRBranch(
                    stack.dup, node_stack.dup,
                    input, lookahead, lookahead_ws,
                    line, column, symbol, fatal_errors, 
                    action
                );
            fatal_errors = false;
        }

        string prev_input = input;
        parseLoop: while ( true )
        {
            if ( symbol == 0 )
            {
            readSymbol:
                match = lookahead;
                match_ws = lookahead_ws;
                symbol = EOS;
                if ( input.length == 0 )
                    lookahead = null;
                else if ( lexer(input, symbol, lookahead) ) {
                    symbol += FIRST_TOKEN;
                }
                if ( symbol == 0 )
                    return false;
                prev_input = input;
                input = input[lookahead.length..$];
            }

            auto state = stack.top.index;
            auto b = action_base[state];
            uint action = 6;
            b += symbol-EOS;
            if ( b < action_check.length && action_check[b] == state )
                action = action_data[b];

            actionSwitch: switch ( action & 6 )
            {
                case 2:
                    action &= 1;
                    stack ~= LRState(action, line, column);
                    symbol = 0;
                    continue parseLoop;
                case 4:
                    action &= 1;
                    auto ri = &rule_infos[action];
                    uint    reduce_line,
                            reduce_column;
                    if ( ri.symbol_count > 0 ) {
                        reduce_line = stack.array[$-ri.symbol_count].line;
                        reduce_column = stack.array[$-ri.symbol_count].column;
                        stack.pop(ri.symbol_count);
                    }
                    else {
                        reduce_line = stack.array[$-1].line;
                        reduce_column = stack.array[$-1].column;
                    }

                    state = stack.top.index;
                    b = goto_base[state];
                    b += ri.nt_index;
                    debug(parser)
                    {
                        if ( b < goto_check.length && goto_check[b] == state ) {
                            stack ~= LRState(goto_data[b], reduce_line, reduce_column);
                        }
                        else
                            assert(0);
                    }
                    else
                        stack ~= LRState(goto_data[b], reduce_line, reduce_column);

                    continue parseLoop;
                case 6:
                    action &= 1;
                    input = prev_input;
                    if ( branch_stack.length == 0 ) {
                        input = prev_input;
                        return false;
                    }
                    auto prev = branch_stack.popPtr;
                    stack           = prev.stack;
                    node_stack      = prev.node_stack;
                    input           = prev.input;
                    prev_input      = input;
                    lookahead       = prev.lookahead;
                    lookahead_ws    = prev.lookahead_ws;
                    line            = prev.line;
                    column          = prev.column;
                    symbol          = prev.symbol;
                    fatal_errors    = prev.fatal_errors;
                    action          = prev.action;

                    version(ProfileConflicts)
                    {
                        if ( (prev.last_conflict & 2) > 0 )
                            shift_failed_counts[prev.last_conflict & 1]++;
                        else
                            reduce_failed_counts[prev.last_conflict & 1]++;
                    }
                    goto actionSwitch;
                default:
                    break;
            }

            switch ( action )
            {
                case 0:
                    input = prev_input;
                    return true;
                default:
                    assert(0);
            }
        }
        assert(0);
    }
}


// generated code end