AddType addType = AddType.yes;
bool mute = false;
Hooks hooks;
- bool hasErrors = false;
-
- /// Called when encountering an error / unrecognized mangle.
- ///
- /// Currently, errors simply make `demangle` return
- /// the input string, but the `msg` string can be used for debugging.
- /// As a future enhancement, error handlers can be supplied through `Hooks`
- void error(string msg = "error")
- {
- hasErrors = true;
- }
//////////////////////////////////////////////////////////////////////////
// Type Testing and Conversion
TypeTuple:
B Number Arguments
*/
- BufSlice parseType() return scope nothrow
+ BufSlice parseType(out bool errStatus) return scope nothrow
{
static immutable string[23] primitives = [
"char", // a
static if (__traits(hasMember, Hooks, "parseType"))
{
- auto n = hooks.parseType(this, null);
- if (this.hasErrors)
+ auto n = hooks.parseType(errStatus, this, null);
+ if (errStatus)
return dst.bslice_empty;
else
if (n !is null)
auto beg = dst.length;
auto t = front;
- BufSlice parseBackrefType(scope BufSlice delegate() pure @safe nothrow parseDg) pure @safe nothrow
+ BufSlice parseBackrefType(out string errStatus, scope BufSlice delegate(bool err_flag) pure @safe nothrow parseDg) pure @safe nothrow
{
if (pos == brp)
{
- this.error("recursive back reference");
+ errStatus = "recursive back reference";
return dst.bslice_empty;
}
auto n = decodeBackref();
if (n == 0 || n > pos)
{
- this.error("invalid back reference");
+ errStatus = "invalid back reference";
return dst.bslice_empty;
}
pos = refPos - n;
brp = refPos;
- auto ret = parseDg();
+ bool err_flag;
+ auto ret = parseDg(err_flag);
+ if (err_flag)
+ {
+ errStatus = "parseDg error";
+ return dst.bslice_empty;
+ }
+
return ret;
}
+ // call parseType() and return error if occured
+ enum parseTypeOrF = "parseType(errStatus); if (errStatus) return dst.bslice_empty;";
+
switch ( t )
{
case 'Q': // Type back reference
- auto r = parseBackrefType(() => parseType());
+ string errMsg;
+ auto r = parseBackrefType(errMsg, (e_flag) => parseType(e_flag));
+ if (errMsg !is null)
+ return dst.bslice_empty;
return r;
case 'O': // Shared (O Type)
popFront();
put( "shared(" );
- parseType();
+ mixin(parseTypeOrF);
put( ')' );
return dst[beg .. $];
case 'x': // Const (x Type)
popFront();
put( "const(" );
- parseType();
+ mixin(parseTypeOrF);
put( ')' );
return dst[beg .. $];
case 'y': // Immutable (y Type)
popFront();
put( "immutable(" );
- parseType();
+ mixin(parseTypeOrF);
put( ')' );
return dst[beg .. $];
case 'N':
popFront();
// TODO: Anything needed here?
put( "inout(" );
- parseType();
+ mixin(parseTypeOrF);
put( ')' );
return dst[beg .. $];
case 'h': // TypeVector (Nh Type)
popFront();
put( "__vector(" );
- parseType();
+ mixin(parseTypeOrF);
put( ')' );
return dst[beg .. $];
default:
- error();
+ errStatus = true;
return dst.bslice_empty;
}
case 'A': // TypeArray (A Type)
popFront();
- parseType();
+ mixin(parseTypeOrF);
put( "[]" );
return dst[beg .. $];
case 'G': // TypeStaticArray (G Number Type)
popFront();
auto num = sliceNumber();
- parseType();
+ mixin(parseTypeOrF);
put( '[' );
put( num );
put( ']' );
case 'H': // TypeAssocArray (H Type Type)
popFront();
// skip t1
- auto tx = parseType();
- if (this.hasErrors)
+ auto tx = parseType(errStatus);
+ if (errStatus)
return dst.bslice_empty;
- parseType();
+ mixin(parseTypeOrF);
put( '[' );
shift(tx);
put( ']' );
return dst[beg .. $];
case 'P': // TypePointer (P Type)
popFront();
- parseType();
+ mixin(parseTypeOrF);
put( '*' );
return dst[beg .. $];
case 'F': case 'U': case 'W': case 'V': case 'R': // TypeFunction
- bool errStatus;
auto r = parseTypeFunction(errStatus);
if (errStatus)
- {
- error();
return dst.bslice_empty;
- }
return r;
case 'C': // TypeClass (C LName)
case 'S': // TypeStruct (S LName)
case 'E': // TypeEnum (E LName)
case 'T': // TypeTypedef (T LName)
popFront();
- bool errStatus;
parseQualifiedName(errStatus);
if (errStatus)
return dst.bslice_empty;
auto modifiers = parseModifier();
if ( front == 'Q' )
{
- bool errStatus;
- auto r = parseBackrefType(() => parseTypeFunction(errStatus, IsDelegate.yes));
- if (errStatus)
- {
- error();
+ string errMsg;
+ auto r = parseBackrefType(errMsg, (e_flag) => parseTypeFunction(e_flag, IsDelegate.yes));
+ if (errMsg !is null)
return dst.bslice_empty;
- }
return r;
}
else
{
- bool errStatus;
parseTypeFunction(errStatus, IsDelegate.yes);
- if (this.hasErrors || errStatus)
+ if (errStatus)
return dst.bslice_empty;
}
put( "ucent" );
return dst[beg .. $];
default:
- error("unknown type");
+ errStatus = true;
return dst.bslice_empty;
}
}
- error("unknown type");
+ errStatus = true;
return dst.bslice_empty;
}
}
pos--;
}
+ // call parseType() and return error if occured
+ enum parseTypeOrF = "parseType(errStatus); if (errStatus) return;";
+
switch ( front )
{
case 'I': // in (I Type)
put("in ");
if (front == 'K')
goto case;
- parseType();
+ mixin(parseTypeOrF);
continue;
case 'K': // ref (K Type)
popFront();
put( "ref " );
- parseType();
+ mixin(parseTypeOrF);
continue;
case 'J': // out (J Type)
popFront();
put( "out " );
- parseType();
+ mixin(parseTypeOrF);
continue;
case 'L': // lazy (L Type)
popFront();
put( "lazy " );
- parseType();
+ mixin(parseTypeOrF);
continue;
default:
- parseType();
+ mixin(parseTypeOrF);
}
}
}
// e.g. `delegate(int) @safedouble ' => 'double delegate(int) @safe'
{
auto retbeg = dst.length;
- parseType();
- if (this.hasErrors)
+ parseType(errStatus);
+ if (errStatus)
return dst.bslice_empty;
put(' ');
shift(dst[argbeg .. retbeg]);
// f MangledName
// A function literal symbol
popFront();
- parseMangledName(false, 1);
- if (this.hasErrors)
- errStatus = true;
+ parseMangledName(errStatus, false, 1);
return;
default:
errStatus = true;
case 'T':
popFront();
putComma(n);
- parseType();
- if (this.hasErrors)
- {
- errStatus = true;
+ parseType(errStatus);
+ if (errStatus)
return;
- }
continue;
case 'V':
popFront();
}
}
BufSlice name = dst.bslice_empty;
- silent( errStatus, delegate void(out bool e_flg) nothrow { name = parseType(); } );
+ silent( errStatus, delegate void(out bool e_flg) nothrow { name = parseType(e_flg); } );
if (errStatus)
return;
parseValue( errStatus, name, t );
debug(trace) printf( "parseMangledNameArg+\n" );
debug(trace) scope(success) printf( "parseMangledNameArg-\n" );
+ bool errStatus;
+
size_t n = 0;
if ( isDigit( front ) )
{
- bool errStatus;
n = decodeNumber(errStatus);
+
if (errStatus)
- {
- error();
return false;
- }
}
- parseMangledName(false, n);
- return !this.hasErrors;
+ parseMangledName(errStatus, false, n );
+
+ return !errStatus;
}
/*
_D QualifiedName Type
_D QualifiedName M Type
*/
- void parseMangledName(bool displayType, size_t n = 0 ) scope nothrow
+ void parseMangledName( out bool errStatus, bool displayType, size_t n = 0 ) scope nothrow
{
debug(trace) printf( "parseMangledName+\n" );
debug(trace) scope(success) printf( "parseMangledName-\n" );
auto end = pos + n;
eat( '_' );
- if (!match('D'))
- return error();
+ errStatus = !match( 'D' );
+ if (errStatus)
+ return;
do
{
if (beg != dst.length)
put( '.' );
- bool errStatus;
parseSymbolName(errStatus);
if (errStatus)
- return error();
+ return;
nameEnd = dst.length;
attr = parseFunctionTypeNoReturn( displayType );
is_sym_name_front = isSymbolNameFront(errStatus);
if (errStatus)
- return error();
+ return;
} while (is_sym_name_front);
if ( displayType )
popFront(); // has 'this' pointer
auto lastlen = dst.length;
- auto type = parseType();
- if (this.hasErrors)
+ auto type = parseType(errStatus);
+ if (errStatus)
return;
if ( displayType )
} while ( true );
}
- void parseMangledName() nothrow
+ void parseMangledName(out bool errStatus) nothrow
{
- parseMangledName(AddType.yes == addType);
+ parseMangledName(errStatus, AddType.yes == addType);
}
char[] doDemangle(alias FUNC)() return scope nothrow
{
debug(info) printf( "demangle(%.*s)\n", cast(int) buf.length, buf.ptr );
- FUNC();
- if (!this.hasErrors)
+ bool errStatus;
+ FUNC(errStatus);
+ if (!errStatus)
{
return dst[0 .. $].getSlice;
}
return true;
}
- char[] parseType(ref Remangle d, char[] name) return scope nothrow
+ char[] parseType( out bool errStatus, ref Remangle d, char[] name ) return scope nothrow
{
- bool errStatus;
if (d.front != 'Q')
return null;
auto n = d.decodeBackref();
if (n == 0 || n > refPos)
{
- d.error("invalid back reference");
+ // invalid back reference
+ errStatus = true;
return null;
}
bool errStatus;
d.parseMangledName(errStatus);
- if (d.hasErrors)
+ if (errStatus)
{
// error cannot occur
return mangled.dup;