Created
December 26, 2009 03:39
-
-
Save DanielKeep/263832 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Parses the storage class for function arguments. | |
/// Authors: Daniel Keep | |
/// Copyright: Copyright © 2009 Daniel Keep | |
/// License: BSD v2 <http://www.opensource.org/licenses/bsd-license.php> | |
module argparse; | |
enum ParamSemantics | |
{ | |
None = 0b0000, | |
In = 0b0001, | |
Out = 0b0010, | |
Ref = 0b0011, | |
Scope = 0b0100, | |
} | |
private: | |
bool startsWith(in string s, in string match) | |
{ | |
if( s.length >= match.length ) | |
return s[0..match.length] == match; | |
else | |
return false; | |
} | |
enum ParseMode | |
{ | |
Normal, | |
StripWS | |
} | |
string classifyType(in string type) | |
{ | |
// Classify | |
if( startsWith(type, "in ") ) | |
return "ParamSemantics.In"; | |
else if( startsWith(type, "out ") ) | |
return "ParamSemantics.Out"; | |
else if( startsWith(type, "ref ") ) | |
return "ParamSemantics.Ref"; | |
else if( startsWith(type, "scope ") ) | |
return "ParamSemantics.Scope"; | |
else | |
return "ParamSemantics.None"; | |
} | |
string parseParamSemanticsImpl(string args) | |
{ | |
// First, chop off the first and last chars (should be parens) | |
assert( args[0] == '(' && args[$-1] == ')' ); | |
args = args[1..$-1]; | |
// If the string is empty, that means no args. | |
if( args.length == 0 ) | |
return "null /+ no arguments +/"; | |
// Start parsing | |
string result = "["; | |
auto mode = ParseMode.Normal; | |
size_t i = 0; | |
int level = 0; | |
foreach( j, c ; args ) | |
{ | |
if( c == ',' && level == 0 ) | |
{ | |
// End of argument | |
auto type = args[i..j]; | |
result ~= classifyType(type) ~ "/+"~type~"+/" ~ ", "; | |
mode = ParseMode.StripWS; | |
} | |
else if( c == '(' || c == '[' ) | |
++level; | |
else if( c == ')' || c == ']' ) | |
--level; | |
else if( mode == ParseMode.StripWS ) | |
{ | |
if( c != ' ' ) | |
{ | |
mode = ParseMode.Normal; | |
i = j; | |
} | |
} | |
else | |
{ | |
// no-op | |
} | |
} | |
// Classify last argument | |
auto type = args[i..$]; | |
result ~= classifyType(type) ~ "/+"~type~"+/"; | |
// Done | |
result ~= "]"; | |
return result ~ `/+ `~args~` +/`; | |
} | |
public template ParameterSemantics(alias Function) | |
{ | |
const ParameterSemantics = | |
ParameterSemantics!(typeof(Function)); | |
} | |
import std.traits : ParameterTypeTuple; | |
public template ParameterSemantics(FnT) | |
{ | |
const ParameterSemantics = | |
mixin(parseParamSemanticsImpl( | |
ParameterTypeTuple!(FnT).stringof)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment