mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-31 04:19:15 +03:00
не рабочая версия
This commit is contained in:
3
data_svelte/scenario.json
Normal file
3
data_svelte/scenario.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"scen": ""
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <map>
|
||||
|
||||
class ExprAST {
|
||||
public:
|
||||
public:
|
||||
virtual ~ExprAST();
|
||||
virtual IoTValue* exec();
|
||||
virtual IoTValue *exec();
|
||||
virtual int setValue(IoTValue *val); // ret 0 - установка значения не поддерживается наследником
|
||||
virtual bool hasEventIdName(String eventIdName);
|
||||
};
|
||||
@@ -60,13 +60,13 @@ class IoTScenario {
|
||||
ExprAST *ParseQuotesExpr();
|
||||
|
||||
/// ifexpr ::= 'if' expression 'then' expression 'else' expression
|
||||
ExprAST *ParseIfExpr(String* IDNames);
|
||||
ExprAST *ParseIfExpr(String *IDNames);
|
||||
|
||||
/// primary
|
||||
/// ::= identifierexpr
|
||||
/// ::= numberexpr
|
||||
/// ::= parenexpr
|
||||
ExprAST *ParsePrimary(String* IDNames);
|
||||
ExprAST *ParsePrimary(String *IDNames);
|
||||
|
||||
/// binoprhs
|
||||
/// ::= ('+' primary)*
|
||||
@@ -77,7 +77,7 @@ class IoTScenario {
|
||||
///
|
||||
ExprAST *ParseExpression(String *IDNames);
|
||||
|
||||
std::vector<ExprAST*> ScenarioElements; // корневые элементы дерава
|
||||
std::vector<ExprAST *> ScenarioElements; // корневые элементы дерава
|
||||
|
||||
String *strFromFile;
|
||||
char getLastChar();
|
||||
@@ -85,7 +85,7 @@ class IoTScenario {
|
||||
|
||||
void clearScenarioElements();
|
||||
|
||||
public:
|
||||
public:
|
||||
void loadScenario(String fileName);
|
||||
void ExecScenario(String eventIdName);
|
||||
|
||||
|
||||
@@ -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", "");
|
||||
|
||||
@@ -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", "");
|
||||
|
||||
@@ -9,43 +9,49 @@
|
||||
|
||||
bool isIotScenException; // признак исключения и попытки прекратить выполнение сценария заранее
|
||||
|
||||
|
||||
// Лексический анализатор возвращает токены [0-255], если это неизвестны,
|
||||
// иначе одну из известных единиц кода
|
||||
enum Token {
|
||||
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* exec() {
|
||||
public:
|
||||
NumberExprAST(float val) { Val.valD = val; }
|
||||
|
||||
IoTValue *exec() {
|
||||
if (isIotScenException) return nullptr;
|
||||
//Serial.printf("Call from NumberExprAST: %f\n", Val.valD);
|
||||
// Serial.printf("Call from NumberExprAST: %f\n", Val.valD);
|
||||
return &Val;
|
||||
}
|
||||
};
|
||||
@@ -53,12 +59,16 @@ public:
|
||||
/// StringExprAST - Класс узла выражения для строковых литералов (Например, "Example with spaces and quotes").
|
||||
class StringExprAST : public ExprAST {
|
||||
IoTValue Val;
|
||||
public:
|
||||
StringExprAST(String val) { Val.isDecimal = false; Val.valS = val;}
|
||||
|
||||
IoTValue* exec() {
|
||||
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());
|
||||
// Serial.printf("Call from StringExprAST: %s\n", Val.valS.c_str());
|
||||
return &Val;
|
||||
}
|
||||
};
|
||||
@@ -66,29 +76,31 @@ public:
|
||||
/// VariableExprAST - Класс узла выражения для переменных (например, "a").
|
||||
class VariableExprAST : public ExprAST {
|
||||
String Name;
|
||||
IoTItem* Item; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID
|
||||
IoTItem *Item; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID
|
||||
bool ItemIsLocal = false;
|
||||
|
||||
public:
|
||||
VariableExprAST(const String &name, IoTItem* item) : Name(name), Item(item) {
|
||||
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;
|
||||
if (Item)
|
||||
Item->setValue(*val);
|
||||
else
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
IoTValue* exec() {
|
||||
IoTValue *exec() {
|
||||
if (isIotScenException) return nullptr;
|
||||
if (!ItemIsLocal) Item = findIoTItem(Name);
|
||||
if (Item) {
|
||||
//if (Item->value.isDecimal)
|
||||
// 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());
|
||||
// else Serial.printf("Call from VariableExprAST: %s = %s\n", Name.c_str(), Item->value.valS.c_str());
|
||||
return &(Item->value);
|
||||
}
|
||||
|
||||
@@ -103,39 +115,44 @@ class BinaryExprAST : public ExprAST {
|
||||
IoTValue val;
|
||||
String lhsStr, rhsStr;
|
||||
|
||||
public:
|
||||
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");
|
||||
// Serial.printf("Call from BinaryExprAST delete\n");
|
||||
}
|
||||
|
||||
IoTValue* exec(){
|
||||
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;
|
||||
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());
|
||||
// Serial.printf("Call from BinaryExprAST: %s\n", printStr.c_str());
|
||||
|
||||
if (RHS == nullptr || LHS == nullptr) return nullptr;
|
||||
|
||||
IoTValue* rhs = RHS->exec(); // получаем значение правого операнда для возможного использования в операции присваивания
|
||||
IoTValue *rhs = RHS->exec(); // получаем значение правого операнда для возможного использования в операции присваивания
|
||||
|
||||
if (Op == '=' && LHS->setValue(rhs)) { // если установка значения не поддерживается, т.е. слева не переменная, то работаем по другим комбинациям далее
|
||||
return rhs; // иначе возвращаем присвоенное значение справа
|
||||
}
|
||||
|
||||
IoTValue* lhs = LHS->exec(); // если присваивания не произошло, значит операция иная и необходимо значение левого операнда
|
||||
IoTValue *lhs = LHS->exec(); // если присваивания не произошло, значит операция иная и необходимо значение левого операнда
|
||||
|
||||
if (lhs != nullptr && rhs !=nullptr) {
|
||||
if (lhs != nullptr && rhs != nullptr) {
|
||||
if (lhs->isDecimal && rhs->isDecimal) {
|
||||
switch (Op) {
|
||||
case '>':
|
||||
@@ -167,8 +184,10 @@ public:
|
||||
val.valD = lhs->valD * rhs->valD;
|
||||
break;
|
||||
case '/':
|
||||
if (rhs->valD != 0) val.valD = lhs->valD / rhs->valD;
|
||||
else val.valD = 3.4E+38;
|
||||
if (rhs->valD != 0)
|
||||
val.valD = lhs->valD / rhs->valD;
|
||||
else
|
||||
val.valD = 3.4E+38;
|
||||
break;
|
||||
|
||||
case '|':
|
||||
@@ -185,8 +204,14 @@ public:
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
@@ -207,40 +232,41 @@ public:
|
||||
return &val;
|
||||
}
|
||||
|
||||
bool compStr(String str1, String str2){
|
||||
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<ExprAST*> Args;
|
||||
std::vector<ExprAST *> Args;
|
||||
IoTItem *Item; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID
|
||||
IoTValue ret; // хранение возвращаемого значения, т.к. возврат по ссылке осуществляется
|
||||
bool ItemIsLocal = false;
|
||||
|
||||
public:
|
||||
CallExprAST(const String &callee, String &cmd, std::vector<ExprAST*> &args, IoTItem *item)
|
||||
public:
|
||||
CallExprAST(const String &callee, String &cmd, std::vector<ExprAST *> &args, IoTItem *item)
|
||||
: Callee(callee), Cmd(cmd), Args(args), Item(item) {
|
||||
if (item) ItemIsLocal = item->iAmLocal;
|
||||
}
|
||||
|
||||
IoTValue* exec() {
|
||||
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");
|
||||
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;
|
||||
@@ -248,21 +274,23 @@ public:
|
||||
}
|
||||
|
||||
if (!ItemIsLocal) Item = findIoTItem(Callee); // пробуем найти переменную если она не локальная (могла придти по сети в процессе)
|
||||
if (!Item) return nullptr; //ret = zeroIotVal; // если все же не пришла, то либо опечатка, либо уже стерлась - выходим
|
||||
if (!Item) return nullptr; // ret = zeroIotVal; // если все же не пришла, то либо опечатка, либо уже стерлась - выходим
|
||||
|
||||
// если все же все ок, то готовим параметры для передачи в модуль
|
||||
std::vector<IoTValue> 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);
|
||||
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());
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -271,11 +299,10 @@ public:
|
||||
if (Args[i]) delete Args[i];
|
||||
}
|
||||
Args.clear();
|
||||
//Serial.printf("Call from CallExprAST delete\n");
|
||||
// Serial.printf("Call from CallExprAST delete\n");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Для сокращения количества преобразований используем числовые коды для фиксации названия системной функции,
|
||||
// которые поддерживает прошивка
|
||||
enum SysOp {
|
||||
@@ -298,7 +325,7 @@ enum SysOp {
|
||||
sysop_mqttPub
|
||||
};
|
||||
|
||||
IoTValue sysExecute(SysOp command, std::vector<IoTValue>& param) {
|
||||
IoTValue sysExecute(SysOp command, std::vector<IoTValue> ¶m) {
|
||||
IoTValue value = {};
|
||||
|
||||
if (_time_isTrust)
|
||||
@@ -382,7 +409,7 @@ IoTValue sysExecute(SysOp command, std::vector<IoTValue>& param) {
|
||||
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());
|
||||
// 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;
|
||||
@@ -394,35 +421,53 @@ IoTValue sysExecute(SysOp command, std::vector<IoTValue>& param) {
|
||||
/// SysCallExprAST - Класс узла выражения для вызова системных команд.
|
||||
class SysCallExprAST : public ExprAST {
|
||||
String Callee;
|
||||
std::vector<ExprAST*> Args;
|
||||
std::vector<ExprAST *> Args;
|
||||
IoTValue ret; // хранение возвращаемого значения, т.к. возврат по ссылке осуществляется
|
||||
//bool ItemIsLocal = false;
|
||||
// bool ItemIsLocal = false;
|
||||
SysOp operation;
|
||||
|
||||
public:
|
||||
SysCallExprAST(const String &callee, std::vector<ExprAST*> &args)
|
||||
public:
|
||||
SysCallExprAST(const String &callee, std::vector<ExprAST *> &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
|
||||
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() {
|
||||
IoTValue *exec() {
|
||||
Serial.printf("Call from SysCallExprAST exec %d\n", operation);
|
||||
|
||||
if (isIotScenException) return nullptr; // если прерывание, то сразу выходим
|
||||
@@ -432,8 +477,10 @@ public:
|
||||
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;
|
||||
if (tmp != nullptr)
|
||||
ArgsAsIoTValue.push_back(*tmp);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ret = sysExecute(operation, ArgsAsIoTValue); // вызываем функцию интерпретатор с передачей всех аргументов
|
||||
@@ -446,7 +493,7 @@ public:
|
||||
if (Args[i]) delete Args[i];
|
||||
}
|
||||
Args.clear();
|
||||
//Serial.printf("Call from CallExprAST delete\n");
|
||||
// Serial.printf("Call from CallExprAST delete\n");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -455,20 +502,21 @@ class IfExprAST : public ExprAST {
|
||||
ExprAST *Cond, *Then, *Else;
|
||||
String _IDNames;
|
||||
|
||||
public:
|
||||
public:
|
||||
IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else, String *IDNames)
|
||||
: Cond(cond), Then(then), Else(_else) {
|
||||
if (IDNames) {
|
||||
_IDNames = *IDNames;
|
||||
} else _IDNames = "";
|
||||
} else
|
||||
_IDNames = "";
|
||||
}
|
||||
|
||||
bool hasEventIdName(String eventIdName) {
|
||||
//Serial.printf("Call from BinaryExprAST _IDNames:%s\n", _IDNames.c_str());
|
||||
// Serial.printf("Call from BinaryExprAST _IDNames:%s\n", _IDNames.c_str());
|
||||
return _IDNames.indexOf(" " + eventIdName + " ") >= 0; // определяем встречался ли ИД, для которого исполняем сценарий в выражении IF
|
||||
}
|
||||
|
||||
IoTValue* exec() {
|
||||
IoTValue *exec() {
|
||||
if (isIotScenException) return nullptr;
|
||||
IoTValue *res_ret = nullptr;
|
||||
IoTValue *cond_ret = nullptr;
|
||||
@@ -476,7 +524,7 @@ public:
|
||||
if (Cond) cond_ret = Cond->exec();
|
||||
|
||||
if (!cond_ret) {
|
||||
//Serial.printf("Call from IfExprAST: Skip If\n");
|
||||
// Serial.printf("Call from IfExprAST: Skip If\n");
|
||||
return nullptr; //&zeroIotVal;
|
||||
}
|
||||
|
||||
@@ -488,9 +536,9 @@ public:
|
||||
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());
|
||||
// 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;
|
||||
}
|
||||
@@ -499,23 +547,23 @@ public:
|
||||
if (Cond) delete Cond;
|
||||
if (Then) delete Then;
|
||||
if (Else) delete Else;
|
||||
//Serial.printf("Call from IfExprAST delete\n");
|
||||
// Serial.printf("Call from IfExprAST delete\n");
|
||||
}
|
||||
};
|
||||
|
||||
/// BracketsExprAST - Класс узла блока кода {}.
|
||||
class BracketsExprAST : public ExprAST {
|
||||
std::vector<ExprAST*> BracketsList;
|
||||
std::vector<ExprAST *> BracketsList;
|
||||
|
||||
public:
|
||||
BracketsExprAST(std::vector<ExprAST*> &bracketsList)
|
||||
public:
|
||||
BracketsExprAST(std::vector<ExprAST *> &bracketsList)
|
||||
: BracketsList(bracketsList) {}
|
||||
|
||||
IoTValue* exec() {
|
||||
IoTValue *exec() {
|
||||
if (isIotScenException) return nullptr;
|
||||
//Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size());
|
||||
// Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size());
|
||||
|
||||
IoTValue* lastExecValue = nullptr;
|
||||
IoTValue *lastExecValue = nullptr;
|
||||
for (unsigned int i = 0; i < BracketsList.size(); i++) {
|
||||
if (BracketsList[i] == nullptr) return nullptr;
|
||||
lastExecValue = BracketsList[i]->exec();
|
||||
@@ -530,35 +578,32 @@ public:
|
||||
}
|
||||
BracketsList.clear();
|
||||
|
||||
//Serial.printf("Call from BracketsExprAST delete\n");
|
||||
// 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();
|
||||
|
||||
if (isalpha(LastChar) || LastChar == '_') { // идентификатор: [a-zA-Z][a-zA-Z0-9]*
|
||||
IdentifierStr = LastChar;
|
||||
while (isalnum((LastChar = getLastChar())) || 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;
|
||||
@@ -599,7 +644,7 @@ public:
|
||||
}
|
||||
|
||||
// Проверка конца файла.
|
||||
//if (LastChar == EOF)
|
||||
// if (LastChar == EOF)
|
||||
// return tok_eof;
|
||||
|
||||
if (LastChar == '=') {
|
||||
@@ -607,7 +652,8 @@ public:
|
||||
if (LastChar == '=') {
|
||||
LastChar = getLastChar();
|
||||
return tok_equal;
|
||||
} else return '=';
|
||||
} else
|
||||
return '=';
|
||||
}
|
||||
|
||||
if (LastChar == '!') {
|
||||
@@ -615,7 +661,8 @@ public:
|
||||
if (LastChar == '=') {
|
||||
LastChar = getLastChar();
|
||||
return tok_notequal;
|
||||
} else return '!';
|
||||
} else
|
||||
return '!';
|
||||
}
|
||||
|
||||
if (LastChar == '<') {
|
||||
@@ -623,7 +670,8 @@ public:
|
||||
if (LastChar == '=') {
|
||||
LastChar = getLastChar();
|
||||
return tok_lesseq;
|
||||
} else return '<';
|
||||
} else
|
||||
return '<';
|
||||
}
|
||||
|
||||
if (LastChar == '>') {
|
||||
@@ -631,30 +679,29 @@ public:
|
||||
if (LastChar == '=') {
|
||||
LastChar = getLastChar();
|
||||
return tok_greateq;
|
||||
} else return '>';
|
||||
} 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;
|
||||
|
||||
@@ -662,19 +709,21 @@ public:
|
||||
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(); // получаем идентификатор.
|
||||
|
||||
@@ -694,7 +743,7 @@ public:
|
||||
|
||||
// Вызов функции.
|
||||
getNextToken(); // получаем (
|
||||
std::vector<ExprAST*> Args;
|
||||
std::vector<ExprAST *> Args;
|
||||
if (CurTok != ')') {
|
||||
while (1) {
|
||||
ExprAST *Arg = ParseExpression(IDNames);
|
||||
@@ -716,18 +765,17 @@ public:
|
||||
return new SysCallExprAST(IdName, Args); // создаем объект запуска системной функции
|
||||
else
|
||||
return new CallExprAST(IdName, Cmd, Args, tmpItem); // создаем объект запуска функции в любом случае даж если не нашли Item
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// numberexpr ::= number
|
||||
ExprAST* IoTScenario::ParseNumberExpr() {
|
||||
/// numberexpr ::= number
|
||||
ExprAST *IoTScenario::ParseNumberExpr() {
|
||||
ExprAST *Result = new NumberExprAST(NumVal);
|
||||
getNextToken(); // получаем число
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
|
||||
/// parenexpr ::= '(' expression ')'
|
||||
ExprAST* IoTScenario::ParseParenExpr() {
|
||||
/// parenexpr ::= '(' expression ')'
|
||||
ExprAST *IoTScenario::ParseParenExpr() {
|
||||
getNextToken(); // получаем (.
|
||||
ExprAST *V = ParseExpression(nullptr);
|
||||
if (!V) return 0;
|
||||
@@ -736,12 +784,12 @@ public:
|
||||
return Error("expected ')'");
|
||||
getNextToken(); // получаем ).
|
||||
return V;
|
||||
}
|
||||
}
|
||||
|
||||
/// bracketsexpr ::= '{' expression '}'
|
||||
ExprAST* IoTScenario::ParseBracketsExpr() {
|
||||
/// bracketsexpr ::= '{' expression '}'
|
||||
ExprAST *IoTScenario::ParseBracketsExpr() {
|
||||
getNextToken(); // получаем {.
|
||||
std::vector<ExprAST*> bracketsList;
|
||||
std::vector<ExprAST *> bracketsList;
|
||||
if (CurTok != '}') {
|
||||
while (1) {
|
||||
ExprAST *Expr = ParseExpression(nullptr);
|
||||
@@ -751,28 +799,29 @@ public:
|
||||
if (CurTok != ';')
|
||||
return Error("Expected ';' in operation list");
|
||||
int ttok = getNextToken();
|
||||
if (!ttok) { Error("Expected '}'"); break; }
|
||||
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(); // получаем число
|
||||
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.
|
||||
|
||||
// условие.
|
||||
@@ -786,7 +835,7 @@ public:
|
||||
ExprAST *Then = ParseExpression(nullptr);
|
||||
if (!Then) return 0;
|
||||
|
||||
//if (CurTok != tok_else)
|
||||
// if (CurTok != tok_else)
|
||||
// return Error("expected else");
|
||||
ExprAST *Else = nullptr;
|
||||
if (CurTok == tok_else) {
|
||||
@@ -795,15 +844,16 @@ public:
|
||||
}
|
||||
|
||||
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");
|
||||
default:
|
||||
return Error("unknown token when expecting an expression");
|
||||
case tok_identifier: {
|
||||
if (IDNames) {
|
||||
String tmpstr = *IDNames;
|
||||
@@ -811,17 +861,22 @@ public:
|
||||
}
|
||||
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();
|
||||
@@ -843,33 +898,32 @@ public:
|
||||
// то берём часть вместе с RHS как LHS.
|
||||
int NextPrec = GetTokPrecedence();
|
||||
if (TokPrec < NextPrec) {
|
||||
RHS = ParseBinOpRHS(TokPrec+1, RHS, IDNames);
|
||||
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) {
|
||||
/// 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];
|
||||
}
|
||||
ScenarioElements.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void IoTScenario::loadScenario(String fileName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST
|
||||
void IoTScenario::loadScenario(String fileName) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST
|
||||
clearScenarioElements(); // удаляем все корневые элементы перед загрузкой новых.
|
||||
LastChar = ' ';
|
||||
|
||||
@@ -877,41 +931,46 @@ public:
|
||||
if (myfile.available()) {
|
||||
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);
|
||||
while (strIterator < strFromFile->length() - 1) {
|
||||
// Serial.printf("-%c", LastChar);
|
||||
switch (CurTok) {
|
||||
//case tok_eof: return;
|
||||
//case ';': getNextToken(); break; // игнорируем верхнеуровневые точки с запятой.
|
||||
// case tok_eof: return;
|
||||
// case ';': getNextToken(); break; // игнорируем верхнеуровневые точки с запятой.
|
||||
case tok_if: {
|
||||
String IDNames = ""; // накопитель встречающихся идентификаторов в условии
|
||||
ScenarioElements.push_back(ParseIfExpr(&IDNames));
|
||||
//Serial.printf("vvvvvvvvvvvvvvvv %s", IDNames.c_str());
|
||||
// Serial.printf("vvvvvvvvvvvvvvvv %s", IDNames.c_str());
|
||||
break;
|
||||
}
|
||||
default: getNextToken(); break;
|
||||
default:
|
||||
getNextToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete strFromFile;
|
||||
strIterator = 0;
|
||||
} else {Error("Open file scenario error");}
|
||||
} else {
|
||||
Error("Open file scenario error");
|
||||
}
|
||||
}
|
||||
|
||||
void IoTScenario::ExecScenario(String eventIdName) { // запускаем поочереди все корневые элементы выражений в сценарии, ожидаемо - это IFы
|
||||
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());
|
||||
// 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;
|
||||
@@ -927,6 +986,6 @@ public:
|
||||
BinopPrecedence['-'] = 26;
|
||||
BinopPrecedence['/'] = 27;
|
||||
BinopPrecedence['*'] = 28; // highest.
|
||||
}
|
||||
}
|
||||
|
||||
IoTScenario::~IoTScenario() {}
|
||||
IoTScenario::~IoTScenario() {}
|
||||
|
||||
Reference in New Issue
Block a user