computerscare-vcv-modules

computerscare modules for VCV Rack
Log | Files | Refs

commit 1b7ade5ffed339f56bb2511b708306f0f0f8e0e9
parent 0285695d6009c0b2abb0c62e5875397501ce0a97
Author: Adam Malone <1319733+freddyz@users.noreply.github.com>
Date:   Wed, 21 Aug 2019 11:52:09 -0500

formulas in laundry soup work

Diffstat:
Msrc/dtpulse.cpp | 65++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/dtpulse.hpp | 5+++--
2 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/src/dtpulse.cpp b/src/dtpulse.cpp @@ -626,6 +626,12 @@ Token::Token(std::string t, std::string v, int dex, int dur) { index = dex; duration = dur; } +Token::Token(std::string t, int val) { + type=t; + value = std::to_string(static_cast<long long>(val)); + index=-1; + duration=val; +} Token::Token(const Token& source) { type=source.type; value=source.value; @@ -643,15 +649,14 @@ Parser::Parser() { void Parser::setForLaundryPoly() { Token t = tokens[0]; while (t.type != "NULL") { - //tokenStack.push_back(t); - tokenStack.push_back(Token(t.type, t.value, t.index,t.duration )); + tokenStack.push_back(Token(t.type, t.value, t.index,t.duration )); t = skipAndPeekToken(); } printf("setForLaundryPoly\n"); printTokenVector(tokenStack); } void Parser::setForLaundry() { - //whitelists + std::vector<std::string> laundryBinaryOp = {"Plus","Minus","Asterix","Backslash","Caret","Ampersand"}; std::vector<std::string> laundryInterleaveAny = {"Letter", "Integer", "ChanceOfInteger", "Digit", "LeftParen", "RightParen", "Channel"}; std::vector<std::string> laundryAtExpandAny = {"Letter", "Digit", "ChanceOfInteger", "Integer", "Channel"}; std::vector<std::string> laundrySquareAny = {"Letter", "Digit", "ChanceOfInteger", "Integer", "Comma", "Channel"}; @@ -669,7 +674,7 @@ void Parser::setForLaundry() { currentIndex = 0; tokens=tokenStack; tokenStack={}; - setFormula(peekToken(),true); + setFormula(peekToken(),laundryBinaryOp,true); if (!inError) { currentIndex = 0; tokens = tokenStack; @@ -829,9 +834,9 @@ void Parser::setForExactIntegers(Token t) { t = skipAndPeekToken(); } } -void Parser::setFormula(Token t,bool laundryMode) { +void Parser::setFormula(Token t,std::vector<std::string> operatorWhitelist,bool laundryMode) { while (t.type != "NULL") { - ParseFormula(t,laundryMode); + ParseFormula(t,operatorWhitelist,laundryMode); if (peekToken().type != "NULL") { tokenStack.push_back(peekToken()); } @@ -889,7 +894,52 @@ void Parser::ParseVariable(Token t) { tokenStack.push_back(Token("ChannelVariable", "1", -1, std::stoi("5"))); } } -void Parser::ParseFormula(Token t, bool laundryMode) { +void Parser::ParseFormula(Token t,std::vector<std::string> operatorWhitelist, bool laundryMode) { + std::vector<Token> terminalStack; + std::vector<Token> operatorStack; + std::vector<std::string> whitelist = operatorWhitelist; + whitelist.push_back("Integer"); + whitelist.push_back("Digit"); + while(matchesAny(t.type,whitelist)) { + if(t.type=="Integer" || t.type=="Digit") { + if(operatorStack.size() > 0) { + if(terminalStack.size() > 0) { + //apply them + std::string op = operatorStack.back().type; + operatorStack.pop_back(); + int lhs = terminalStack.back().duration; + int rhs = t.duration; + int result; + terminalStack.pop_back(); + if(op=="Asterix") { + result=lhs*rhs; + } else if(op=="Ampersand") { + result=lhs%rhs; + } else if(op=="Plus") { + result=lhs+rhs; + } + else if(op=="Minus") { + result=lhs-rhs; + } + else if(op=="Backslash") { + result = lhs/rhs; + } + terminalStack.push_back(Token("Integer",result)); + } + else { + inError=true; + } + } + else { + terminalStack.push_back(t); + } + } + else { //operator + operatorStack.push_back(t); + } + t = skipAndPeekToken(); + } + tokenStack.insert(tokenStack.end(), terminalStack.begin(), terminalStack.end()); } void Parser::ParseExactInteger(Token t) { if (t.type == "LeftAngle") { @@ -1224,6 +1274,7 @@ std::vector<Token> tokenizeString(std::string input) { else if (token == ":") stack.push_back(Token("Colon", token)); else if (token == ";") stack.push_back(Token("Semicolon", token)); else if (token == "|") stack.push_back(Token("Pipe", token)); + else if (token == "%") stack.push_back(Token("Ampersand", token)); else if (knobandinputlookup.find(token) != std::string::npos) { stack.push_back(Token("Letter", token, knobandinputlookup.find(token))); } diff --git a/src/dtpulse.hpp b/src/dtpulse.hpp @@ -27,6 +27,7 @@ class Token { Token(std::string t, std::string v); Token(std::string t, std::string v, int dex, int dur); Token(std::string t, std::string v, int dex); + Token(std::string t, int val); Token(const Token& source); void print(); }; @@ -48,7 +49,7 @@ class Parser { void skipToken(); void setExactValue(Token t); void setForExactIntegers(Token t); - void setFormula(Token t, bool laundryMode); + void setFormula(Token t,std::vector<std::string> operatorWhitelist, bool laundryMode); void setForVariables(Token t); void setForChanceOfIntegers(Token t); void setForRandoms(Token t); @@ -68,7 +69,7 @@ class Parser { int currentIndex; void ParseExactValue(Token t); void ParseExactInteger(Token t); - void ParseFormula(Token t, bool laundryMode); + void ParseFormula(Token t,std::vector<std::string> operatorWhitelist,bool laundryMode); void ParseVariable(Token t); void ParseRandomSequence(Token t); void ParseInterleave(Token t,std::vector<std::string> whitelist);