2022-02-14 12:48:59 +03:00
# include "Global.h"
2022-02-15 11:37:31 +01:00
# include "classes/IoTItem.h"
# include "classes/IoTScenario.h"
# include "utils/FileUtils.h"
2022-08-21 20:53:49 +03:00
# include "NTP.h"
2022-02-24 00:54:56 +03:00
2022-09-05 23:24:57 +03:00
bool isIotScenException = false ; // признак исключения и попытки прекратить выполнение сценария заранее
2022-02-28 00:49:57 +03:00
2022-08-23 13:06:01 +02:00
// Лексический анализатор возвращает токены [0-255], если это неизвестны,
2022-02-14 12:48:59 +03:00
// иначе одну из известных единиц кода
enum Token {
2022-08-23 13:06:01 +02:00
tok_eof = - 1 ,
// операнды (первичные выражения: идентификаторы, числа)
tok_identifier = - 4 ,
tok_number = - 5 ,
tok_string = - 3 ,
// двухсимвольные операторы бинарных операций
tok_equal = - 2 ,
tok_notequal = - 9 ,
tok_lesseq = - 10 ,
tok_greateq = - 11 ,
2022-10-27 10:50:09 +03:00
tok_silentset = - 12 ,
2022-08-23 13:06:01 +02:00
// управление
tok_if = - 6 ,
tok_then = - 7 ,
tok_else = - 8
2022-02-14 12:48:59 +03:00
} ;
//===----------------------------------------------------------------------===//
// Abstract Syntax Tree (Абстрактное Синтаксическое Дерево или Дерево Парсинга)
//===----------------------------------------------------------------------===//
/// ExprAST - Базовый класс для всех узлов выражений.
ExprAST : : ~ ExprAST ( ) { }
2022-08-23 13:06:01 +02:00
IoTValue * ExprAST : : exec ( ) { return nullptr ; }
2022-10-27 10:50:09 +03:00
int ExprAST : : setValue ( IoTValue * val , bool generateEvent ) { return 0 ; } // 0 - установка значения не поддерживается наследником
2022-11-04 16:47:46 +03:00
bool ExprAST : : hasEventIdName ( const String & eventIdName ) { return false ; } // по умолчанию все узлы не связаны с ИД события, для которого выполняется сценарий
2022-08-23 13:06:01 +02:00
// struct IoTValue zeroIotVal;
2022-02-14 12:48:59 +03:00
/// NumberExprAST - Класс узла выражения для числовых литералов (Например, "1.0").
class NumberExprAST : public ExprAST {
2022-08-23 13:06:01 +02:00
IoTValue Val ;
public :
2022-09-14 18:53:02 +02:00
NumberExprAST ( String val ) {
2022-09-05 16:26:27 +03:00
Val . valD = strtod ( val . c_str ( ) , 0 ) ;
Val . valS = val ;
}
2022-08-23 13:06:01 +02:00
IoTValue * exec ( ) {
if ( isIotScenException ) return nullptr ;
// Serial.printf("Call from NumberExprAST: %f\n", Val.valD);
return & Val ;
}
2022-02-14 12:48:59 +03:00
} ;
/// StringExprAST - Класс узла выражения для строковых литералов (Например, "Example with spaces and quotes").
class StringExprAST : public ExprAST {
2022-08-23 13:06:01 +02:00
IoTValue 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 ;
}
2022-02-14 12:48:59 +03:00
} ;
/// VariableExprAST - Класс узла выражения для переменных (например, "a").
2022-02-23 20:14:29 +03:00
class VariableExprAST : public ExprAST {
2022-08-23 13:06:01 +02:00
String Name ;
IoTItem * Item ; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID
2022-11-01 12:33:39 +03:00
//bool ItemIsLocal = false;
2022-08-23 13:06:01 +02:00
public :
VariableExprAST ( const String & name , IoTItem * item ) : Name ( name ) , Item ( item ) {
2022-11-01 12:33:39 +03:00
//if (item) ItemIsLocal = item->iAmLocal;
2022-08-23 13:06:01 +02:00
}
2022-10-27 10:50:09 +03:00
int setValue ( IoTValue * val , bool generateEvent ) {
2022-11-01 12:33:39 +03:00
//if (!ItemIsLocal) Item = findIoTItem(Name);
2022-08-23 13:06:01 +02:00
if ( Item )
2022-10-27 10:50:09 +03:00
Item - > setValue ( * val , generateEvent ) ;
2022-08-23 13:06:01 +02:00
else
return 0 ;
return 1 ;
}
IoTValue * exec ( ) {
if ( isIotScenException ) return nullptr ;
2022-11-01 12:33:39 +03:00
//if (!ItemIsLocal) Item = findIoTItem(Name);
2022-08-23 13:06:01 +02:00
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 ) ;
}
2022-11-01 12:33:39 +03:00
SerialPrint ( " E " , Name , " The element is not found or the connection is lost " , Name ) ;
2022-08-23 13:06:01 +02:00
return nullptr ; // Item не найден.
}
2022-02-14 12:48:59 +03:00
} ;
/// BinaryExprAST - Класс узла выражения для бинарных операторов.
class BinaryExprAST : public ExprAST {
2022-08-23 13:06:01 +02:00
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 ) { }
~ BinaryExprAST ( ) {
if ( LHS ) delete LHS ;
if ( RHS ) delete RHS ;
// Serial.printf("Call from BinaryExprAST delete\n");
}
IoTValue * exec ( ) {
if ( isIotScenException ) return nullptr ;
2022-08-28 21:56:47 +03:00
// 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;
2022-08-23 13:06:01 +02:00
// Serial.printf("Call from BinaryExprAST: %s\n", printStr.c_str());
if ( RHS = = nullptr | | LHS = = nullptr ) return nullptr ;
IoTValue * rhs = RHS - > exec ( ) ; // получаем значение правого операнда для возможного использования в операции присваивания
2022-10-22 22:53:49 +03:00
if ( rhs = = nullptr ) return nullptr ;
2022-09-14 18:53:02 +02:00
2022-10-27 10:50:09 +03:00
if ( Op = = ' = ' & & LHS - > setValue ( rhs , true ) ) { // если установка значения не поддерживается, т.е . слева не переменная, то работаем по другим комбинациям далее
return rhs ; // иначе возвращаем присвоенное значение справа
}
if ( Op = = tok_silentset & & LHS - > setValue ( rhs , false ) ) { // если установка значения не поддерживается, т.е . слева не переменная, то работаем по другим комбинациям далее
2022-08-23 13:06:01 +02:00
return rhs ; // иначе возвращаем присвоенное значение справа
2022-02-14 12:48:59 +03:00
}
2022-08-23 13:06:01 +02:00
IoTValue * lhs = LHS - > exec ( ) ; // если присваивания не произошло, значит операция иная и необходимо значение левого операнда
2022-10-22 22:53:49 +03:00
if ( lhs = = nullptr ) return 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 ;
2022-08-23 13:06:01 +02:00
}
2022-10-22 22:53:49 +03:00
return & val ;
}
2022-08-23 13:06:01 +02:00
2022-10-22 22:53:49 +03:00
if ( ! lhs - > isDecimal | | ! rhs - > isDecimal ) {
if ( lhs - > isDecimal )
lhsStr = ( String ) lhs - > valD ;
else
lhsStr = lhs - > valS ;
2022-10-27 10:50:09 +03:00
2022-10-22 22:53:49 +03:00
if ( rhs - > isDecimal )
rhsStr = ( String ) rhs - > valD ;
else
rhsStr = rhs - > valS ;
2022-10-27 10:50:09 +03:00
2022-10-22 22:53:49 +03:00
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 ;
2022-08-23 13:06:01 +02:00
}
2022-10-22 22:53:49 +03:00
return & val ;
2022-02-14 12:48:59 +03:00
}
2022-10-22 22:53:49 +03:00
2022-02-14 12:48:59 +03:00
return & val ;
}
2022-05-06 11:59:47 +03:00
2022-08-23 13:06:01 +02:00
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 ;
}
2022-05-06 11:59:47 +03:00
2022-08-23 13:06:01 +02:00
return true ; // str1 == str2;
}
2022-02-14 12:48:59 +03:00
} ;
/// CallExprAST - Класс узла выражения для вызова команды.
class CallExprAST : public ExprAST {
2022-08-23 13:06:01 +02:00
String Callee ;
String Cmd ;
std : : vector < ExprAST * > Args ;
IoTItem * Item ; // ссылка на объект модуля (прямой доступ к идентификатору указанному в сценарии), если получилось найти модуль по ID
IoTValue ret ; // хранение возвращаемого значения, т.к. возврат по ссылке осуществляется
2022-11-01 12:33:39 +03:00
//bool ItemIsLocal = false;
2022-08-23 13:06:01 +02:00
public :
CallExprAST ( const String & callee , String & cmd , std : : vector < ExprAST * > & args , IoTItem * item )
: Callee ( callee ) , Cmd ( cmd ) , Args ( args ) , Item ( item ) {
2022-11-01 12:33:39 +03:00
//if (item) ItemIsLocal = item->iAmLocal;
2022-08-23 13:06:01 +02:00
}
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 ;
}
2022-02-14 12:48:59 +03:00
2022-11-01 12:33:39 +03:00
//if (!ItemIsLocal) Item = findIoTItem(Callee); // пробуем найти переменную если она не локальная (могла придти по сети в процессе)
2022-08-23 13:06:01 +02:00
if ( ! Item ) return nullptr ; // ret = zeroIotVal; // если все же не пришла, то либо опечатка, либо уже стерлась - выходим
2022-10-30 12:12:15 +03:00
if ( Cmd = = " getIntFromNet " ) {
ret . valD = Item - > getIntFromNet ( ) ;
ret . isDecimal = true ;
return & ret ;
}
2022-08-23 13:06:01 +02:00
// если все же все ок, то готовим параметры для передачи в модуль
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);
}
2022-08-21 20:53:49 +03:00
2022-08-23 13:06:01 +02:00
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");
}
} ;
// Для сокращения количества преобразований используем числовые коды для фиксации названия системной функции,
2022-08-21 20:53:49 +03:00
// которые поддерживает прошивка
enum SysOp {
2022-08-23 13:06:01 +02:00
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 ,
2022-10-22 11:34:52 +03:00
sysop_getRSSI ,
2022-08-23 13:06:01 +02:00
sysop_getIP ,
2022-09-17 22:04:06 +03:00
sysop_mqttPub ,
sysop_getUptime
2022-08-21 20:53:49 +03:00
} ;
2022-08-23 13:06:01 +02:00
IoTValue sysExecute ( SysOp command , std : : vector < IoTValue > & param ) {
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 :
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 = " none " ;
}
2022-08-23 10:06:45 +03:00
switch ( command ) {
2022-08-23 13:06:01 +02:00
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 ) ;
2022-08-21 20:53:49 +03:00
# ifdef ESP32
2022-08-23 13:06:01 +02:00
esp_sleep_enable_timer_wakeup ( param [ 0 ] . valD * 1000000 ) ;
delay ( 1000 ) ;
esp_deep_sleep_start ( ) ;
2022-08-21 20:53:49 +03:00
# else
2022-08-23 13:06:01 +02:00
ESP . deepSleep ( param [ 0 ] . valD * 1000000 ) ;
2022-08-21 20:53:49 +03:00
# endif
2022-08-23 13:06:01 +02:00
}
break ;
2022-10-22 11:34:52 +03:00
case sysop_getRSSI :
value . valD = WiFi . RSSI ( ) ;
value . isDecimal = true ;
break ;
2022-08-23 13:06:01 +02:00
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());
2022-10-22 08:01:33 +03:00
String tmpStr = param [ 1 ] . valS ;
if ( param [ 1 ] . isDecimal ) tmpStr = param [ 1 ] . valD ;
value . valD = mqtt . publish ( param [ 0 ] . valS . c_str ( ) , tmpStr . c_str ( ) , false ) ;
2022-08-23 13:06:01 +02:00
}
break ;
2022-09-17 22:04:06 +03:00
case sysop_getUptime :
value . valS = jsonReadStr ( errorsHeapJson , F ( " upt " ) ) ;
value . isDecimal = false ;
break ;
2022-08-23 13:06:01 +02:00
}
return value ;
2022-08-21 20:53:49 +03:00
}
/// SysCallExprAST - Класс узла выражения для вызова системных команд.
class SysCallExprAST : public ExprAST {
2022-08-23 13:06:01 +02:00
String Callee ;
std : : vector < ExprAST * > Args ;
IoTValue ret ; // хранение возвращаемого значения, т.к. возврат по ссылке осуществляется
// bool ItemIsLocal = false;
SysOp operation ;
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 ;
2022-10-22 11:34:52 +03:00
else if ( Callee = = " getRSSI " )
operation = sysop_getRSSI ;
2022-08-23 13:06:01 +02:00
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 ;
2022-09-17 22:04:06 +03:00
else if ( Callee = = " getUptime " )
operation = sysop_getUptime ;
2022-08-23 13:06:01 +02:00
else
operation = sysop_notfound ;
}
IoTValue * exec ( ) {
2022-09-14 18:53:02 +02:00
// Serial.printf("Call from SysCallExprAST exec %d\n", operation);
2022-08-23 13:06:01 +02:00
if ( isIotScenException ) return nullptr ; // если прерывание, то сразу выходим
// готовим параметры для передачи в в функцию интерпретатор действий
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 ;
}
ret = sysExecute ( operation , ArgsAsIoTValue ) ; // вызываем функцию интерпретатор с передачей всех аргументов
return & ret ;
}
~ 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");
}
2022-08-21 20:53:49 +03:00
} ;
2022-02-14 12:48:59 +03:00
/// IfExprAST - Класс узла выражения для if/then/else.
class IfExprAST : public ExprAST {
2022-08-23 13:06:01 +02:00
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 = " " ;
}
2022-11-04 16:47:46 +03:00
bool hasEventIdName ( const String & eventIdName ) {
2022-08-23 13:06:01 +02:00
// 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;
}
2022-10-22 22:53:49 +03:00
// если число больше нуля или строка не равна пустой, то считаем условие выполненным
if ( cond_ret - > isDecimal & & cond_ret - > valD | | ! ( cond_ret - > isDecimal ) & & cond_ret - > valS ! = " " ) {
2022-08-23 13:06:01 +02:00
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());
2022-10-28 16:21:49 +03:00
//Serial.printf("\n");
2022-08-23 13:06:01 +02:00
return cond_ret ;
}
~ IfExprAST ( ) {
if ( Cond ) delete Cond ;
if ( Then ) delete Then ;
if ( Else ) delete Else ;
// Serial.printf("Call from IfExprAST delete\n");
}
2022-02-14 12:48:59 +03:00
} ;
/// BracketsExprAST - Класс узла блока кода {}.
class BracketsExprAST : public ExprAST {
2022-08-23 13:06:01 +02:00
std : : vector < ExprAST * > BracketsList ;
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
public :
BracketsExprAST ( std : : vector < ExprAST * > & bracketsList )
: BracketsList ( bracketsList ) { }
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
IoTValue * exec ( ) {
if ( isIotScenException ) return nullptr ;
// Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size());
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
IoTValue * lastExecValue = nullptr ;
for ( unsigned int i = 0 ; i < BracketsList . size ( ) ; i + + ) {
if ( BracketsList [ i ] = = nullptr ) return nullptr ;
lastExecValue = BracketsList [ i ] - > exec ( ) ;
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
return lastExecValue ;
2022-02-14 12:48:59 +03:00
}
2022-08-23 13:06:01 +02:00
~ BracketsExprAST ( ) {
for ( unsigned int i = 0 ; i < BracketsList . size ( ) ; i + + ) {
if ( BracketsList [ i ] ) delete BracketsList [ i ] ;
}
BracketsList . clear ( ) ;
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
// Serial.printf("Call from BracketsExprAST delete\n");
}
} ;
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
//===----------------------------------------------------------------------===//
// Lexer (Лексический анализатор)
//===----------------------------------------------------------------------===//
2022-02-14 12:48:59 +03:00
2022-08-30 14:00:22 +03:00
int IoTScenario : : getLastChar ( ) {
2022-09-04 19:16:08 +03:00
if ( mode = = 0 ) {
if ( file ) {
LastChar = file . read ( ) ;
if ( LastChar = = 10 ) curLine + + ;
return LastChar ;
2022-09-29 19:43:37 +02:00
} else
2022-09-14 18:53:02 +02:00
return EOF ;
2022-09-04 19:16:08 +03:00
} else if ( mode = = 1 ) {
if ( charCount < strFromFile . length ( ) ) {
LastChar = strFromFile . charAt ( charCount ) ;
2022-09-29 19:43:37 +02:00
// Serial.printf("%d, ", LastChar);
2022-09-04 19:16:08 +03:00
if ( LastChar = = 10 ) curLine + + ;
charCount + + ;
return LastChar ;
2022-09-29 19:43:37 +02:00
} else
2022-09-14 18:53:02 +02:00
return EOF ;
} else {
2022-09-14 21:29:26 +03:00
return EOF ;
2022-09-04 19:16:08 +03:00
}
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// gettok - Возвращает следующий токен из стандартного потока ввода.
int IoTScenario : : gettok ( ) {
2022-02-14 12:48:59 +03:00
// Пропускаем пробелы.
2022-09-30 08:36:35 +03:00
while ( isspace ( LastChar ) | | LastChar = = ' ; ' )
2022-08-23 13:06:01 +02:00
LastChar = getLastChar ( ) ;
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
if ( isalpha ( LastChar ) | | LastChar = = ' _ ' ) { // идентификатор: [a-zA-Z][a-zA-Z0-9]*
2022-08-30 14:00:22 +03:00
IdentifierStr = ( char ) LastChar ;
2022-08-23 13:06:01 +02:00
while ( isalnum ( ( LastChar = getLastChar ( ) ) ) | | LastChar = = ' _ ' ) {
2022-08-30 14:00:22 +03:00
IdentifierStr + = ( char ) LastChar ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
// Serial.printf("%s ", IdentifierStr.c_str());
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
if ( IdentifierStr = = " if " ) return tok_if ;
if ( IdentifierStr = = " then " ) return tok_then ;
if ( IdentifierStr = = " else " ) return tok_else ;
return tok_identifier ;
2022-02-14 12:48:59 +03:00
}
2022-09-14 18:53:02 +02:00
NumStr = " " ;
2022-08-31 08:52:43 +03:00
if ( LastChar = = ' - ' ) {
LastChar = getLastChar ( ) ;
2022-09-14 18:53:02 +02:00
if ( isdigit ( LastChar ) )
NumStr = " - " ;
else
return ' - ' ;
2022-08-31 08:52:43 +03:00
}
2022-08-23 13:06:01 +02:00
if ( isdigit ( LastChar ) ) { // Число: [0-9.]+
do {
2022-08-30 14:00:22 +03:00
NumStr + = ( char ) LastChar ;
2022-08-23 13:06:01 +02:00
LastChar = getLastChar ( ) ;
} while ( isdigit ( LastChar ) | | LastChar = = ' . ' ) ;
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
return tok_number ;
2022-02-14 12:48:59 +03:00
}
if ( LastChar = = ' # ' ) {
2022-08-23 13:06:01 +02:00
// Комментарий до конца строки
do LastChar = getLastChar ( ) ;
2022-08-30 14:00:22 +03:00
while ( LastChar ! = EOF & & LastChar ! = ' \n ' & & LastChar ! = ' \r ' ) ;
2022-08-28 20:33:43 +03:00
if ( LastChar ! = EOF )
return gettok ( ) ;
2022-08-23 13:06:01 +02:00
}
if ( LastChar = = ' " ' ) { // "строка"
IdentifierStr = " " ;
2022-02-14 12:48:59 +03:00
LastChar = getLastChar ( ) ;
2022-08-30 14:00:22 +03:00
while ( LastChar ! = ' " ' & & LastChar ! = EOF ) {
IdentifierStr + = ( char ) LastChar ;
2022-08-23 13:06:01 +02:00
LastChar = getLastChar ( ) ;
}
LastChar = getLastChar ( ) ;
return tok_string ;
2022-02-14 12:48:59 +03:00
}
2022-08-23 13:06:01 +02:00
2022-02-14 12:48:59 +03:00
// Проверка конца файла.
2022-08-30 14:00:22 +03:00
if ( LastChar = = EOF )
return tok_eof ;
2022-02-14 12:48:59 +03:00
if ( LastChar = = ' = ' ) {
LastChar = getLastChar ( ) ;
2022-08-23 13:06:01 +02:00
if ( LastChar = = ' = ' ) {
LastChar = getLastChar ( ) ;
return tok_equal ;
} else
return ' = ' ;
2022-02-14 12:48:59 +03:00
}
2022-10-27 10:50:09 +03:00
if ( LastChar = = ' : ' ) {
LastChar = getLastChar ( ) ;
if ( LastChar = = ' = ' ) {
LastChar = getLastChar ( ) ;
return tok_silentset ;
} else
return ' : ' ;
}
2022-02-14 12:48:59 +03:00
if ( LastChar = = ' ! ' ) {
LastChar = getLastChar ( ) ;
2022-08-23 13:06:01 +02:00
if ( LastChar = = ' = ' ) {
LastChar = getLastChar ( ) ;
return tok_notequal ;
} else
return ' ! ' ;
2022-02-14 12:48:59 +03:00
}
if ( LastChar = = ' < ' ) {
LastChar = getLastChar ( ) ;
2022-08-23 13:06:01 +02:00
if ( LastChar = = ' = ' ) {
LastChar = getLastChar ( ) ;
return tok_lesseq ;
} else
return ' < ' ;
2022-02-14 12:48:59 +03:00
}
if ( LastChar = = ' > ' ) {
LastChar = getLastChar ( ) ;
2022-08-23 13:06:01 +02:00
if ( LastChar = = ' = ' ) {
LastChar = getLastChar ( ) ;
return tok_greateq ;
} else
return ' > ' ;
2022-02-14 12:48:59 +03:00
}
2022-09-14 18:53:02 +02:00
2022-02-14 12:48:59 +03:00
// В противном случае просто возвращаем символ как значение ASCII
int ThisChar = LastChar ;
LastChar = getLastChar ( ) ;
return ThisChar ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
//===----------------------------------------------------------------------===//
// Parser (Парсер или Синтаксический Анализатор)
//===----------------------------------------------------------------------===//
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// CurTok/getNextToken - Предоставляет простой буфер токенов. CurTok - это текущий
/// токен, просматриваемый парсером. getNextToken получает следующий токен от
/// лексического анализатора и обновляет CurTok.
int IoTScenario : : getNextToken ( ) {
2022-02-14 12:48:59 +03:00
return CurTok = gettok ( ) ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// GetTokPrecedence - Возвращает приоритет текущего бинарного оператора.
int IoTScenario : : GetTokPrecedence ( ) {
2022-02-14 12:48:59 +03:00
if ( ! ( isascii ( CurTok ) | | BinopPrecedence . count ( CurTok ) ) )
2022-08-23 13:06:01 +02:00
return - 1 ;
2022-02-14 12:48:59 +03:00
// Удостоверимся, что это объявленный бинарный оператор.
int TokPrec = BinopPrecedence [ CurTok ] ;
if ( TokPrec < = 0 ) return - 1 ;
return TokPrec ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// Error* - Это небольшие вспомогательные функции для обработки ошибок.
ExprAST * IoTScenario : : Error ( const char * Str ) {
2022-09-05 23:24:57 +03:00
Serial . printf ( " Scenario error in line %d: %s \n " , curLine , Str ) ;
isIotScenException = true ;
2022-08-23 13:06:01 +02:00
return nullptr ;
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// identifierexpr
/// ::= identifier
/// ::= identifier '(' expression* ')'
2022-09-03 21:32:39 +03:00
ExprAST * IoTScenario : : ParseIdentifierExpr ( String * IDNames , bool callFromCondition ) {
2022-09-05 23:24:57 +03:00
if ( isIotScenException ) return nullptr ;
2022-02-14 12:48:59 +03:00
String IdName = IdentifierStr ;
String Cmd = " " ;
2022-08-23 13:06:01 +02:00
IoTItem * tmpItem = findIoTItem ( IdName ) ;
2022-02-14 12:48:59 +03:00
getNextToken ( ) ; // получаем идентификатор.
2022-08-23 13:06:01 +02:00
2022-02-14 12:48:59 +03:00
if ( CurTok = = ' . ' ) {
2022-08-23 13:06:01 +02:00
getNextToken ( ) ;
Cmd = IdentifierStr ;
getNextToken ( ) ;
2022-02-14 12:48:59 +03:00
}
2022-08-23 13:06:01 +02:00
if ( CurTok ! = ' ( ' ) { // Обычная переменная.
// if (tmpItem) return new VariableExprAST(IdName, tmpItem);
// else return new StringExprAST("id " + IdName + " not_found");
2022-02-26 10:50:40 +03:00
2022-08-23 13:06:01 +02:00
// создаем экземпляр переменной в любом случае, даж если не нашли (tmpItem = nulptr), т.к. переменная может придти из сети позже
return new VariableExprAST ( IdName , tmpItem ) ;
2022-02-14 12:48:59 +03:00
}
2022-08-23 13:06:01 +02:00
2022-02-14 12:48:59 +03:00
// Вызов функции.
getNextToken ( ) ; // получаем (
2022-08-23 13:06:01 +02:00
std : : vector < ExprAST * > Args ;
2022-02-14 12:48:59 +03:00
if ( CurTok ! = ' ) ' ) {
2022-08-23 13:06:01 +02:00
while ( 1 ) {
2022-09-03 21:32:39 +03:00
ExprAST * Arg = ParseExpression ( IDNames , callFromCondition ) ;
2022-08-29 00:45:55 +03:00
if ( ! Arg ) return nullptr ;
2022-08-23 13:06:01 +02:00
Args . push_back ( Arg ) ;
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
if ( CurTok = = ' ) ' ) break ;
2022-02-14 12:48:59 +03:00
2022-09-14 18:53:02 +02:00
if ( CurTok ! = ' , ' ) {
2022-08-23 13:06:01 +02:00
return Error ( " Expected ') ' or ' , ' in argument list " ) ;
2022-09-05 23:24:57 +03:00
}
2022-08-23 13:06:01 +02:00
getNextToken ( ) ;
}
2022-02-14 12:48:59 +03:00
}
2022-08-21 20:53:49 +03:00
// Получаем ';'.
2022-02-14 12:48:59 +03:00
getNextToken ( ) ;
2022-08-21 20:53:49 +03:00
2022-08-23 13:06:01 +02:00
if ( Cmd = = " " )
return new SysCallExprAST ( IdName , Args ) ; // создаем объект запуска системной функции
else
return new CallExprAST ( IdName , Cmd , Args , tmpItem ) ; // создаем объект запуска функции в любом случае даж если не нашли Item
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// numberexpr ::= number
ExprAST * IoTScenario : : ParseNumberExpr ( ) {
2022-09-05 23:24:57 +03:00
if ( isIotScenException ) return nullptr ;
2022-09-05 16:26:27 +03:00
ExprAST * Result = new NumberExprAST ( NumStr ) ;
2022-08-23 13:06:01 +02:00
getNextToken ( ) ; // получаем число
2022-02-14 12:48:59 +03:00
return Result ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// parenexpr ::= '(' expression ')'
2022-09-03 21:32:39 +03:00
ExprAST * IoTScenario : : ParseParenExpr ( String * IDNames , bool callFromCondition ) {
2022-02-14 12:48:59 +03:00
getNextToken ( ) ; // получаем (.
2022-09-03 21:32:39 +03:00
ExprAST * V = ParseExpression ( IDNames , callFromCondition ) ;
2022-08-29 00:45:55 +03:00
if ( ! V ) return nullptr ;
2022-08-23 13:06:01 +02:00
2022-02-14 12:48:59 +03:00
if ( CurTok ! = ' ) ' )
2022-08-23 13:06:01 +02:00
return Error ( " expected ') ' " ) ;
2022-09-14 18:53:02 +02:00
// getNextToken(); // получаем ).
2022-02-14 12:48:59 +03:00
return V ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// bracketsexpr ::= '{' expression '}'
2022-09-03 21:32:39 +03:00
ExprAST * IoTScenario : : ParseBracketsExpr ( String * IDNames , bool callFromCondition ) {
2022-09-05 23:24:57 +03:00
if ( isIotScenException ) return nullptr ;
2022-02-14 12:48:59 +03:00
getNextToken ( ) ; // получаем {.
2022-08-23 13:06:01 +02:00
std : : vector < ExprAST * > bracketsList ;
2022-09-14 18:53:02 +02:00
while ( CurTok ! = ' } ' ) {
ExprAST * Expr = ParseExpression ( IDNames , callFromCondition ) ;
if ( ! Expr ) return nullptr ;
bracketsList . push_back ( Expr ) ;
2022-08-23 13:06:01 +02:00
2022-09-14 18:53:02 +02:00
// if (CurTok == '}') break;
2022-09-03 21:32:39 +03:00
2022-09-14 18:53:02 +02:00
// Serial.printf("ParseBracketsExpr CurTok = %d \n", CurTok);
2022-09-03 21:32:39 +03:00
2022-09-14 18:53:02 +02:00
// if (CurTok != ';')
// return Error("Expected ';' in operation list");
// int ttok = getNextToken();
if ( CurTok = = tok_eof ) {
return Error ( " Expected '}' " ) ;
2022-08-23 13:06:01 +02:00
}
2022-09-14 18:53:02 +02:00
}
2022-08-23 13:06:01 +02:00
2022-09-03 21:32:39 +03:00
getNextToken ( ) ; // получаем }.
2022-02-14 12:48:59 +03:00
return new BracketsExprAST ( bracketsList ) ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// quotesexpr ::= '"' expression '"'
ExprAST * IoTScenario : : ParseQuotesExpr ( ) {
2022-09-05 23:24:57 +03:00
if ( isIotScenException ) return nullptr ;
2022-02-14 12:48:59 +03:00
String StringCont = IdentifierStr ;
ExprAST * Result = new StringExprAST ( StringCont ) ;
2022-08-23 13:06:01 +02:00
getNextToken ( ) ; // получаем число
2022-02-14 12:48:59 +03:00
return Result ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// ifexpr ::= 'if' expression 'then' expression 'else' expression
ExprAST * IoTScenario : : ParseIfExpr ( String * IDNames ) {
2022-09-05 23:24:57 +03:00
if ( isIotScenException ) return nullptr ;
2022-02-14 12:48:59 +03:00
getNextToken ( ) ; // Получаем if.
2022-08-23 13:06:01 +02:00
2022-02-14 12:48:59 +03:00
// условие.
2022-09-03 21:32:39 +03:00
ExprAST * Cond = ParseExpression ( IDNames , true ) ;
2022-08-29 00:45:55 +03:00
if ( ! Cond ) return nullptr ;
2022-08-23 13:06:01 +02:00
2022-02-14 12:48:59 +03:00
if ( CurTok ! = tok_then )
2022-08-23 13:06:01 +02:00
return Error ( " expected then " ) ;
2022-02-14 12:48:59 +03:00
getNextToken ( ) ; // Получаем then
2022-08-23 13:06:01 +02:00
2022-09-03 21:32:39 +03:00
ExprAST * Then = ParseExpression ( IDNames , false ) ;
2022-08-29 00:45:55 +03:00
if ( ! Then ) return nullptr ;
2022-08-23 13:06:01 +02:00
// if (CurTok != tok_else)
// return Error("expected else");
2022-02-14 12:48:59 +03:00
ExprAST * Else = nullptr ;
if ( CurTok = = tok_else ) {
2022-08-23 13:06:01 +02:00
getNextToken ( ) ;
2022-09-03 21:32:39 +03:00
Else = ParseExpression ( IDNames , false ) ;
if ( ! Else ) return nullptr ;
2022-02-14 12:48:59 +03:00
}
2022-03-03 22:58:39 +03:00
return new IfExprAST ( Cond , Then , Else , IDNames ) ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-23 13:06:01 +02:00
/// primary
/// ::= identifierexpr
/// ::= numberexpr
/// ::= parenexpr
2022-09-03 21:32:39 +03:00
ExprAST * IoTScenario : : ParsePrimary ( String * IDNames , bool callFromCondition ) {
2022-02-14 12:48:59 +03:00
switch ( CurTok ) {
2022-08-23 13:06:01 +02:00
default :
2022-08-29 16:01:25 +03:00
Serial . println ( CurTok ) ;
2022-08-23 13:06:01 +02:00
return Error ( " unknown token when expecting an expression " ) ;
case tok_identifier : {
2022-09-03 21:32:39 +03:00
if ( callFromCondition & & IDNames ) {
2022-08-23 13:06:01 +02:00
String tmpstr = * IDNames ;
* IDNames = tmpstr + " " + IdentifierStr + " " ;
}
2022-09-03 21:32:39 +03:00
return ParseIdentifierExpr ( IDNames , callFromCondition ) ;
2022-08-23 13:06:01 +02:00
}
case tok_number :
return ParseNumberExpr ( ) ;
case ' ( ' :
2022-09-03 21:32:39 +03:00
return ParseParenExpr ( IDNames , callFromCondition ) ;
2022-08-23 13:06:01 +02:00
case ' { ' :
2022-09-03 21:32:39 +03:00
return ParseBracketsExpr ( IDNames , callFromCondition ) ;
2022-08-23 13:06:01 +02:00
case tok_string :
return ParseQuotesExpr ( ) ;
case tok_if :
return ParseIfExpr ( IDNames ) ;
}
}
/// binoprhs
/// ::= ('+' primary)*
2022-09-03 21:32:39 +03:00
ExprAST * IoTScenario : : ParseBinOpRHS ( int ExprPrec , ExprAST * LHS , String * IDNames , bool callFromCondition ) {
2022-09-05 23:24:57 +03:00
if ( isIotScenException ) return nullptr ;
2022-02-14 12:48:59 +03:00
// Если это бинарный оператор, получаем е г о приоритет
while ( 1 ) {
2022-08-23 13:06:01 +02:00
int TokPrec = GetTokPrecedence ( ) ;
// Если этот бинарный оператор связывает выражения по крайней мере так же,
// как текущий, то используем е г о
if ( TokPrec < ExprPrec )
return LHS ;
// Отлично, мы знаем, что это бинарный оператор.
int BinOp = CurTok ;
getNextToken ( ) ; // eat binop
// Разобрать первичное выражение после бинарного оператора
2022-09-03 21:32:39 +03:00
ExprAST * RHS = ParsePrimary ( IDNames , callFromCondition ) ;
2022-08-29 00:45:55 +03:00
if ( ! RHS ) return nullptr ;
2022-08-23 13:06:01 +02:00
// Если BinOp связан с RHS меньшим приоритетом, чем оператор после RHS,
// то берём часть вместе с RHS как LHS.
int NextPrec = GetTokPrecedence ( ) ;
if ( TokPrec < NextPrec ) {
2022-09-03 21:32:39 +03:00
RHS = ParseBinOpRHS ( TokPrec + 1 , RHS , IDNames , callFromCondition ) ;
2022-08-29 00:45:55 +03:00
if ( RHS = = nullptr ) return nullptr ;
2022-08-23 13:06:01 +02:00
}
// Собираем LHS/RHS.
LHS = new BinaryExprAST ( BinOp , LHS , RHS ) ;
}
}
/// expression
/// ::= primary binoprhs
///
2022-09-03 21:32:39 +03:00
ExprAST * IoTScenario : : ParseExpression ( String * IDNames , bool callFromCondition ) {
ExprAST * LHS = ParsePrimary ( IDNames , callFromCondition ) ;
2022-08-29 00:45:55 +03:00
if ( ! LHS ) return nullptr ;
2022-09-03 21:32:39 +03:00
return ParseBinOpRHS ( 0 , LHS , IDNames , callFromCondition ) ;
2022-08-23 13:06:01 +02:00
}
2022-02-14 12:48:59 +03:00
2022-08-30 14:00:22 +03:00
void IoTScenario : : loadScenario ( String fileName ) { // подготавливаем контекст для чтения и интерпретации файла
2022-09-05 23:24:57 +03:00
isIotScenException = false ;
2022-09-04 19:16:08 +03:00
if ( mode = = 0 ) {
if ( file ) file . close ( ) ;
file = FileFS . open ( fileName . c_str ( ) , " r " ) ;
if ( ! file ) {
Error ( " Open file scenario error " ) ;
return ;
}
} else if ( mode = = 1 ) {
file = FileFS . open ( fileName . c_str ( ) , " r " ) ;
if ( ! file ) {
Error ( " Open file scenario error " ) ;
return ;
}
2022-09-04 11:20:33 +03:00
strFromFile = file . readString ( ) ;
2022-09-29 22:48:33 +02:00
// strFromFile.replace("{\"scen\":\"", "");
// strFromFile.replace("\\n", "\n");
// strFromFile.replace("\\\"", "\"");
// strFromFile.replace(";", " ");
// strFromFile.replace("\\t", " ");
// strFromFile.remove(strFromFile.length() - 2, 2);
2022-09-04 19:16:08 +03:00
Serial . printf ( " strFromFile: %s, %s \n " , strFromFile . c_str ( ) , fileName . c_str ( ) ) ;
2022-09-04 11:20:33 +03:00
file . close ( ) ;
2022-09-14 18:53:02 +02:00
}
2022-09-04 11:20:33 +03:00
}
2022-11-04 16:47:46 +03:00
void IoTScenario : : exec ( const String & eventIdName ) { // посимвольно считываем и сразу интерпретируем сценарий в дерево AST
2022-09-04 11:20:33 +03:00
if ( mode = = 0 & & ! file ) return ;
2022-08-30 14:00:22 +03:00
LastChar = 0 ;
CurTok = 0 ;
2022-08-30 23:31:38 +03:00
curLine = 1 ;
2022-09-04 19:16:08 +03:00
charCount = 0 ;
2022-08-30 14:00:22 +03:00
2022-09-14 18:53:02 +02:00
if ( mode = = 0 ) file . seek ( 0 ) ;
2022-09-04 11:20:33 +03:00
if ( mode < 2 ) {
while ( CurTok ! = EOF ) {
2022-09-14 18:53:02 +02:00
switch ( CurTok ) {
2022-09-04 11:20:33 +03:00
case tok_if : {
IDNames = " " ; // сбрасываем накопитель встречающихся идентификаторов в условии
ExprAST * tmpAST = ParseIfExpr ( & IDNames ) ;
2022-09-05 23:24:57 +03:00
if ( tmpAST ) {
if ( tmpAST - > hasEventIdName ( eventIdName ) ) {
tmpAST - > exec ( ) ;
}
delete tmpAST ;
2022-09-14 18:53:02 +02:00
} else
getNextToken ( ) ;
break ;
}
default :
getNextToken ( ) ;
break ;
2022-09-04 11:20:33 +03:00
}
2022-02-14 12:48:59 +03:00
}
2022-08-23 13:06:01 +02:00
}
}
IoTScenario : : IoTScenario ( ) {
2022-02-14 12:48:59 +03:00
// Задаём стандартные бинарные операторы.
// 1 - наименьший приоритет.
2022-10-27 10:50:09 +03:00
BinopPrecedence [ tok_silentset ] = 1 ;
BinopPrecedence [ ' = ' ] = 2 ;
2022-08-23 13:06:01 +02:00
BinopPrecedence [ ' | ' ] = 5 ;
BinopPrecedence [ ' & ' ] = 6 ;
BinopPrecedence [ tok_equal ] = 10 ; // ==
2022-02-25 21:51:20 +03:00
BinopPrecedence [ tok_notequal ] = 11 ; // !=
2022-08-23 13:06:01 +02:00
BinopPrecedence [ tok_lesseq ] = 15 ; // <=
BinopPrecedence [ tok_greateq ] = 16 ; // >=
2022-02-25 21:51:20 +03:00
BinopPrecedence [ ' < ' ] = 20 ;
BinopPrecedence [ ' > ' ] = 21 ;
BinopPrecedence [ ' + ' ] = 25 ;
BinopPrecedence [ ' - ' ] = 26 ;
2022-08-23 13:06:01 +02:00
BinopPrecedence [ ' / ' ] = 27 ;
2022-02-25 21:51:20 +03:00
BinopPrecedence [ ' * ' ] = 28 ; // highest.
2022-08-23 13:06:01 +02:00
}
2022-08-30 14:00:22 +03:00
IoTScenario : : ~ IoTScenario ( ) {
if ( file ) file . close ( ) ;
}