Log in

View Full Version : MaskTools_Expr_Conv() - v0.00


StainlessS
10th January 2022, 17:27
MaskTools_Expr_Conv()

MaskTools expression converter.

Hope somebody can find a use for it.

# MaskTools_Expr_Conv.avsi

/*
v0.00 MaskTools_Expr_Conv() # by StainlessS @ Doom9 https://forum.doom9.org/showthread.php?t=183646
Takes a masktools() style rpn or Infix expression, converts to an output rpn or Infix expression.

Requires RT_Stats & AVS+ [and of course MaskTools].

MaskTools_Expr_Conv(String InExpr,Bool "InIsRpn"=True, String "VarNames"="",Bool "OutIsRpn"=!InIsRpn,Bool "Shortform"=False,Bool "Debug"=TRUE)


Copes with up to 9 named variables in input expression.
Named variables are converted to temp substitute numbers, 999999991 -> 999999999,
expression are converted via Mt_Polish or Mt_Infix, then substitutes converted back again to named variables)
Where used, variable NAMES must also be given in Varnames arg.

Input expressions strings should be enclosed in additional triple quotes to avoid evaluation of the contents,
ie not "x " + String(NamedVar) + " +" but instead """ "x " + String(NamedVar) + " +" """.
(the string itself has to contain the above double quote characters that are BETWEEN the triple quotes.

Output Expressions (results) are returned as if used for input (as if tripple quote enclosed), you may need to do something like
OutExpr = Eval(OutExpr) to use it. [Printing it will print contained quotes].
S = String(1234) is NOT the same as S = "String(1234)"
Result of above 1st S is "1234", of 2nd S is "String(1234)".

InExpr can contain rpn/infix expressions with variable names in either "Longform" or "Shortform".
Expression with Longform variables:
like " ... " + string(SomeVarname) + " ... "
longform rpn, eg """ "x " + String(VarAdd) + " + " + String(VarMult) + " * " + String(VarSub) + " -" """
Longform Infix, eg """ "(((x+" + String(VarAdd) + ")*" + String(VarMult) + ")-" + String(VarSub) + ")" """

Expression with Shortform variables:
like """ ... SomeVarname ... """ [ie without the """ ... String(SomeVarname) ... """ stringy thingy]
Shortform rpn, eg """ "x VarAdd + VarMult * VarSub -" """
Shortform Infix, eg """ "(((x+VarAdd)*VarMult)-VarSub)" """

Shortform expressions will not normally work in mt_lut etc without varname conversion to string and insertion into the expression,
the purpose of these shortform expressions is just for user convenience to provide a READABLE expression without all the nasty " ... " + String(...) + " ... ", stuff.

Input expression may be of types longform or Shortform, it dont matter which type is input.
Output expression may be of types longform(Shortform arg = default false) or Shortform (ShortForm=true).

Must supply any used variable names in pseudo multiline string, or "" = no variable names used in expression string.

Args:-
InExpr, Cannot be "".
rpn or infix, Expr [ rpn as arg to eg mt_Lut(rpn), or mt_lut(expr=mt_Polish(infix) ].

Input expression may be of types longform or Shortform, it dont matter which type is input.

InExpr expression can include eg,
" ... " + string(SomeVarname) + " ... " + etc # Longform
or " ... SomeVarname ... " # Shortform

MUST Enclose entire InExpr expression line in Triple Quotes, """ " ..." """.
eg,
InExpr = """ "x " + String(VarAdd) + " + " + String(VarMult) + " * " + String(VarSub) + " - " """ # rpn Longform

OR
InExpr = """ "x VarAdd + VarMult * VarSub -" """ # rpn Shortform

Where VarAdd, VarMult, and VarSub are variable names supplied in later described Varnames arg.

InIsRpn, Default true.
True, InExpr is a rpn expression, else is an Infix expression.
Controls conversion, rpn -> infix, Infix -> rpn.

Varnames, Optional, default "".
Must supply any used variable names in pseudo multiline string, or "" = none.
Any Variable names used in InExpr string, MUST be given here.
eg, Varnames = "VarAdd\nVarMult\nVarSub\n" # 3 '\n' separated Variable names, "VarAdd", "VarMult" and "VarSub". [just the names, not values].

OutIsRpn, Default !InIsRpn.
Default !InIsRpn, outputs infix if input is rpn, and rpn if input is infix.
You can force output to be the same as input by making OutIsRpn same as InIsRpn.
Perhaps make OutIsRpn same as InIsRpn to convert longform to Shortform or vice-versa)
When OutIsRpn == InIsRpn, there is call to neither mt_Polish() nor mt_Infix().

ShortForm, default false (ie longform).
True, returns shortform output string, ie without " + String(VarName) + " etc", style evaluated variables as strings.
The only use for shortform string is to make it more easily readable, it cannot be used with Masktools.
Shortform expressions without any Variable names, are the same as longform.

Debug, Default TRUE. Output some stuff to Debugview window [Google DebugView].

###

Example 1, Longform input rpn, longform output Infix.
VarNames = "VarAdd\nVarMult\nVarSub\n"
rpn = """ "x " + String(VarAdd) + " + " + String(VarMult) + " * " + String(VarSub) + " -" """
infix = MaskTools_Expr_Conv(rpn,InIsRpn=true,varnames=VarNames)
# Result in square brackets = ["(((x+" + String(VarAdd) + ")*" + String(VarMult) + ")-" + String(VarSub) + ")"]

Example 2, Shortform input rpn, longform output Infix.
VarNames = "VarAdd\nVarMult\nVarSub\n"
rpn = """ "x VarAdd + VarMult * VarSub -" """
infix = MaskTools_Expr_Conv(rpn,InIsRpn=true,varnames=VarNames)
# Result in square brackets = ["(((x+" + String(VarAdd) + ")*" + String(VarMult) + ")-" + String(VarSub) + ")"]

Example 3, Longform input rpn, Shortform output Infix.
VarNames = "VarAdd\nVarMult\nVarSub\n"
rpn = """ "x " + String(VarAdd) + " + " + String(VarMult) + " * " + String(VarSub) + " -" """
infix = MaskTools_Expr_Conv(rpn,InIsRpn=true,varnames=VarNames,ShortForm=True)
# Result in square brackets = ["(((x+VarAdd)*VarMult)-VarSub)"]

Example 4, Shortform input rpn, Shortform output Infix.
VarNames = "VarAdd\nVarMult\nVarSub\n"
rpn = """ "x VarAdd + VarMult * VarSub -" """
infix = MaskTools_Expr_Conv(rpn,InIsRpn=true,varnames=VarNames,ShortForm=True)
# Result in square brackets = ["(((x+VarAdd)*VarMult)-VarSub)"]


Example 5, Longform input Infix, longform output rpn.
VarNames = "VarAdd\nVarMult\nVarSub\n"
infix = """ "((x + " + String(VarAdd) + ") * " + String(VarMult) + " - " + String(VarSub) """
rpn = MaskTools_Expr_Conv(infix,InIsRpn=false,varnames=VarNames)
# result in square brackets = ["x " + String(VarAdd) + " + " + String(VarMult) + " * " + String(VarSub) + " - "]

Example 6, Shortform input Infix, longform output rpn.
VarNames = "VarAdd\nVarMult\nVarSub\n"
infix = """ "((x + VarAdd) * VarMult) - VarSub" """
rpn = MaskTools_Expr_Conv(infix,InIsRpn=false,varnames=VarNames)
# result in square brackets = ["x " + String(VarAdd) + " + " + String(VarMult) + " * " + String(VarSub) + " - "]

Example 7, Longform input Infix, Shortform output rpn.
VarNames = "VarAdd\nVarMult\nVarSub\n"
infix = """ "((x + " + String(VarAdd) + ") * " + String(VarMult) + " - " + String(VarSub) """
rpn = MaskTools_Expr_Conv(infix,InIsRpn=false,varnames=VarNames,ShortForm=True)
# result in square brackets = ["x VarAdd + VarMult * VarSub - "]

Example 8, Shortform input Infix, Shortform output rpn.
VarNames = "VarAdd\nVarMult\nVarSub\n"
infix = """ "((x + VarAdd) * VarMult) - VarSub" """
rpn = MaskTools_Expr_Conv(infix,InIsRpn=false,varnames=VarNames,ShortForm=True)
# result in square brackets = ["x VarAdd + VarMult * VarSub - "]


Example 9,Longform input rpn, shortform output rpn.
VarNames = "VarAdd\nVarMult\nVarSub\n"
rpn = """ "x " + String(VarAdd) + " + " + String(VarMult) + " * " + String(VarSub) + " -" """
infix = MaskTools_Expr_Conv(rpn,InIsRpn=true,varnames=VarNames,OutIsRpn=true,ShortForm=true)
# Result in square brackets = ["x VarAdd + VarMult * VarSub -"]

Example 10,Shortform input rpn, Longform output rpn.
VarNames = "VarAdd\nVarMult\nVarSub\n"
rpn = """ "x VarAdd + VarMult * VarSub -" """
infix = MaskTools_Expr_Conv(rpn,InIsRpn=true,varnames=VarNames,OutIsRpn=true,ShortForm=false)
# Result in square brackets = ["x " + String(VarAdd) + " + " + String(VarMult) + " * " + String(VarSub) + " -"]

Example 11, Longform input Infix, Shortform output infix.
VarNames = "VarAdd\nVarMult\nVarSub\n"
infix = """ "(((x+" + String(VarAdd) + ")*" + String(VarMult) + ")-" + String(VarSub) + ")" """
rpn = MaskTools_Expr_Conv(infix,InIsRpn=false,varnames=VarNames,OutIsRpn=False,ShortForm=True)
# result in square brackets = ["(((x+VarAdd)*VarMult)-VarSub)"]

Example 12, Shortform input Infix, Longform output infix.
VarNames = "VarAdd\nVarMult\nVarSub\n"
infix = """ "(((x+VarAdd)*VarMult)-VarSub)" """
rpn = MaskTools_Expr_Conv(infix,InIsRpn=false,varnames=VarNames,OutIsRpn=False,ShortForm=False)
# result in square brackets = ["(((x+" + String(VarAdd) + ")*" + String(VarMult) + ")-" + String(VarSub) + ")"]

*/


Function MaskTools_Expr_Conv(String InExpr,Bool "InIsRpn", String "VarNames",Bool "OutIsRpn", Bool "Shortform",Bool "Debug") {
myName = "MaskTools_Expr_Conv: "
InIsRpn = Default(InIsRpn,True)
VarNames = Default(VarNames,"").RT_String # Convert ALL'\n' to chr(10) separators
OutIsRpn = Default(OutIsRpn, !InIsRpn)
ShortForm = Default(ShortForm,false)
Debug = Default(Debug,True)
Assert(InExpr != "",myName+"Need input expression")
nVars = VarNames.RT_TxtQueryLines
Assert(nVars <= 9,myName+"Max number of VarsNames = 9")
VarSubstitutes = RT_String("999999991\n999999992\n999999993\n999999994\n999999995\n999999996\n999999997\n999999998\n999999999\n")
# Create multiline find and replace strings for substitutions
SubstituteAsText="" # Init, Multiline string of VarSubstitutes used in this call
StringAsText="" # Init, Multiliine string of Varnames as Insert strings, eg Chr(34) + " + string(" + "9999991" + ") + " + Chr(34)
for(i=0, nVars-1) {
vn=VarNames.RT_TxtGetLine(i)
# check for valid varname
nlen = vn.strLen
Assert(0 < nLen,myName+RT_String("Varname[%d] cannot be '' [zero rel]",i))
# Chk valid VarName ['_' or Alpha for 1st char, thereafter also digit]
a = vn.Rt_Ord
Assert(a==95 || ((65 <= a <= 90) || (97 <= a <= 122)),myName+RT_String("Illegal Varname '%s'",vn))
for(j=2,nLen) {
a = vn.Rt_Ord(pos=j)
Assert(a==95 || ((65 <= a <= 90) || (97 <= a <= 122)) || (48 <= a <= 57), myName+RT_String("Illegal Varname '%s'",vn))
}
subst = VarSubstitutes.RT_TxtGetLine(i)
Eval(vn + " = subst") # Assign substitute string to temp local varname vn
SubstituteAsText = RT_String("%s%s\n",SubstituteAsText,subst) # add substitute to multiline string
StringAsText = RT_String("%s%s\n",StringAsText,Chr(34) + " + String(" + vn + ") + " + Chr(34))
}
(DEBUG) ? RT_DebugF("InExpr = %s",InExpr,name=myName) : NOP
RawInExpr = InExpr.RT_StrReplaceMulti(VarNames,SubstituteAsText,False) # Convert vars to substitutions.
(DEBUG) ? RT_DebugF("RawInExpr = %s",RawInExpr,name=myName) : NOP
EvalRawInExpr = Eval(RawInExpr) # Convert remaining Longform Strings() to Shortform substitutions. [QUOTES Removed by Eval]
(DEBUG) ? RT_DebugF("EvalRawInExpr = '%s'",EvalRawInExpr,name=myName) : NOP
if(InIsRpn == OutIsRpn) {
(DEBUG) ? RT_DebugF("No rpn<->infix conversion",name=myName) : NOP
RawOutExpr = EvalRawInExpr
} else {
if(OutIsRpn) {
(DEBUG) ? RT_DebugF("Calling Mt_Polish('%s')",EvalRawInExpr,name=myName) : NOP # Single quotes mark extent of string only.
try { RawOutExpr = Mt_Polish(EvalRawInExpr) }
catch(msg) {
omsg = RT_String("Mt_Polish('%s') FAILS\n SysErr=%s",EvalRawInExpr,msg)
RT_DebugF("%s",omsg,name=myName)
Assert(False,myName+omsg)
}
} else {
(DEBUG) ? RT_DebugF("Calling Mt_Infix('%s')",EvalRawInExpr,name=myName) : NOP # Single quotes mark extent of string only.
try { RawOutExpr = Mt_Infix(EvalRawInExpr) }
catch(msg) {
omsg = RT_String("Mt_Infix('%s') FAILS\n SysErr=%s",EvalRawInExpr,msg)
RT_DebugF("%s",omsg,name=myName)
Assert(False,myName+omsg)
}
}
}
(DEBUG) ? RT_DebugF("RawOutExpr = '%s'",RawOutExpr,name=myName) : NOP # Single quotes mark extent of string only.
######
ShortFormOutExpr = Chr(34) + RawOutExpr.RT_StrReplaceMulti(SubstituteAsText,VarNames,False) + Chr(34)
(DEBUG) ? RT_DebugF("ShortFormOutExpr = %s",ShortFormOutExpr,name=myName) : NOP
LongformOutExpr = Chr(34) + RawOutExpr.RT_StrReplaceMulti(SubstituteAsText,StringAsText,False) + Chr(34)
(DEBUG) ? RT_DebugF("LongformOutExpr = %s",LongformOutExpr,name=myName) : NOP
Result = (ShortForm) ? ShortFormOutExpr: LongformOutExpr
(DEBUG) ? RT_DebugF("RESULT in [] = [%s]\n",Result,name=myName) : NOP
Return Result # Results are quote enclosed.
}


EDIT: Does not support any MaskTools Keywords in expression, eg "sin", "log", "max", "round".