diff --git a/data_svelte/scenario.json b/data_svelte/scenario.json new file mode 100644 index 00000000..d328c9e4 --- /dev/null +++ b/data_svelte/scenario.json @@ -0,0 +1,3 @@ +{ + "scen": "" +} \ No newline at end of file diff --git a/include/classes/IoTScenario.h b/include/classes/IoTScenario.h index de1328f1..6308fd26 100644 --- a/include/classes/IoTScenario.h +++ b/include/classes/IoTScenario.h @@ -4,91 +4,91 @@ #include class ExprAST { -public: - virtual ~ExprAST(); - virtual IoTValue* exec(); - virtual int setValue(IoTValue *val); // ret 0 - установка значения не поддерживается наследником - virtual bool hasEventIdName(String eventIdName); + public: + virtual ~ExprAST(); + virtual IoTValue *exec(); + virtual int setValue(IoTValue *val); // ret 0 - установка значения не поддерживается наследником + virtual bool hasEventIdName(String eventIdName); }; class IoTScenario { - //===----------------------------------------------------------------------===// - // Lexer (Лексический анализатор) - //===----------------------------------------------------------------------===// + //===----------------------------------------------------------------------===// + // Lexer (Лексический анализатор) + //===----------------------------------------------------------------------===// - String IdentifierStr; // Заполняется, если tok_identifier - float NumVal; // Заполняется, если tok_number - char LastChar = ' '; + String IdentifierStr; // Заполняется, если tok_identifier + float NumVal; // Заполняется, если tok_number + char LastChar = ' '; - /// gettok - Возвращает следующий токен из стандартного потока ввода. - int gettok(); + /// gettok - Возвращает следующий токен из стандартного потока ввода. + int gettok(); - //===----------------------------------------------------------------------===// - // Parser (Парсер или Синтаксический Анализатор) - //===----------------------------------------------------------------------===// + //===----------------------------------------------------------------------===// + // Parser (Парсер или Синтаксический Анализатор) + //===----------------------------------------------------------------------===// - /// CurTok/getNextToken - Предоставляет простой буфер токенов. CurTok - это текущий - /// токен, просматриваемый парсером. getNextToken получает следующий токен от - /// лексического анализатора и обновляет CurTok. - int CurTok; - int getNextToken(); + /// CurTok/getNextToken - Предоставляет простой буфер токенов. CurTok - это текущий + /// токен, просматриваемый парсером. getNextToken получает следующий токен от + /// лексического анализатора и обновляет CurTok. + int CurTok; + int getNextToken(); - /// BinopPrecedence - Содержит приоритеты для бинарных операторов - std::map BinopPrecedence; + /// BinopPrecedence - Содержит приоритеты для бинарных операторов + std::map BinopPrecedence; - /// GetTokPrecedence - Возвращает приоритет текущего бинарного оператора. - int GetTokPrecedence(); + /// GetTokPrecedence - Возвращает приоритет текущего бинарного оператора. + int GetTokPrecedence(); - /// Error* - Это небольшие вспомогательные функции для обработки ошибок. - ExprAST *Error(const char *Str); + /// Error* - Это небольшие вспомогательные функции для обработки ошибок. + ExprAST *Error(const char *Str); - /// identifierexpr - /// ::= identifier - /// ::= identifier '(' expression* ')' - ExprAST *ParseIdentifierExpr(String *IDNames); + /// identifierexpr + /// ::= identifier + /// ::= identifier '(' expression* ')' + ExprAST *ParseIdentifierExpr(String *IDNames); - /// numberexpr ::= number - ExprAST *ParseNumberExpr(); + /// numberexpr ::= number + ExprAST *ParseNumberExpr(); - /// parenexpr ::= '(' expression ')' - ExprAST *ParseParenExpr(); + /// parenexpr ::= '(' expression ')' + ExprAST *ParseParenExpr(); - /// bracketsexpr ::= '{' expression '}' - ExprAST *ParseBracketsExpr(); + /// bracketsexpr ::= '{' expression '}' + ExprAST *ParseBracketsExpr(); - /// quotesexpr ::= '"' expression '"' - ExprAST *ParseQuotesExpr(); + /// quotesexpr ::= '"' expression '"' + ExprAST *ParseQuotesExpr(); - /// ifexpr ::= 'if' expression 'then' expression 'else' expression - ExprAST *ParseIfExpr(String* IDNames); + /// ifexpr ::= 'if' expression 'then' expression 'else' expression + ExprAST *ParseIfExpr(String *IDNames); - /// primary - /// ::= identifierexpr - /// ::= numberexpr - /// ::= parenexpr - ExprAST *ParsePrimary(String* IDNames); + /// primary + /// ::= identifierexpr + /// ::= numberexpr + /// ::= parenexpr + ExprAST *ParsePrimary(String *IDNames); - /// binoprhs - /// ::= ('+' primary)* - ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames); + /// binoprhs + /// ::= ('+' primary)* + ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames); - /// expression - /// ::= primary binoprhs - /// - ExprAST *ParseExpression(String *IDNames); + /// expression + /// ::= primary binoprhs + /// + ExprAST *ParseExpression(String *IDNames); - std::vector ScenarioElements; // корневые элементы дерава + std::vector ScenarioElements; // корневые элементы дерава - String *strFromFile; - char getLastChar(); - int strIterator = 0; + String *strFromFile; + char getLastChar(); + int strIterator = 0; - void clearScenarioElements(); + void clearScenarioElements(); -public: - void loadScenario(String fileName); - void ExecScenario(String eventIdName); + public: + void loadScenario(String fileName); + void ExecScenario(String eventIdName); - IoTScenario(); - ~IoTScenario(); -}; \ No newline at end of file + IoTScenario(); + ~IoTScenario(); +}; diff --git a/src/Main.cpp b/src/Main.cpp index 1a3430b4..51ef1bd2 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -63,7 +63,7 @@ void setup() { asyncUdpInit(); //загрузка сценария - iotScen.loadScenario("/scenario.txt"); + iotScen.loadScenario("/scenario.json"); // создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке IoTItems.push_back((IoTItem *)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}")); generateEvent("onStart", ""); diff --git a/src/WsServer.cpp b/src/WsServer.cpp index 6637933e..9915af45 100644 --- a/src/WsServer.cpp +++ b/src/WsServer.cpp @@ -63,7 +63,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) sendFileToWs("/items.json", num, 1024); sendFileToWs("/widgets.json", num, 1024); sendFileToWs("/config.json", num, 1024); - sendFileToWs("/scenario.txt", num, 1024); + sendFileToWs("/scenario.json", num, 1024); standWebSocket.sendTXT(num, settingsFlashJson); } //**сохранение**// @@ -73,7 +73,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) clearConfigure(); Serial.println("Start config"); configure("/config.json"); - iotScen.loadScenario("/scenario.txt"); + iotScen.loadScenario("/scenario.json"); } //**сохранение**// if (headerStr == "/tuoyal|") { @@ -81,13 +81,9 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) } //**сохранение**// if (headerStr == "/oiranecs|") { - if (length - headerLenth == 0) { - SerialPrint("i", "WS", "Scenario file empty"); - writeFile("/scenario.txt", ""); - } else { - writeFileUint8tByFrames("scenario.txt", payload, length, headerLenth, 256); - iotScen.loadScenario("/scenario.txt"); - } + writeFileUint8tByFrames("scenario.json", payload, length, headerLenth, 256); + iotScen.loadScenario("/scenario.json"); + // создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке IoTItems.push_back((IoTItem*)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}")); generateEvent("onStart", ""); diff --git a/src/classes/IoTScenario.cpp b/src/classes/IoTScenario.cpp index d65f3dcf..85e7e289 100644 --- a/src/classes/IoTScenario.cpp +++ b/src/classes/IoTScenario.cpp @@ -9,924 +9,983 @@ bool isIotScenException; // признак исключения и попытки прекратить выполнение сценария заранее - -// Лексический анализатор возвращает токены [0-255], если это неизвестны, +// Лексический анализатор возвращает токены [0-255], если это неизвестны, // иначе одну из известных единиц кода enum Token { - tok_eof = -1, + tok_eof = -1, - // операнды (первичные выражения: идентификаторы, числа) - tok_identifier = -4, tok_number = -5, tok_string = -3, + // операнды (первичные выражения: идентификаторы, числа) + tok_identifier = -4, + tok_number = -5, + tok_string = -3, - // двухсимвольные операторы бинарных операций - tok_equal = -2, tok_notequal = -9, tok_lesseq = -10, tok_greateq = -11, + // двухсимвольные операторы бинарных операций + tok_equal = -2, + tok_notequal = -9, + tok_lesseq = -10, + tok_greateq = -11, - // управление - tok_if = -6, tok_then = -7, tok_else = -8 + // управление + tok_if = -6, + tok_then = -7, + tok_else = -8 }; - //===----------------------------------------------------------------------===// // Abstract Syntax Tree (Абстрактное Синтаксическое Дерево или Дерево Парсинга) //===----------------------------------------------------------------------===// /// ExprAST - Базовый класс для всех узлов выражений. ExprAST::~ExprAST() {} -IoTValue* ExprAST::exec() {return nullptr;} -int ExprAST::setValue(IoTValue *val) {return 0;} // 0 - установка значения не поддерживается наследником -bool ExprAST::hasEventIdName(String eventIdName) {return false;} // по умолчанию все узлы не связаны с ИД события, для которого выполняется сценарий -//struct IoTValue zeroIotVal; - +IoTValue *ExprAST::exec() { return nullptr; } +int ExprAST::setValue(IoTValue *val) { return 0; } // 0 - установка значения не поддерживается наследником +bool ExprAST::hasEventIdName(String eventIdName) { return false; } // по умолчанию все узлы не связаны с ИД события, для которого выполняется сценарий +// struct IoTValue zeroIotVal; + /// NumberExprAST - Класс узла выражения для числовых литералов (Например, "1.0"). class NumberExprAST : public ExprAST { - IoTValue Val; -public: - NumberExprAST(float val) { Val.valD = val;} + IoTValue Val; - IoTValue* exec() { - if (isIotScenException) return nullptr; - //Serial.printf("Call from NumberExprAST: %f\n", Val.valD); - return &Val; - } + public: + NumberExprAST(float val) { Val.valD = val; } + + IoTValue *exec() { + if (isIotScenException) return nullptr; + // Serial.printf("Call from NumberExprAST: %f\n", Val.valD); + return &Val; + } }; /// StringExprAST - Класс узла выражения для строковых литералов (Например, "Example with spaces and quotes"). class StringExprAST : public ExprAST { - IoTValue Val; -public: - StringExprAST(String val) { Val.isDecimal = false; Val.valS = val;} + IoTValue Val; - IoTValue* exec() { - if (isIotScenException) return nullptr; - //Serial.printf("Call from StringExprAST: %s\n", Val.valS.c_str()); - return &Val; - } + public: + StringExprAST(String val) { + Val.isDecimal = false; + Val.valS = val; + } + + IoTValue *exec() { + if (isIotScenException) return nullptr; + // Serial.printf("Call from StringExprAST: %s\n", Val.valS.c_str()); + return &Val; + } }; /// VariableExprAST - Класс узла выражения для переменных (например, "a"). class VariableExprAST : public ExprAST { - String Name; - IoTItem* Item; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID - bool ItemIsLocal = false; + String Name; + IoTItem *Item; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID + bool ItemIsLocal = false; -public: - VariableExprAST(const String &name, IoTItem* item) : Name(name), Item(item) { - if (item) ItemIsLocal = item->iAmLocal; - } - - int setValue(IoTValue *val) { - if (!ItemIsLocal) Item = findIoTItem(Name); - if (Item) Item->setValue(*val); - else return 0; - - return 1; - } - - IoTValue* exec() { - if (isIotScenException) return nullptr; - if (!ItemIsLocal) Item = findIoTItem(Name); - if (Item) { - //if (Item->value.isDecimal) - // Serial.printf("Call from VariableExprAST: %s = %f\n", Name.c_str(), Item->value.valD); - //else Serial.printf("Call from VariableExprAST: %s = %s\n", Name.c_str(), Item->value.valS.c_str()); - return &(Item->value); + public: + VariableExprAST(const String &name, IoTItem *item) : Name(name), Item(item) { + if (item) ItemIsLocal = item->iAmLocal; } - return nullptr; // Item не найден. - } + int setValue(IoTValue *val) { + if (!ItemIsLocal) Item = findIoTItem(Name); + if (Item) + Item->setValue(*val); + else + return 0; + + return 1; + } + + IoTValue *exec() { + if (isIotScenException) return nullptr; + if (!ItemIsLocal) Item = findIoTItem(Name); + if (Item) { + // if (Item->value.isDecimal) + // Serial.printf("Call from VariableExprAST: %s = %f\n", Name.c_str(), Item->value.valD); + // else Serial.printf("Call from VariableExprAST: %s = %s\n", Name.c_str(), Item->value.valS.c_str()); + return &(Item->value); + } + + return nullptr; // Item не найден. + } }; /// BinaryExprAST - Класс узла выражения для бинарных операторов. class BinaryExprAST : public ExprAST { - signed char Op; - ExprAST *LHS, *RHS; - IoTValue val; - String lhsStr, rhsStr; + signed char Op; + ExprAST *LHS, *RHS; + IoTValue val; + String lhsStr, rhsStr; -public: - BinaryExprAST(signed char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + public: + BinaryExprAST(signed char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} - ~BinaryExprAST() { - if (LHS) delete LHS; - if (RHS) delete RHS; - //Serial.printf("Call from BinaryExprAST delete\n"); - } - - IoTValue* exec(){ - if (isIotScenException) return nullptr; - String printStr = ""; - - if (Op == tok_equal) printStr = "=="; - else if (Op == tok_notequal) printStr = "!="; - else if (Op == tok_lesseq) printStr = "<="; - else if (Op == tok_greateq) printStr = ">="; - else printStr = printStr + (char)Op; - - //Serial.printf("Call from BinaryExprAST: %s\n", printStr.c_str()); - - if (RHS == nullptr || LHS == nullptr) return nullptr; - - IoTValue* rhs = RHS->exec(); // получаем значение правого операнда для возможного использования в операции присваивания - - if (Op == '=' && LHS->setValue(rhs)) { // если установка значения не поддерживается, т.е. слева не переменная, то работаем по другим комбинациям далее - return rhs; // иначе возвращаем присвоенное значение справа + ~BinaryExprAST() { + if (LHS) delete LHS; + if (RHS) delete RHS; + // Serial.printf("Call from BinaryExprAST delete\n"); } - IoTValue* lhs = LHS->exec(); // если присваивания не произошло, значит операция иная и необходимо значение левого операнда - - if (lhs != nullptr && rhs !=nullptr) { - if (lhs->isDecimal && rhs->isDecimal) { - switch (Op) { - case '>': - val.valD = lhs->valD > rhs->valD; - break; - case '<': - val.valD = lhs->valD < rhs->valD; - break; - case tok_lesseq: - val.valD = lhs->valD <= rhs->valD; - break; - case tok_greateq: - val.valD = lhs->valD >= rhs->valD; - break; - case tok_equal: - val.valD = lhs->valD == rhs->valD; - break; - case tok_notequal: - val.valD = lhs->valD != rhs->valD; - break; + IoTValue *exec() { + if (isIotScenException) return nullptr; + String printStr = ""; - case '+': - val.valD = lhs->valD + rhs->valD; - break; - case '-': - val.valD = lhs->valD - rhs->valD; - break; - case '*': - val.valD = lhs->valD * rhs->valD; - break; - case '/': - if (rhs->valD != 0) val.valD = lhs->valD / rhs->valD; - else val.valD = 3.4E+38; - break; + if (Op == tok_equal) + printStr = "=="; + else if (Op == tok_notequal) + printStr = "!="; + else if (Op == tok_lesseq) + printStr = "<="; + else if (Op == tok_greateq) + printStr = ">="; + else + printStr = printStr + (char)Op; - case '|': - val.valD = lhs->valD || rhs->valD; - break; - case '&': - val.valD = lhs->valD && rhs->valD; - break; + // Serial.printf("Call from BinaryExprAST: %s\n", printStr.c_str()); - default: - break; + if (RHS == nullptr || LHS == nullptr) return nullptr; + + IoTValue *rhs = RHS->exec(); // получаем значение правого операнда для возможного использования в операции присваивания + + if (Op == '=' && LHS->setValue(rhs)) { // если установка значения не поддерживается, т.е. слева не переменная, то работаем по другим комбинациям далее + return rhs; // иначе возвращаем присвоенное значение справа + } + + IoTValue *lhs = LHS->exec(); // если присваивания не произошло, значит операция иная и необходимо значение левого операнда + + if (lhs != nullptr && rhs != nullptr) { + if (lhs->isDecimal && rhs->isDecimal) { + switch (Op) { + case '>': + val.valD = lhs->valD > rhs->valD; + break; + case '<': + val.valD = lhs->valD < rhs->valD; + break; + case tok_lesseq: + val.valD = lhs->valD <= rhs->valD; + break; + case tok_greateq: + val.valD = lhs->valD >= rhs->valD; + break; + case tok_equal: + val.valD = lhs->valD == rhs->valD; + break; + case tok_notequal: + val.valD = lhs->valD != rhs->valD; + break; + + case '+': + val.valD = lhs->valD + rhs->valD; + break; + case '-': + val.valD = lhs->valD - rhs->valD; + break; + case '*': + val.valD = lhs->valD * rhs->valD; + break; + case '/': + if (rhs->valD != 0) + val.valD = lhs->valD / rhs->valD; + else + val.valD = 3.4E+38; + break; + + case '|': + val.valD = lhs->valD || rhs->valD; + break; + case '&': + val.valD = lhs->valD && rhs->valD; + break; + + default: + break; + } + return &val; + } + + if (!lhs->isDecimal || !rhs->isDecimal) { + if (lhs->isDecimal) + lhsStr = lhs->valD; + else + lhsStr = lhs->valS; + if (rhs->isDecimal) + rhsStr = rhs->valD; + else + rhsStr = rhs->valS; + switch (Op) { + case tok_equal: + val.valD = compStr(lhsStr, rhsStr); + break; + + case '+': + val.valS = lhsStr + rhsStr; + val.valD = 1; + val.isDecimal = false; + break; + + default: + break; + } + return &val; + } } return &val; - } + } - if (!lhs->isDecimal || !rhs->isDecimal) { - if (lhs->isDecimal) lhsStr = lhs->valD; else lhsStr = lhs->valS; - if (rhs->isDecimal) rhsStr = rhs->valD; else rhsStr = rhs->valS; - switch (Op) { - case tok_equal: - val.valD = compStr(lhsStr, rhsStr); - break; - - case '+': - val.valS = lhsStr + rhsStr; - val.valD = 1; - val.isDecimal = false; - break; - - default: - break; + bool compStr(String str1, String str2) { + if (str1.length() != str2.length()) return false; + for (int i = 0; i < str1.length(); i++) { + if (str1[i] == '*' || str2[i] == '*') continue; //считаем, что если есть подстановочная звезда, то символы равны + if (str1[i] != str2[i]) return false; } - return &val; - } - } - return &val; - } - bool compStr(String str1, String str2){ - if (str1.length() != str2.length()) return false; - for (int i = 0; i < str1.length(); i++) { - if (str1[i] == '*' || str2[i] == '*') continue; //считаем, что если есть подстановочная звезда, то символы равны - if (str1[i] != str2[i]) return false; + return true; // str1 == str2; } - - return true;//str1 == str2; - } - }; /// CallExprAST - Класс узла выражения для вызова команды. class CallExprAST : public ExprAST { - String Callee; - String Cmd; - std::vector Args; - IoTItem *Item; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID - IoTValue ret; // хранение возвращаемого значения, т.к. возврат по ссылке осуществляется - bool ItemIsLocal = false; + String Callee; + String Cmd; + std::vector Args; + IoTItem *Item; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID + IoTValue ret; // хранение возвращаемого значения, т.к. возврат по ссылке осуществляется + bool ItemIsLocal = false; -public: - CallExprAST(const String &callee, String &cmd, std::vector &args, IoTItem *item) - : Callee(callee), Cmd(cmd), Args(args), Item(item) { - if (item) ItemIsLocal = item->iAmLocal; + public: + CallExprAST(const String &callee, String &cmd, std::vector &args, IoTItem *item) + : Callee(callee), Cmd(cmd), Args(args), Item(item) { + if (item) ItemIsLocal = item->iAmLocal; } - IoTValue* exec() { - if (isIotScenException) return nullptr; // если прерывание, то сразу выходим - - if (Cmd == "exit" || Callee == "exit") { // если системная команда, то выполняем и выходим - IoTValue* tmp; - if (Args.size() > 0 && Args[0]) tmp = Args[0]->exec(); - else SerialPrint("i", "SysExt", "Exit"); - if (tmp) SerialPrint("i", "SysExt", "Exit = '" + tmp->valS + "'"); - - isIotScenException = true; - return nullptr; + IoTValue *exec() { + if (isIotScenException) return nullptr; // если прерывание, то сразу выходим + + if (Cmd == "exit" || Callee == "exit") { // если системная команда, то выполняем и выходим + IoTValue *tmp; + if (Args.size() > 0 && Args[0]) + tmp = Args[0]->exec(); + else + SerialPrint("i", "SysExt", "Exit"); + if (tmp) SerialPrint("i", "SysExt", "Exit = '" + tmp->valS + "'"); + + isIotScenException = true; + return nullptr; + } + + if (!ItemIsLocal) Item = findIoTItem(Callee); // пробуем найти переменную если она не локальная (могла придти по сети в процессе) + if (!Item) return nullptr; // ret = zeroIotVal; // если все же не пришла, то либо опечатка, либо уже стерлась - выходим + + // если все же все ок, то готовим параметры для передачи в модуль + std::vector ArgsAsIoTValue; + for (unsigned int i = 0; i < Args.size(); i++) { + if (Args[i] == nullptr) return nullptr; + IoTValue *tmp = Args[i]->exec(); + if (tmp != nullptr) + ArgsAsIoTValue.push_back(*tmp); + else + return nullptr; // ArgsAsIoTValue.push_back(zeroIotVal); + } + + ret = Item->execute(Cmd, ArgsAsIoTValue); // вызываем команду из модуля напрямую с передачей всех аргументов + + // if (ret.isDecimal) Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %f\n", Callee.c_str(), Cmd.c_str(), ret.valD); + // else Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %s\n", Callee.c_str(), Cmd.c_str(), ret.valS.c_str()); + return &ret; } - if (!ItemIsLocal) Item = findIoTItem(Callee); // пробуем найти переменную если она не локальная (могла придти по сети в процессе) - if (!Item) return nullptr; //ret = zeroIotVal; // если все же не пришла, то либо опечатка, либо уже стерлась - выходим - - // если все же все ок, то готовим параметры для передачи в модуль - std::vector ArgsAsIoTValue; - for (unsigned int i = 0; i < Args.size(); i++) { - if (Args[i] == nullptr) return nullptr; - IoTValue *tmp = Args[i]->exec(); - if (tmp != nullptr) ArgsAsIoTValue.push_back(*tmp); - else return nullptr; //ArgsAsIoTValue.push_back(zeroIotVal); + ~CallExprAST() { + for (unsigned int i = 0; i < Args.size(); i++) { + if (Args[i]) delete Args[i]; + } + Args.clear(); + // Serial.printf("Call from CallExprAST delete\n"); } - - ret = Item->execute(Cmd, ArgsAsIoTValue); // вызываем команду из модуля напрямую с передачей всех аргументов - - //if (ret.isDecimal) Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %f\n", Callee.c_str(), Cmd.c_str(), ret.valD); - //else Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %s\n", Callee.c_str(), Cmd.c_str(), ret.valS.c_str()); - return &ret; - } - - ~CallExprAST() { - for (unsigned int i = 0; i < Args.size(); i++) { - if (Args[i]) delete Args[i]; - } - Args.clear(); - //Serial.printf("Call from CallExprAST delete\n"); - } }; - -// Для сокращения количества преобразований используем числовые коды для фиксации названия системной функции, +// Для сокращения количества преобразований используем числовые коды для фиксации названия системной функции, // которые поддерживает прошивка enum SysOp { - sysop_notfound = 0, - sysop_reboot = 1, - sysop_digitalRead, - sysop_analogRead, // - sysop_digitalWrite, // - sysop_digitalInvert, // - sysop_deepSleep, // - sysop_getHours, // - sysop_getMinutes, // - sysop_getSeconds, // - sysop_getMonth, // - sysop_getDay, - sysop_gethhmm, - sysop_gethhmmss, - sysop_getTime, - sysop_getIP, - sysop_mqttPub + sysop_notfound = 0, + sysop_reboot = 1, + sysop_digitalRead, + sysop_analogRead, // + sysop_digitalWrite, // + sysop_digitalInvert, // + sysop_deepSleep, // + sysop_getHours, // + sysop_getMinutes, // + sysop_getSeconds, // + sysop_getMonth, // + sysop_getDay, + sysop_gethhmm, + sysop_gethhmmss, + sysop_getTime, + sysop_getIP, + sysop_mqttPub }; -IoTValue sysExecute(SysOp command, std::vector& param) { - IoTValue value = {}; +IoTValue sysExecute(SysOp command, std::vector ¶m) { + IoTValue value = {}; - if (_time_isTrust) - switch (command) { - case sysop_getHours: - value.valD = _time_local.hour; - break; - case sysop_getMinutes: - value.valD = _time_local.minute; - break; - case sysop_getSeconds: - value.valD = _time_local.second; - break; - case sysop_getMonth: - value.valD = _time_local.month; - break; - case sysop_getDay: - value.valD = _time_local.day_of_month; - break; - case sysop_gethhmm: + if (_time_isTrust) + switch (command) { + case sysop_getHours: + value.valD = _time_local.hour; + break; + case sysop_getMinutes: + value.valD = _time_local.minute; + break; + case sysop_getSeconds: + value.valD = _time_local.second; + break; + case sysop_getMonth: + value.valD = _time_local.month; + break; + case sysop_getDay: + value.valD = _time_local.day_of_month; + break; + case sysop_gethhmm: + value.isDecimal = false; + value.valS = getTimeLocal_hhmm(); + break; + case sysop_gethhmmss: + value.isDecimal = false; + value.valS = getTimeLocal_hhmmss(); + break; + case sysop_getTime: + value.isDecimal = false; + value.valS = getDateTimeDotFormated(); + break; + } + else { value.isDecimal = false; - value.valS = getTimeLocal_hhmm(); - break; - case sysop_gethhmmss: - value.isDecimal = false; - value.valS = getTimeLocal_hhmmss(); - break; - case sysop_getTime: - value.isDecimal = false; - value.valS = getDateTimeDotFormated(); - break; + value.valS = "none"; } - else { - value.isDecimal = false; - value.valS = "none"; - } - switch (command) { - case sysop_reboot: - ESP.restart(); - break; - case sysop_digitalRead: - if (param.size()) { - IoTgpio.pinMode(param[0].valD, INPUT); - value.valD = IoTgpio.digitalRead(param[0].valD); - } - break; - case sysop_analogRead: - if (param.size()) { - IoTgpio.pinMode(param[0].valD, INPUT); - value.valD = IoTgpio.analogRead(param[0].valD); - } - break; - case sysop_digitalWrite: - if (param.size() == 2) { - IoTgpio.pinMode(param[0].valD, OUTPUT); - IoTgpio.digitalWrite(param[0].valD, param[1].valD); - } - break; - case sysop_digitalInvert: - if (param.size()) { - IoTgpio.pinMode(param[0].valD, OUTPUT); - IoTgpio.digitalInvert(param[0].valD); - } - break; - case sysop_deepSleep: - if (param.size()) { - Serial.printf("Ушел спать на %d сек...", (int)param[0].valD); + switch (command) { + case sysop_reboot: + ESP.restart(); + break; + case sysop_digitalRead: + if (param.size()) { + IoTgpio.pinMode(param[0].valD, INPUT); + value.valD = IoTgpio.digitalRead(param[0].valD); + } + break; + case sysop_analogRead: + if (param.size()) { + IoTgpio.pinMode(param[0].valD, INPUT); + value.valD = IoTgpio.analogRead(param[0].valD); + } + break; + case sysop_digitalWrite: + if (param.size() == 2) { + IoTgpio.pinMode(param[0].valD, OUTPUT); + IoTgpio.digitalWrite(param[0].valD, param[1].valD); + } + break; + case sysop_digitalInvert: + if (param.size()) { + IoTgpio.pinMode(param[0].valD, OUTPUT); + IoTgpio.digitalInvert(param[0].valD); + } + break; + case sysop_deepSleep: + if (param.size()) { + Serial.printf("Ушел спать на %d сек...", (int)param[0].valD); #ifdef ESP32 - esp_sleep_enable_timer_wakeup(param[0].valD * 1000000); - delay(1000); - esp_deep_sleep_start(); + esp_sleep_enable_timer_wakeup(param[0].valD * 1000000); + delay(1000); + esp_deep_sleep_start(); #else - ESP.deepSleep(param[0].valD * 1000000); + ESP.deepSleep(param[0].valD * 1000000); #endif - } - break; - case sysop_getIP: - value.valS = jsonReadStr(settingsFlashJson, F("ip")); - value.isDecimal = false; - break; - case sysop_mqttPub: - if (param.size() == 2) { - //Serial.printf("Call from sysExecute %s %s\n", param[0].valS.c_str(), param[1].valS.c_str()); - value.valD = mqtt.publish(param[0].valS.c_str(), param[1].valS.c_str(), false); - } - break; - } + } + break; + case sysop_getIP: + value.valS = jsonReadStr(settingsFlashJson, F("ip")); + value.isDecimal = false; + break; + case sysop_mqttPub: + if (param.size() == 2) { + // Serial.printf("Call from sysExecute %s %s\n", param[0].valS.c_str(), param[1].valS.c_str()); + value.valD = mqtt.publish(param[0].valS.c_str(), param[1].valS.c_str(), false); + } + break; + } - return value; + return value; } /// SysCallExprAST - Класс узла выражения для вызова системных команд. class SysCallExprAST : public ExprAST { - String Callee; - std::vector Args; - IoTValue ret; // хранение возвращаемого значения, т.к. возврат по ссылке осуществляется - //bool ItemIsLocal = false; - SysOp operation; + String Callee; + std::vector Args; + IoTValue ret; // хранение возвращаемого значения, т.к. возврат по ссылке осуществляется + // bool ItemIsLocal = false; + SysOp operation; -public: - SysCallExprAST(const String &callee, std::vector &args) - : Callee(callee), Args(args) { - if (Callee == "reboot") operation = sysop_reboot; else - if (Callee == "digitalRead") operation = sysop_digitalRead; else - if (Callee == "analogRead") operation = sysop_analogRead; else - if (Callee == "digitalWrite") operation = sysop_digitalWrite; else - if (Callee == "digitalInvert") operation = sysop_digitalInvert; else - if (Callee == "deepSleep") operation = sysop_deepSleep; else - if (Callee == "getTime") operation = sysop_getTime; else - if (Callee == "getHours") operation = sysop_getHours; else - if (Callee == "getMinutes") operation = sysop_getMinutes; else - if (Callee == "getSeconds") operation = sysop_getSeconds; else - if (Callee == "getMonth") operation = sysop_getMonth; else - if (Callee == "getDay") operation = sysop_getDay; else - if (Callee == "getIP") operation = sysop_getIP; else - if (Callee == "mqttPub") operation = sysop_mqttPub; else - if (Callee == "gethhmm") operation = sysop_gethhmm; else - if (Callee == "gethhmmss") operation = sysop_gethhmmss; else - if (Callee == "getTime") operation = sysop_getTime; else - operation = sysop_notfound; + public: + SysCallExprAST(const String &callee, std::vector &args) + : Callee(callee), Args(args) { + if (Callee == "reboot") + operation = sysop_reboot; + else if (Callee == "digitalRead") + operation = sysop_digitalRead; + else if (Callee == "analogRead") + operation = sysop_analogRead; + else if (Callee == "digitalWrite") + operation = sysop_digitalWrite; + else if (Callee == "digitalInvert") + operation = sysop_digitalInvert; + else if (Callee == "deepSleep") + operation = sysop_deepSleep; + else if (Callee == "getTime") + operation = sysop_getTime; + else if (Callee == "getHours") + operation = sysop_getHours; + else if (Callee == "getMinutes") + operation = sysop_getMinutes; + else if (Callee == "getSeconds") + operation = sysop_getSeconds; + else if (Callee == "getMonth") + operation = sysop_getMonth; + else if (Callee == "getDay") + operation = sysop_getDay; + else if (Callee == "getIP") + operation = sysop_getIP; + else if (Callee == "mqttPub") + operation = sysop_mqttPub; + else if (Callee == "gethhmm") + operation = sysop_gethhmm; + else if (Callee == "gethhmmss") + operation = sysop_gethhmmss; + else if (Callee == "getTime") + operation = sysop_getTime; + else + operation = sysop_notfound; } - IoTValue* exec() { - Serial.printf("Call from SysCallExprAST exec %d\n", operation); - - if (isIotScenException) return nullptr; // если прерывание, то сразу выходим - - // готовим параметры для передачи в в функцию интерпретатор действий - std::vector ArgsAsIoTValue; - for (unsigned int i = 0; i < Args.size(); i++) { - if (Args[i] == nullptr) return nullptr; - IoTValue *tmp = Args[i]->exec(); - if (tmp != nullptr) ArgsAsIoTValue.push_back(*tmp); - else return nullptr; + IoTValue *exec() { + Serial.printf("Call from SysCallExprAST exec %d\n", operation); + + if (isIotScenException) return nullptr; // если прерывание, то сразу выходим + + // готовим параметры для передачи в в функцию интерпретатор действий + std::vector ArgsAsIoTValue; + for (unsigned int i = 0; i < Args.size(); i++) { + if (Args[i] == nullptr) return nullptr; + IoTValue *tmp = Args[i]->exec(); + if (tmp != nullptr) + ArgsAsIoTValue.push_back(*tmp); + else + return nullptr; + } + + ret = sysExecute(operation, ArgsAsIoTValue); // вызываем функцию интерпретатор с передачей всех аргументов + + return &ret; } - ret = sysExecute(operation, ArgsAsIoTValue); // вызываем функцию интерпретатор с передачей всех аргументов - - return &ret; - } - - ~SysCallExprAST() { - for (unsigned int i = 0; i < Args.size(); i++) { - if (Args[i]) delete Args[i]; + ~SysCallExprAST() { + for (unsigned int i = 0; i < Args.size(); i++) { + if (Args[i]) delete Args[i]; + } + Args.clear(); + // Serial.printf("Call from CallExprAST delete\n"); } - Args.clear(); - //Serial.printf("Call from CallExprAST delete\n"); - } }; /// IfExprAST - Класс узла выражения для if/then/else. class IfExprAST : public ExprAST { - ExprAST *Cond, *Then, *Else; - String _IDNames; + ExprAST *Cond, *Then, *Else; + String _IDNames; -public: - IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else, String *IDNames) - : Cond(cond), Then(then), Else(_else) { - if (IDNames) { - _IDNames = *IDNames; - } else _IDNames = ""; + public: + IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else, String *IDNames) + : Cond(cond), Then(then), Else(_else) { + if (IDNames) { + _IDNames = *IDNames; + } else + _IDNames = ""; } - bool hasEventIdName(String eventIdName) { - //Serial.printf("Call from BinaryExprAST _IDNames:%s\n", _IDNames.c_str()); - return _IDNames.indexOf(" " + eventIdName + " ") >= 0; // определяем встречался ли ИД, для которого исполняем сценарий в выражении IF - } - - IoTValue* exec() { - if (isIotScenException) return nullptr; - IoTValue *res_ret = nullptr; - IoTValue *cond_ret = nullptr; - - if (Cond) cond_ret = Cond->exec(); - - if (!cond_ret) { - //Serial.printf("Call from IfExprAST: Skip If\n"); - return nullptr; //&zeroIotVal; + bool hasEventIdName(String eventIdName) { + // Serial.printf("Call from BinaryExprAST _IDNames:%s\n", _IDNames.c_str()); + return _IDNames.indexOf(" " + eventIdName + " ") >= 0; // определяем встречался ли ИД, для которого исполняем сценарий в выражении IF } - if (cond_ret->isDecimal && cond_ret->valD) { - if (Then == nullptr) return nullptr; - res_ret = Then->exec(); - } else { - if (Else == nullptr) return nullptr; - res_ret = Else->exec(); - } + IoTValue *exec() { + if (isIotScenException) return nullptr; + IoTValue *res_ret = nullptr; + IoTValue *cond_ret = nullptr; - //if (!res_ret) Serial.printf("Call from IfExprAST: Cond result = %f, no body result\n", cond_ret->valD); - //else if (res_ret->isDecimal) Serial.printf("Call from IfExprAST: Cond result = %f, result = %f\n", cond_ret->valD, res_ret->valD); - //else Serial.printf("Call from IfExprAST: Cond result = %f, result = %s\n", cond_ret->valD, res_ret->valS.c_str()); - Serial.printf("\n"); - return cond_ret; - } + if (Cond) cond_ret = Cond->exec(); - ~IfExprAST() { - if (Cond) delete Cond; - if (Then) delete Then; - if (Else) delete Else; - //Serial.printf("Call from IfExprAST delete\n"); - } + if (!cond_ret) { + // Serial.printf("Call from IfExprAST: Skip If\n"); + return nullptr; //&zeroIotVal; + } + + if (cond_ret->isDecimal && cond_ret->valD) { + if (Then == nullptr) return nullptr; + res_ret = Then->exec(); + } else { + if (Else == nullptr) return nullptr; + res_ret = Else->exec(); + } + + // if (!res_ret) Serial.printf("Call from IfExprAST: Cond result = %f, no body result\n", cond_ret->valD); + // else if (res_ret->isDecimal) Serial.printf("Call from IfExprAST: Cond result = %f, result = %f\n", cond_ret->valD, res_ret->valD); + // else Serial.printf("Call from IfExprAST: Cond result = %f, result = %s\n", cond_ret->valD, res_ret->valS.c_str()); + Serial.printf("\n"); + return cond_ret; + } + + ~IfExprAST() { + if (Cond) delete Cond; + if (Then) delete Then; + if (Else) delete Else; + // Serial.printf("Call from IfExprAST delete\n"); + } }; /// BracketsExprAST - Класс узла блока кода {}. class BracketsExprAST : public ExprAST { - std::vector BracketsList; + std::vector BracketsList; -public: - BracketsExprAST(std::vector &bracketsList) - : BracketsList(bracketsList) {} + public: + BracketsExprAST(std::vector &bracketsList) + : BracketsList(bracketsList) {} - IoTValue* exec() { - if (isIotScenException) return nullptr; - //Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size()); - - IoTValue* lastExecValue = nullptr; - for (unsigned int i = 0; i < BracketsList.size(); i++) { - if (BracketsList[i] == nullptr) return nullptr; - lastExecValue = BracketsList[i]->exec(); + IoTValue *exec() { + if (isIotScenException) return nullptr; + // Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size()); + + IoTValue *lastExecValue = nullptr; + for (unsigned int i = 0; i < BracketsList.size(); i++) { + if (BracketsList[i] == nullptr) return nullptr; + lastExecValue = BracketsList[i]->exec(); + } + + return lastExecValue; } - return lastExecValue; - } + ~BracketsExprAST() { + for (unsigned int i = 0; i < BracketsList.size(); i++) { + if (BracketsList[i]) delete BracketsList[i]; + } + BracketsList.clear(); - ~BracketsExprAST() { - for (unsigned int i = 0; i < BracketsList.size(); i++) { - if (BracketsList[i]) delete BracketsList[i]; + // Serial.printf("Call from BracketsExprAST delete\n"); } - BracketsList.clear(); - - //Serial.printf("Call from BracketsExprAST delete\n"); - } }; +//===----------------------------------------------------------------------===// +// Lexer (Лексический анализатор) +//===----------------------------------------------------------------------===// - //===----------------------------------------------------------------------===// - // Lexer (Лексический анализатор) - //===----------------------------------------------------------------------===// - - - char IoTScenario::getLastChar() { +char IoTScenario::getLastChar() { strIterator++; return strFromFile->charAt(strIterator - 1); - } - - /// gettok - Возвращает следующий токен из стандартного потока ввода. - int IoTScenario::gettok() { +} +/// gettok - Возвращает следующий токен из стандартного потока ввода. +int IoTScenario::gettok() { // Пропускаем пробелы. while (isspace(LastChar)) - LastChar = getLastChar(); + LastChar = getLastChar(); - if (isalpha(LastChar) || LastChar == '_') { // идентификатор: [a-zA-Z][a-zA-Z0-9]* - IdentifierStr = LastChar; - while (isalnum((LastChar = getLastChar())) || LastChar == '_'){ - IdentifierStr += LastChar; - } + if (isalpha(LastChar) || LastChar == '_') { // идентификатор: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = getLastChar())) || LastChar == '_') { + IdentifierStr += LastChar; + } - //Serial.printf("%s ", IdentifierStr.c_str()); + // Serial.printf("%s ", IdentifierStr.c_str()); - if (IdentifierStr == "if") return tok_if; - if (IdentifierStr == "then") return tok_then; - if (IdentifierStr == "else") return tok_else; - return tok_identifier; + if (IdentifierStr == "if") return tok_if; + if (IdentifierStr == "then") return tok_then; + if (IdentifierStr == "else") return tok_else; + return tok_identifier; } - if (isdigit(LastChar)) { // Число: [0-9.]+ - String NumStr; - do { - NumStr += LastChar; - LastChar = getLastChar(); - } while (isdigit(LastChar) || LastChar == '.'); + if (isdigit(LastChar)) { // Число: [0-9.]+ + String NumStr; + do { + NumStr += LastChar; + LastChar = getLastChar(); + } while (isdigit(LastChar) || LastChar == '.'); - NumVal = strtod(NumStr.c_str(), 0); - return tok_number; + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; } if (LastChar == '#') { - // Комментарий до конца строки - do LastChar = getLastChar(); - while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - - if (LastChar != EOF) - return gettok(); + // Комментарий до конца строки + do LastChar = getLastChar(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); } - if (LastChar == '"') { // "строка" - IdentifierStr = ""; - LastChar = getLastChar(); - while (LastChar != '"') { - IdentifierStr += LastChar; + if (LastChar == '"') { // "строка" + IdentifierStr = ""; LastChar = getLastChar(); - } - LastChar = getLastChar(); - - return tok_string; + while (LastChar != '"') { + IdentifierStr += LastChar; + LastChar = getLastChar(); + } + LastChar = getLastChar(); + + return tok_string; } - + // Проверка конца файла. - //if (LastChar == EOF) + // if (LastChar == EOF) // return tok_eof; if (LastChar == '=') { - LastChar = getLastChar(); - if (LastChar == '=') { LastChar = getLastChar(); - return tok_equal; - } else return '='; + if (LastChar == '=') { + LastChar = getLastChar(); + return tok_equal; + } else + return '='; } if (LastChar == '!') { - LastChar = getLastChar(); - if (LastChar == '=') { LastChar = getLastChar(); - return tok_notequal; - } else return '!'; + if (LastChar == '=') { + LastChar = getLastChar(); + return tok_notequal; + } else + return '!'; } if (LastChar == '<') { - LastChar = getLastChar(); - if (LastChar == '=') { LastChar = getLastChar(); - return tok_lesseq; - } else return '<'; + if (LastChar == '=') { + LastChar = getLastChar(); + return tok_lesseq; + } else + return '<'; } if (LastChar == '>') { - LastChar = getLastChar(); - if (LastChar == '=') { LastChar = getLastChar(); - return tok_greateq; - } else return '>'; + if (LastChar == '=') { + LastChar = getLastChar(); + return tok_greateq; + } else + return '>'; } // В противном случае просто возвращаем символ как значение ASCII int ThisChar = LastChar; LastChar = getLastChar(); return ThisChar; - } +} +//===----------------------------------------------------------------------===// +// Parser (Парсер или Синтаксический Анализатор) +//===----------------------------------------------------------------------===// - //===----------------------------------------------------------------------===// - // Parser (Парсер или Синтаксический Анализатор) - //===----------------------------------------------------------------------===// - - - /// CurTok/getNextToken - Предоставляет простой буфер токенов. CurTok - это текущий - /// токен, просматриваемый парсером. getNextToken получает следующий токен от - /// лексического анализатора и обновляет CurTok. - int IoTScenario::getNextToken() { +/// CurTok/getNextToken - Предоставляет простой буфер токенов. CurTok - это текущий +/// токен, просматриваемый парсером. getNextToken получает следующий токен от +/// лексического анализатора и обновляет CurTok. +int IoTScenario::getNextToken() { return CurTok = gettok(); - } +} - /// GetTokPrecedence - Возвращает приоритет текущего бинарного оператора. - int IoTScenario::GetTokPrecedence() { +/// GetTokPrecedence - Возвращает приоритет текущего бинарного оператора. +int IoTScenario::GetTokPrecedence() { if (!(isascii(CurTok) || BinopPrecedence.count(CurTok))) - return -1; - + return -1; + // Удостоверимся, что это объявленный бинарный оператор. int TokPrec = BinopPrecedence[CurTok]; if (TokPrec <= 0) return -1; return TokPrec; - } +} - /// Error* - Это небольшие вспомогательные функции для обработки ошибок. - ExprAST* IoTScenario::Error(const char *Str) { Serial.printf("Error: %s\n", Str); return nullptr;} +/// Error* - Это небольшие вспомогательные функции для обработки ошибок. +ExprAST *IoTScenario::Error(const char *Str) { + Serial.printf("Error: %s\n", Str); + return nullptr; +} - - /// identifierexpr - /// ::= identifier - /// ::= identifier '(' expression* ')' - ExprAST* IoTScenario::ParseIdentifierExpr(String *IDNames) { +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +ExprAST *IoTScenario::ParseIdentifierExpr(String *IDNames) { String IdName = IdentifierStr; String Cmd = ""; - IoTItem* tmpItem = findIoTItem(IdName); + IoTItem *tmpItem = findIoTItem(IdName); getNextToken(); // получаем идентификатор. - + if (CurTok == '.') { - getNextToken(); - Cmd = IdentifierStr; - getNextToken(); + getNextToken(); + Cmd = IdentifierStr; + getNextToken(); } - if (CurTok != '(') { // Обычная переменная. - // if (tmpItem) return new VariableExprAST(IdName, tmpItem); - // else return new StringExprAST("id " + IdName + " not_found"); + if (CurTok != '(') { // Обычная переменная. + // if (tmpItem) return new VariableExprAST(IdName, tmpItem); + // else return new StringExprAST("id " + IdName + " not_found"); - // создаем экземпляр переменной в любом случае, даж если не нашли (tmpItem = nulptr), т.к. переменная может придти из сети позже - return new VariableExprAST(IdName, tmpItem); + // создаем экземпляр переменной в любом случае, даж если не нашли (tmpItem = nulptr), т.к. переменная может придти из сети позже + return new VariableExprAST(IdName, tmpItem); } - + // Вызов функции. getNextToken(); // получаем ( - std::vector Args; + std::vector Args; if (CurTok != ')') { - while (1) { - ExprAST *Arg = ParseExpression(IDNames); - if (!Arg) return 0; - Args.push_back(Arg); + while (1) { + ExprAST *Arg = ParseExpression(IDNames); + if (!Arg) return 0; + Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') break; - if (CurTok != ',') - return Error("Expected ')' or ',' in argument list"); - getNextToken(); - } + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } } // Получаем ';'. getNextToken(); - - if (Cmd == "") - return new SysCallExprAST(IdName, Args); // создаем объект запуска системной функции + + if (Cmd == "") + return new SysCallExprAST(IdName, Args); // создаем объект запуска системной функции else - return new CallExprAST(IdName, Cmd, Args, tmpItem); // создаем объект запуска функции в любом случае даж если не нашли Item + return new CallExprAST(IdName, Cmd, Args, tmpItem); // создаем объект запуска функции в любом случае даж если не нашли Item +} - } - - /// numberexpr ::= number - ExprAST* IoTScenario::ParseNumberExpr() { +/// numberexpr ::= number +ExprAST *IoTScenario::ParseNumberExpr() { ExprAST *Result = new NumberExprAST(NumVal); - getNextToken(); // получаем число + getNextToken(); // получаем число return Result; - } +} - /// parenexpr ::= '(' expression ')' - ExprAST* IoTScenario::ParseParenExpr() { +/// parenexpr ::= '(' expression ')' +ExprAST *IoTScenario::ParseParenExpr() { getNextToken(); // получаем (. ExprAST *V = ParseExpression(nullptr); if (!V) return 0; - + if (CurTok != ')') - return Error("expected ')'"); + return Error("expected ')'"); getNextToken(); // получаем ). return V; - } +} - /// bracketsexpr ::= '{' expression '}' - ExprAST* IoTScenario::ParseBracketsExpr() { +/// bracketsexpr ::= '{' expression '}' +ExprAST *IoTScenario::ParseBracketsExpr() { getNextToken(); // получаем {. - std::vector bracketsList; + std::vector bracketsList; if (CurTok != '}') { - while (1) { - ExprAST *Expr = ParseExpression(nullptr); - if (!Expr) return 0; - bracketsList.push_back(Expr); + while (1) { + ExprAST *Expr = ParseExpression(nullptr); + if (!Expr) return 0; + bracketsList.push_back(Expr); - if (CurTok != ';') - return Error("Expected ';' in operation list"); - int ttok = getNextToken(); - if (!ttok) { Error("Expected '}'"); break; } - - if (CurTok == '}') break; + if (CurTok != ';') + return Error("Expected ';' in operation list"); + int ttok = getNextToken(); + if (!ttok) { + Error("Expected '}'"); + break; + } - - } + if (CurTok == '}') break; + } } - + getNextToken(); // получаем }. return new BracketsExprAST(bracketsList); - } +} - /// quotesexpr ::= '"' expression '"' - ExprAST* IoTScenario::ParseQuotesExpr() { +/// quotesexpr ::= '"' expression '"' +ExprAST *IoTScenario::ParseQuotesExpr() { String StringCont = IdentifierStr; ExprAST *Result = new StringExprAST(StringCont); - getNextToken(); // получаем число + getNextToken(); // получаем число return Result; - } +} - /// ifexpr ::= 'if' expression 'then' expression 'else' expression - ExprAST* IoTScenario::ParseIfExpr(String *IDNames) { +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +ExprAST *IoTScenario::ParseIfExpr(String *IDNames) { getNextToken(); // Получаем if. - + // условие. ExprAST *Cond = ParseExpression(IDNames); if (!Cond) return 0; - + if (CurTok != tok_then) - return Error("expected then"); + return Error("expected then"); getNextToken(); // Получаем then - + ExprAST *Then = ParseExpression(nullptr); if (!Then) return 0; - - //if (CurTok != tok_else) - // return Error("expected else"); + + // if (CurTok != tok_else) + // return Error("expected else"); ExprAST *Else = nullptr; if (CurTok == tok_else) { - getNextToken(); - Else = ParseExpression(nullptr); + getNextToken(); + Else = ParseExpression(nullptr); } return new IfExprAST(Cond, Then, Else, IDNames); - } +} - /// primary - /// ::= identifierexpr - /// ::= numberexpr - /// ::= parenexpr - ExprAST* IoTScenario::ParsePrimary(String* IDNames) { +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +ExprAST *IoTScenario::ParsePrimary(String *IDNames) { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: { - if (IDNames) { - String tmpstr = *IDNames; - *IDNames = tmpstr + " " + IdentifierStr + " "; - } - return ParseIdentifierExpr(IDNames); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: { + if (IDNames) { + String tmpstr = *IDNames; + *IDNames = tmpstr + " " + IdentifierStr + " "; + } + return ParseIdentifierExpr(IDNames); + } + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case '{': + return ParseBracketsExpr(); + case tok_string: + return ParseQuotesExpr(); + case tok_if: + return ParseIfExpr(IDNames); } - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); - case '{': return ParseBracketsExpr(); - case tok_string: return ParseQuotesExpr(); - case tok_if: return ParseIfExpr(IDNames); - } - } +} - /// binoprhs - /// ::= ('+' primary)* - ExprAST* IoTScenario::ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames) { +/// binoprhs +/// ::= ('+' primary)* +ExprAST *IoTScenario::ParseBinOpRHS(int ExprPrec, ExprAST *LHS, String *IDNames) { // Если это бинарный оператор, получаем его приоритет while (1) { - int TokPrec = GetTokPrecedence(); - - // Если этот бинарный оператор связывает выражения по крайней мере так же, - // как текущий, то используем его - if (TokPrec < ExprPrec) - return LHS; - - // Отлично, мы знаем, что это бинарный оператор. - int BinOp = CurTok; - getNextToken(); // eat binop - - // Разобрать первичное выражение после бинарного оператора - ExprAST *RHS = ParsePrimary(IDNames); - if (!RHS) return 0; - - // Если BinOp связан с RHS меньшим приоритетом, чем оператор после RHS, - // то берём часть вместе с RHS как LHS. - int NextPrec = GetTokPrecedence(); - if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS, IDNames); - if (RHS == 0) return 0; - } - - // Собираем LHS/RHS. - LHS = new BinaryExprAST(BinOp, LHS, RHS); - } - } - + int TokPrec = GetTokPrecedence(); - /// expression - /// ::= primary binoprhs - /// - ExprAST* IoTScenario::ParseExpression(String *IDNames) { + // Если этот бинарный оператор связывает выражения по крайней мере так же, + // как текущий, то используем его + if (TokPrec < ExprPrec) + return LHS; + + // Отлично, мы знаем, что это бинарный оператор. + int BinOp = CurTok; + getNextToken(); // eat binop + + // Разобрать первичное выражение после бинарного оператора + ExprAST *RHS = ParsePrimary(IDNames); + if (!RHS) return 0; + + // Если BinOp связан с RHS меньшим приоритетом, чем оператор после RHS, + // то берём часть вместе с RHS как LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec + 1, RHS, IDNames); + if (RHS == 0) return 0; + } + + // Собираем LHS/RHS. + LHS = new BinaryExprAST(BinOp, LHS, RHS); + } +} + +/// expression +/// ::= primary binoprhs +/// +ExprAST *IoTScenario::ParseExpression(String *IDNames) { ExprAST *LHS = ParsePrimary(IDNames); if (!LHS) return 0; return ParseBinOpRHS(0, LHS, IDNames); - } +} - void IoTScenario::clearScenarioElements() { // удаляем все корневые элементы дерева AST +void IoTScenario::clearScenarioElements() { // удаляем все корневые элементы дерева AST for (unsigned int i = 0; i < ScenarioElements.size(); i++) { - if (ScenarioElements[i]) delete ScenarioElements[i]; + if (ScenarioElements[i]) delete ScenarioElements[i]; } ScenarioElements.clear(); - } +} - void IoTScenario::loadScenario(String fileName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST - clearScenarioElements(); // удаляем все корневые элементы перед загрузкой новых. +void IoTScenario::loadScenario(String fileName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST + clearScenarioElements(); // удаляем все корневые элементы перед загрузкой новых. LastChar = ' '; File myfile = seekFile(fileName); if (myfile.available()) { - strFromFile = new String(""); - *strFromFile = myfile.readString(); - myfile.close(); + strFromFile = new String(""); + *strFromFile = myfile.readString(); + Serial.println(*strFromFile); + jsonRead(*strFromFile, "scen", *strFromFile, true); + myfile.close(); - getNextToken(); - while (strIterator < strFromFile->length()-1) { - //Serial.printf("-%c", LastChar); - switch (CurTok) { - //case tok_eof: return; - //case ';': getNextToken(); break; // игнорируем верхнеуровневые точки с запятой. - case tok_if: { - String IDNames = ""; // накопитель встречающихся идентификаторов в условии - ScenarioElements.push_back(ParseIfExpr(&IDNames)); - //Serial.printf("vvvvvvvvvvvvvvvv %s", IDNames.c_str()); - break; - } - default: getNextToken(); break; + getNextToken(); + while (strIterator < strFromFile->length() - 1) { + // Serial.printf("-%c", LastChar); + switch (CurTok) { + // case tok_eof: return; + // case ';': getNextToken(); break; // игнорируем верхнеуровневые точки с запятой. + case tok_if: { + String IDNames = ""; // накопитель встречающихся идентификаторов в условии + ScenarioElements.push_back(ParseIfExpr(&IDNames)); + // Serial.printf("vvvvvvvvvvvvvvvv %s", IDNames.c_str()); + break; + } + default: + getNextToken(); + break; + } } - } - delete strFromFile; - strIterator = 0; - } else {Error("Open file scenario error");} - } + delete strFromFile; + strIterator = 0; + } else { + Error("Open file scenario error"); + } +} - void IoTScenario::ExecScenario(String eventIdName) { // запускаем поочереди все корневые элементы выражений в сценарии, ожидаемо - это IFы - // eventIdName - ID элемента для которого выполняем сценарий, т.е. игнорируем любые проверки, если нет такого ID в условиях +void IoTScenario::ExecScenario(String eventIdName) { // запускаем поочереди все корневые элементы выражений в сценарии, ожидаемо - это IFы + // eventIdName - ID элемента для которого выполняем сценарий, т.е. игнорируем любые проверки, если нет такого ID в условиях isIotScenException = false; Serial.printf("Count root elements in scenario: %d\n", ScenarioElements.size()); for (unsigned int i = 0; i < ScenarioElements.size(); i++) { - if (ScenarioElements[i] && ScenarioElements[i]->hasEventIdName(eventIdName)) ScenarioElements[i]->exec(); - //else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str()); - if (isIotScenException) return; + if (ScenarioElements[i] && ScenarioElements[i]->hasEventIdName(eventIdName)) ScenarioElements[i]->exec(); + // else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str()); + if (isIotScenException) return; } - } +} - - IoTScenario::IoTScenario() { +IoTScenario::IoTScenario() { // Задаём стандартные бинарные операторы. // 1 - наименьший приоритет. - BinopPrecedence['='] = 1; - BinopPrecedence['|'] = 5; - BinopPrecedence['&'] = 6; - BinopPrecedence[tok_equal] = 10; // == + BinopPrecedence['='] = 1; + BinopPrecedence['|'] = 5; + BinopPrecedence['&'] = 6; + BinopPrecedence[tok_equal] = 10; // == BinopPrecedence[tok_notequal] = 11; // != - BinopPrecedence[tok_lesseq] = 15; // <= - BinopPrecedence[tok_greateq] = 16; // >= + BinopPrecedence[tok_lesseq] = 15; // <= + BinopPrecedence[tok_greateq] = 16; // >= BinopPrecedence['<'] = 20; BinopPrecedence['>'] = 21; BinopPrecedence['+'] = 25; BinopPrecedence['-'] = 26; - BinopPrecedence['/'] = 27; + BinopPrecedence['/'] = 27; BinopPrecedence['*'] = 28; // highest. - } - - IoTScenario::~IoTScenario() {} \ No newline at end of file +} + +IoTScenario::~IoTScenario() {}