Mercurial > projects > mde
view mde/mergetag/old-code/typeSpec.d.old @ 4:9a990644948c
Many changes: upgraded to tango 0.99.4, reorganised mde/input, large changes to mde/mergetag and mde/init, separated off test/MTTest.d and more.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Sun, 06 Jan 2008 17:38:51 +0000 |
parents | |
children |
line wrap: on
line source
/+ I wrote this and then realised it's not worth using, it being easier and faster to match type strings without this. This module does enable spaces to be in appropriate places, but so what... module typeSpec; import mde.mergetag.exception; import Util = tango.text.Util; /** * Struct to view a type specifier string. */ struct TypeView { /// Type of stored type specifier (NULL, BASIC, ARRAY, ASSOCIATIVE_ARRAY). enum SPEC_TYPE : ubyte { NULL, BASIC, ARRAY, ASSOCIATIVE_ARRAY } SPEC_TYPE spec_type; /// Current specifier type. union { char[] type_name; /// For BASIC types is the type name. TypeView* type_array_value; /// For ARRAY and ASSOCIATIVE_ARRAY types, this is the value-type. } TypeView* type_array_key; /// For ASSOCIATIVE_ARRAY types, this is the key-type; /** Construct and return a TypeView from a source string. * * Such a string should have one of the following forms: * TYPE_NAME: [_a-zA-Z][_a-zA-Z0-9]* (regexp) * ARRAY: TYPE_NAME[] * ASSOC_ARRAY: TYPE_NAME[TYPE_NAME] * * Throws MTBadTypeStringException on bad type specifier strings. */ static TypeSpec parse (char[] src) { bool isNameChar (char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c = '_'; } void throwErr () { logger.warn ("Bad type string"); throw new MTBadTypeStringException (); } src = Util.trim(src); if (!src.length) throwErr; TypeView ret; if (src[$-1] == ']') { // ARRAY or ASSOCIATIVE_ARRAY type if (src.length < 2) throwErr; if (src[$-2] == '[') { // ARRAY type ret.spec_type = SPEC_TYPE.ARRAY; // this is an array of... ret.type_array_value = parse (src[0..$-2]); // whatever this is } else { // ASSOCIATIVE_ARRAY type // look backwards for matching '[' bracket: uint i = src.length-2; uint recursion_depth = 0; while (true) { char c = src[i]; if (c == ']') ++recursion_depth; if (c == '[') { if (recursion_depth) --recursion_depth; else break; } if (i == 0) throwErr; // no matching bracket! else --i; } ret.spec_type = SPEC_TYPE.ASSOCIATIVE_ARRAY; ret.type_array_value = parse (src[0..i]); ret.type_array_key = parse (src[i+1..$-1]); } } else { // BASIC type char c = src[0]; if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c = '_')) throwErr; for (uint i=1; i < src.length; ++i) { if (!isNameChar(src[i])) throwErr; } ret.spec_type = SPEC_TYPE.BASIC; ret.type_name = src; } return ret; } } unittest { TypeView tv = TypeView.parse (` type1 [] [ Type2 [] ] [] `); assert (tv.spec_type == SPEC_TYPE.ARRAY); assert (tv.type_array_value.spec_type == SPEC_TYPE.ASSOCIATIVE_ARRAY); assert (tv.type_array_value.type_array_value.spec_type == SPEC_TYPE.ARRAY); assert (tv.type_array_value.type_array_value.type_array_value.spec_type == SPEC_TYPE.BASIC); assert (tv.type_array_value.type_array_value.type_array_value.type_name == `type1`); assert (tv.type_array_value.type_array_key.spec_type == SPEC_TYPE.ARRAY); assert (tv.type_array_value.type_array_key.type_array_value.spec_type == SPEC_TYPE.BASIC); assert (tv.type_array_value.type_array_key.type_array_value.type_name == `Type2`); } +/