Templates, templates, templates...
Voitech via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sat Jan 23 03:30:15 PST 2016
Hi, I have a problem with creating proper inheritance chain with
templates. First i will give some background about my problem.
I'm trying to create a validator for math calculation
expressions. I don't want to use regexps as this is approach
gives me headache and probably will not allow further extension i
want. For now expressions should look like this:
1+2+3/4, -(5*(25-5)/19), sqrt(-5/-6*(212)) etc.
So each of charactes is parsed to something like PrimaryElement
class PrimaryElement {
const dchar value;
SymbolType symbolType;
}
SymbolsType is an enum which contains:
EXPR_START,+,-,/,DIGIT,(,),.,EXPR_END
So now i want to create validator for input so user couldn't
insert something like:
/00..34-+/493 but only 0.34-493. I want to divide it into phases.
First phase is SymbolType validation so it will handles problems
like:
+-/345..3 but not 00000000.234+3-53
Second phase will take care about value validation so user cant
insert 0000.0+3 but only 0.000+3
Third phase would be executed to check expression is completed
and not allow to calculate expression for situations like
0.000+3, 3-3+4.5+ or 364/4-5.3+(
Now i'm trying to implement phase one. So i create
PrimaryElementProcessor which will take some kind of rules and
check PrimaryElement[] that way if divided parts of array fits
into one of rules then it is valid. Rules will be trimmed to size
of expression if necessary.
Model and constants declaration looks like this:
private enum ControllFlag{
none,ommitable,repeatable
}
private enum LogicFlag{
none,or,and
}
private class Rule(V,F){
V value;
F flag;
this(){
}
this(V value){
this.value=value;
}
this(V value,F flag){
this.value=value;
this.flag=flag;
}
}
private alias ControllTemplate(T) =Rule!(T,ControllFlag);
private alias SymbolRule =ControllTemplate!(SymbolType);
private alias StringRule =ControllTemplate!(SymbolRule[]);
private alias LogicTemplate(T...)
=Rule!(ControllTemplate(T)[],LogicFlag);
private alias LogicRule=LogicTemplate!([SymbolRule,StringRule]);
<--error
So i first want to handle case like DDDDD.DDDD or DDDDDD where D
is Digit
instantiation code:
SymbolRule digitRule = new
SymbolRule(SymbolType.digit,ControllFlag.repeatable);
SymbolRule commaRule = new SymbolRule(SymbolType.comma);
StringRule numericRule = new
StringRule([digitRule,commaRule,digitRule]);
LogicRule decimalRule = new
LogicRule([digitRule,numericRule],LogicFlag.or);
error:
Error: type Rule!(Rule!(SymbolType, ControllFlag)[],
ControllFlag) has no value
Ok so i want to hold different types in LogicRule maybe Algebraic
implementation would do?
private alias ControllTemplate(T) =Rule!(T,ControllFlag);
private alias SymbolRule =ControllTemplate!(SymbolType);
private alias StringRule =ControllTemplate!(SymbolRule[]);
private alias LogicTemplate(T...)
=Rule!(Algebraic!(ControllTemplate(T))[],LogicFlag); <--error
private alias AlgebraicLogicRule =
LogicTemplate!(SymbolRule,StringRule);
error:
Error: cannot pass type (Rule!(SymbolType, ControllFlag),
Rule!(Rule!(SymbolType, ControllFlag)[], ControllFlag)) as a
function argument
So maybe something simpler:
private alias ControllTemplate(T) =Rule!(T,ControllFlag);
private alias SymbolRule =ControllTemplate!(SymbolType);
private alias StringRule =ControllTemplate!(SymbolRule[]);
private alias SimpleLogicRule
=Rule!(Algebraic!(SymbolRule,StringRule)[],LogicFlag);
Compiles but... when i try to instantiate SimpleLogicRule like
SymbolRule digitRule = new
SymbolRule(SymbolType.digit,ControllFlag.repeatable);
SymbolRule commaRule = new SymbolRule(SymbolType.comma);
StringRule numericRule = new
StringRule([digitRule,commaRule,digitRule]);
SimpleLogicRule decimalRule = new
SimpleLogicRule([digitRule,numericRule],LogicFlag.or); <--- error
i get error:
None of the overloads of '__ctor' are callable using argument
types (Object[], LogicFlag), candidates are: ...
So i understand compiler can't cast/extract array of different
types to known type.
I created a wrapper for this two types SymbolRule and StringRule
and init it somewhere before passing to LogicRule ctor. This
approach makes a lot of boilerplate code for example:
alias Wrapper = Algebraic!(SymbolRule,StringRule);
alias LogicRule =Rule!(Wrapper[],LogicFlag);
SymbolRule digitRule = new
SymbolRule(SymbolType.digit,ControllFlag.repeatable);
SymbolRule commaRule = new SymbolRule(SymbolType.comma);
StringRule numericRule = new
StringRule([digitRule,commaRule,digitRule]);
Wrapper digitRuleWrapper =digitRule; <-- how to ommit this ?
Wrapper numericRuleWrapper =numericRule; <-- how to ommit this ?
LogicRule decimalRule=new
LogicRule([digitRuleWrapper,numericRuleWrapper],LogicFlag.or);
Is there any nicer way to handle this case ?
Cheers Voitech.
More information about the Digitalmars-d-learn
mailing list