mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-11 21:03:05 +08:00
Merge pull request #625 from RaiKoHoff/Dev_0823
More TinyExpr integration
This commit is contained in:
commit
21208a3ed2
259
src/Notepad3.c
259
src/Notepad3.c
@ -5983,6 +5983,154 @@ void OpenHotSpotURL(DocPos position, bool bForceBrowser)
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _HandleAutoCloseTags()
|
||||
//
|
||||
static void __fastcall _HandleAutoIndent(int const charAdded) {
|
||||
// in CRLF mode handle LF only...
|
||||
if (((SC_EOL_CRLF == g_iEOLMode) && (charAdded != '\r')) || (SC_EOL_CRLF != g_iEOLMode))
|
||||
{
|
||||
DocPos const iCurPos = SciCall_GetCurrentPos();
|
||||
DocLn const iCurLine = SciCall_LineFromPosition(iCurPos);
|
||||
|
||||
// Move bookmark along with line if inserting lines (pressing return within indent area of line) because Scintilla does not do this for us
|
||||
if (iCurLine > 0)
|
||||
{
|
||||
//DocPos const iPrevLineLength = Sci_GetNetLineLength(iCurLine - 1);
|
||||
if (SciCall_GetLineEndPosition(iCurLine - 1) == SciCall_GetLineIndentPosition(iCurLine - 1))
|
||||
{
|
||||
int const bitmask = SciCall_MarkerGet(iCurLine - 1);
|
||||
if (bitmask & (1 << MARKER_NP3_BOOKMARK))
|
||||
{
|
||||
SciCall_MarkerDelete(iCurLine - 1, MARKER_NP3_BOOKMARK);
|
||||
SciCall_MarkerAdd(iCurLine, MARKER_NP3_BOOKMARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iCurLine > 0/* && iLineLength <= 2*/)
|
||||
{
|
||||
DocPos const iPrevLineLength = SciCall_LineLength(iCurLine - 1);
|
||||
char* pLineBuf = NULL;
|
||||
bool bAllocLnBuf = false;
|
||||
if (iPrevLineLength < TEMPLINE_BUFFER) {
|
||||
pLineBuf = g_pTempLineBufferMain;
|
||||
}
|
||||
else {
|
||||
bAllocLnBuf = true;
|
||||
pLineBuf = AllocMem(iPrevLineLength + 1, HEAP_ZERO_MEMORY);
|
||||
}
|
||||
if (pLineBuf)
|
||||
{
|
||||
SciCall_GetLine(iCurLine - 1, pLineBuf);
|
||||
*(pLineBuf + iPrevLineLength) = '\0';
|
||||
for (char* pPos = pLineBuf; *pPos; pPos++) {
|
||||
if (*pPos != ' ' && *pPos != '\t')
|
||||
*pPos = '\0';
|
||||
}
|
||||
if (*pLineBuf) {
|
||||
_BEGIN_UNDO_ACTION_;
|
||||
SciCall_AddText(lstrlenA(pLineBuf), pLineBuf);
|
||||
_END_UNDO_ACTION_;
|
||||
}
|
||||
if (bAllocLnBuf) { FreeMem(pLineBuf); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _HandleAutoCloseTags()
|
||||
//
|
||||
static void __fastcall _HandleAutoCloseTags()
|
||||
{
|
||||
//int lexerID = (int)SendMessage(g_hwndEdit,SCI_GETLEXER,0,0);
|
||||
//if (lexerID == SCLEX_HTML || lexerID == SCLEX_XML)
|
||||
{
|
||||
DocPos const iCurPos = SciCall_GetCurrentPos();
|
||||
DocPos const iHelper = iCurPos - (DocPos)(COUNTOF(g_pTempLineBufferMain) - 1);
|
||||
DocPos const iStartPos = max(0, iHelper);
|
||||
DocPos const iSize = iCurPos - iStartPos;
|
||||
|
||||
if (iSize >= 3)
|
||||
{
|
||||
const char* pBegin = SciCall_GetRangePointer(iStartPos, iSize);
|
||||
|
||||
if (pBegin[iSize - 2] != '/') {
|
||||
|
||||
const char* pCur = &pBegin[iSize - 2];
|
||||
|
||||
while (pCur > pBegin && *pCur != '<' && *pCur != '>') { --pCur; }
|
||||
|
||||
int cchIns = 2;
|
||||
StringCchCopyA(g_pTempLineBufferMain, FNDRPL_BUFFER, "</");
|
||||
if (*pCur == '<') {
|
||||
pCur++;
|
||||
while (StrChrA(":_-.", *pCur) || IsCharAlphaNumericA(*pCur)) {
|
||||
g_pTempLineBufferMain[cchIns++] = *pCur;
|
||||
pCur++;
|
||||
}
|
||||
}
|
||||
g_pTempLineBufferMain[cchIns++] = '>';
|
||||
g_pTempLineBufferMain[cchIns] = '\0';
|
||||
|
||||
if (cchIns > 3 &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</base>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</bgsound>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</br>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</embed>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</hr>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</img>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</input>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</link>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</meta>", -1))
|
||||
{
|
||||
_BEGIN_UNDO_ACTION_;
|
||||
SciCall_ReplaceSel(g_pTempLineBufferMain);
|
||||
SciCall_SetSel(iCurPos, iCurPos);
|
||||
_END_UNDO_ACTION_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// _HandleTinyExpr() - called on '?' insert
|
||||
//
|
||||
static void __fastcall _HandleTinyExpr()
|
||||
{
|
||||
DocPos const iCurPos = SciCall_GetCurrentPos();
|
||||
DocPos const iPosBefore = SciCall_PositionBefore(iCurPos);
|
||||
char const chBefore = SciCall_GetCharAt(iPosBefore - 1);
|
||||
if (chBefore == '=') // got "=?" evaluate expression trigger
|
||||
{
|
||||
DocPos const iLnCaretPos = SciCall_GetCurLine(COUNTOF(g_pTempLineBufferMain), g_pTempLineBufferMain);
|
||||
g_pTempLineBufferMain[(iLnCaretPos > 1) ? (iLnCaretPos-2) : 0] = '\0'; // breakbefore "=?"
|
||||
|
||||
int iExprErr = 1;
|
||||
const char* pBegin = &g_pTempLineBufferMain[0];
|
||||
double dExprEval = 0.0;
|
||||
|
||||
while (*pBegin && iExprErr) {
|
||||
dExprEval = te_interp(pBegin++, &iExprErr);
|
||||
}
|
||||
if (*pBegin && !iExprErr) {
|
||||
char chExpr[64] = { '\0' };
|
||||
StringCchPrintfA(chExpr, COUNTOF(chExpr), "%.6G", dExprEval);
|
||||
SciCall_SetSel(iPosBefore, iCurPos);
|
||||
SciCall_ReplaceSel(chExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// MsgNotify() - Handles WM_NOTIFY
|
||||
@ -6158,112 +6306,17 @@ LRESULT MsgNotify(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
case SCN_CHARADDED:
|
||||
{
|
||||
// Auto indent
|
||||
if (bAutoIndent && (scn->ch == '\x0D' || scn->ch == '\x0A'))
|
||||
if (bAutoIndent && (scn->ch == '\r' || scn->ch == '\n'))
|
||||
{
|
||||
// in CRLF mode handle LF only...
|
||||
if ((SC_EOL_CRLF == g_iEOLMode && scn->ch != '\x0A') || SC_EOL_CRLF != g_iEOLMode)
|
||||
{
|
||||
const DocPos iCurPos = SciCall_GetCurrentPos();
|
||||
const DocLn iCurLine = SciCall_LineFromPosition(iCurPos);
|
||||
|
||||
// Move bookmark along with line if inserting lines (pressing return within indent area of line) because Scintilla does not do this for us
|
||||
if (iCurLine > 0)
|
||||
{
|
||||
//const DocPos iPrevLineLength = Sci_GetNetLineLength(iCurLine - 1);
|
||||
if (SciCall_GetLineEndPosition(iCurLine - 1) == SciCall_GetLineIndentPosition(iCurLine - 1))
|
||||
{
|
||||
int bitmask = SciCall_MarkerGet(iCurLine - 1);
|
||||
if (bitmask & (1 << MARKER_NP3_BOOKMARK))
|
||||
{
|
||||
SciCall_MarkerDelete(iCurLine - 1, MARKER_NP3_BOOKMARK);
|
||||
SciCall_MarkerAdd(iCurLine, MARKER_NP3_BOOKMARK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iCurLine > 0/* && iLineLength <= 2*/)
|
||||
{
|
||||
const DocPos iPrevLineLength = SciCall_LineLength(iCurLine - 1);
|
||||
char* pLineBuf = NULL;
|
||||
bool bAllocLnBuf = false;
|
||||
if (iPrevLineLength < TEMPLINE_BUFFER) {
|
||||
pLineBuf = g_pTempLineBufferMain;
|
||||
}
|
||||
else {
|
||||
bAllocLnBuf = true;
|
||||
pLineBuf = AllocMem(iPrevLineLength + 1, HEAP_ZERO_MEMORY);
|
||||
}
|
||||
if (pLineBuf)
|
||||
{
|
||||
SciCall_GetLine(iCurLine - 1, pLineBuf);
|
||||
*(pLineBuf + iPrevLineLength) = '\0';
|
||||
for (char* pPos = pLineBuf; *pPos; pPos++) {
|
||||
if (*pPos != ' ' && *pPos != '\t')
|
||||
*pPos = '\0';
|
||||
}
|
||||
if (*pLineBuf) {
|
||||
_BEGIN_UNDO_ACTION_;
|
||||
SciCall_AddText(lstrlenA(pLineBuf), pLineBuf);
|
||||
_END_UNDO_ACTION_;
|
||||
}
|
||||
if (bAllocLnBuf) { FreeMem(pLineBuf); }
|
||||
}
|
||||
}
|
||||
}
|
||||
_HandleAutoIndent(scn->ch);
|
||||
}
|
||||
// Auto close tags
|
||||
else if (bAutoCloseTags && scn->ch == '>')
|
||||
{
|
||||
//int lexerID = (int)SendMessage(g_hwndEdit,SCI_GETLEXER,0,0);
|
||||
//if (lexerID == SCLEX_HTML || lexerID == SCLEX_XML)
|
||||
{
|
||||
const DocPos iCurPos = SciCall_GetCurrentPos();
|
||||
const DocPos iHelper = iCurPos - (DocPos)(COUNTOF(g_pTempLineBufferMain) - 1);
|
||||
const DocPos iStartPos = max(0, iHelper);
|
||||
const DocPos iSize = iCurPos - iStartPos;
|
||||
|
||||
if (iSize >= 3)
|
||||
{
|
||||
const char* pBegin = SciCall_GetRangePointer(iStartPos, iSize);
|
||||
|
||||
if (pBegin[iSize - 2] != '/') {
|
||||
|
||||
const char* pCur = &pBegin[iSize - 2];
|
||||
|
||||
while (pCur > pBegin && *pCur != '<' && *pCur != '>')
|
||||
--pCur;
|
||||
|
||||
int cchIns = 2;
|
||||
StringCchCopyA(g_pTempLineBufferMain, FNDRPL_BUFFER, "</");
|
||||
if (*pCur == '<') {
|
||||
pCur++;
|
||||
while (StrChrA(":_-.", *pCur) || IsCharAlphaNumericA(*pCur)) {
|
||||
g_pTempLineBufferMain[cchIns++] = *pCur;
|
||||
pCur++;
|
||||
}
|
||||
}
|
||||
g_pTempLineBufferMain[cchIns++] = '>';
|
||||
g_pTempLineBufferMain[cchIns] = '\0';
|
||||
|
||||
if (cchIns > 3 &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</base>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</bgsound>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</br>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</embed>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</hr>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</img>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</input>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</link>", -1) &&
|
||||
StringCchCompareINA(g_pTempLineBufferMain, COUNTOF(g_pTempLineBufferMain), "</meta>", -1))
|
||||
{
|
||||
_BEGIN_UNDO_ACTION_;
|
||||
SciCall_ReplaceSel(g_pTempLineBufferMain);
|
||||
SciCall_SetSel(iCurPos, iCurPos);
|
||||
_END_UNDO_ACTION_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_HandleAutoCloseTags();
|
||||
}
|
||||
else if (scn->ch == '?') {
|
||||
_HandleTinyExpr();
|
||||
}
|
||||
else if (g_bAutoCompleteWords && !SendMessage(g_hwndEdit, SCI_AUTOCACTIVE, 0, 0)) {
|
||||
EditCompleteWord(g_hwndEdit, false);
|
||||
@ -8312,6 +8365,7 @@ static void __fastcall _UpdateStatusbarDelayed(bool bForceRedraw)
|
||||
// try calculate expression of selection
|
||||
static WCHAR tchExpression[32] = { L'\0' };
|
||||
static int s_iExprError = -3;
|
||||
static char chExpression[1024] = { '\0' };
|
||||
|
||||
if (g_iStatusbarVisible[STATUS_TINYEXPR])
|
||||
{
|
||||
@ -8322,13 +8376,12 @@ static void __fastcall _UpdateStatusbarDelayed(bool bForceRedraw)
|
||||
|
||||
if (bIsSelCountable)
|
||||
{
|
||||
char chExpression[1024] = { '\0' };
|
||||
|
||||
if (SciCall_GetSelText(NULL) < COUNTOF(chExpression))
|
||||
{
|
||||
SciCall_GetSelText(chExpression);
|
||||
//StrDelChrA(chExpression, " \r\n\t\v");
|
||||
StrDelChrA(chExpression, "\r\n");
|
||||
|
||||
g_dExpression = te_interp(chExpression, &g_iExprError);
|
||||
|
||||
if (!g_iExprError) {
|
||||
|
||||
@ -672,6 +672,100 @@ void test_combinatorics() {
|
||||
}
|
||||
|
||||
|
||||
void test_logic() {
|
||||
test_case cases[] = {
|
||||
{"1 && 1", 1},
|
||||
{"1 && 0", 0},
|
||||
{"0 && 1", 0},
|
||||
{"0 && 0", 0},
|
||||
{"1 || 1", 1},
|
||||
{"1 || 0", 1},
|
||||
{"0 || 1", 1},
|
||||
{"0 || 0", 0},
|
||||
{"!0", 1},
|
||||
{"!1", 0},
|
||||
{"!2", 0},
|
||||
|
||||
{"!-2", 0},
|
||||
{"-!2", 0},
|
||||
{"!!0", 0},
|
||||
{"!!1", 1},
|
||||
{"!!2", 1},
|
||||
{"!!-2", 1},
|
||||
{"!-!2", 1},
|
||||
{"-!!2", -1},
|
||||
{"--!!2", 1},
|
||||
|
||||
{"1 < 2", 1},
|
||||
{"2 < 2", 0},
|
||||
{"2 <= 2", 1},
|
||||
{"2 > 1", 1},
|
||||
{"2 > 2", 0},
|
||||
{"2 >= 2", 1},
|
||||
{"2 > -2", 1},
|
||||
{"-2 < 2", 1},
|
||||
|
||||
{"0 == 0", 1},
|
||||
{"0 != 0", 0},
|
||||
{"2 == 2", 1},
|
||||
{"2 != 2", 0},
|
||||
{"2 == 3", 0},
|
||||
{"2 != 3", 1},
|
||||
{"2 == 2.0001", 0},
|
||||
{"2 != 2.0001", 1},
|
||||
|
||||
{"1 < 2 && 2 < 3", 1},
|
||||
{"1 < 2 && 3 < 2", 0},
|
||||
{"2 < 1 && 2 < 3", 0},
|
||||
{"2 < 1 && 3 < 2", 0},
|
||||
{"1 < 2 || 2 < 3", 1},
|
||||
{"1 < 2 || 3 < 2", 1},
|
||||
{"2 < 1 || 2 < 3", 1},
|
||||
{"2 < 1 || 3 < 2", 0},
|
||||
|
||||
{"1 < 1+1", 1},
|
||||
{"1 < 1*2", 1},
|
||||
{"1 < 2/2", 0},
|
||||
{"1 < 2^2", 1},
|
||||
|
||||
{"5+5 < 4+10", 1},
|
||||
{"5+(5 < 4)+10", 15},
|
||||
{"5+(5 < 4+10)", 6},
|
||||
{"(5+5 < 4)+10", 10},
|
||||
{"5+!(5 < 4)+10", 16},
|
||||
{"5+!(5 < 4+10)", 5},
|
||||
{"!(5+5 < 4)+10", 11},
|
||||
|
||||
#ifdef TE_POW_FROM_RIGHT
|
||||
{"!0^2", 1},
|
||||
{"!0^-1", 0},
|
||||
{"-!0^2", -1},
|
||||
#else
|
||||
{"!0^2", 1},
|
||||
{"!0^-1", 1},
|
||||
{"-!0^2", 1},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
int i;
|
||||
for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) {
|
||||
const char *expr = cases[i].expr;
|
||||
const double answer = cases[i].answer;
|
||||
|
||||
int err;
|
||||
const double ev = te_interp(expr, &err);
|
||||
lok(!err);
|
||||
lfequal(ev, answer);
|
||||
|
||||
if (err) {
|
||||
printf("FAILED: %s (%d)\n", expr, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
lrun("Results", test_results);
|
||||
@ -685,6 +779,7 @@ int main(int argc, char *argv[])
|
||||
lrun("Optimize", test_optimize);
|
||||
lrun("Pow", test_pow);
|
||||
lrun("Combinatorics", test_combinatorics);
|
||||
lrun("Logic", test_logic);
|
||||
lresults();
|
||||
|
||||
return lfails != 0;
|
||||
|
||||
@ -228,6 +228,19 @@ static double divide(double a, double b) {return a / b;}
|
||||
static double negate(double a) {return -a;}
|
||||
static double comma(double a, double b) {(void)a; return b;}
|
||||
|
||||
static double greater(double a, double b) {return a > b;}
|
||||
static double greater_eq(double a, double b) {return a >= b;}
|
||||
static double lower(double a, double b) {return a < b;}
|
||||
static double lower_eq(double a, double b) {return a <= b;}
|
||||
static double equal(double a, double b) {return a == b;}
|
||||
static double not_equal(double a, double b) {return a != b;}
|
||||
static double logical_and(double a, double b) {return a != 0.0 && b != 0.0;}
|
||||
static double logical_or(double a, double b) {return a != 0.0 || b != 0.0;}
|
||||
static double logical_not(double a) {return a == 0.0;}
|
||||
static double logical_notnot(double a) {return a != 0.0;}
|
||||
static double negate_logical_not(double a) {return -(a == 0.0);}
|
||||
static double negate_logical_notnot(double a) {return -(a != 0.0);}
|
||||
|
||||
|
||||
void next_token(state *s) {
|
||||
s->type = TOK_NULL;
|
||||
@ -284,6 +297,51 @@ void next_token(state *s) {
|
||||
case '/': s->type = TOK_INFIX; s->function = divide; break;
|
||||
case '^': s->type = TOK_INFIX; s->function = pow; break;
|
||||
case '%': s->type = TOK_INFIX; s->function = fmod; break;
|
||||
case '!':
|
||||
if (s->next++[0] == '=') {
|
||||
s->type = TOK_INFIX; s->function = not_equal;
|
||||
} else {
|
||||
s->next--;
|
||||
s->type = TOK_INFIX; s->function = logical_not;
|
||||
}
|
||||
break;
|
||||
case '=':
|
||||
if (s->next++[0] == '=') {
|
||||
s->type = TOK_INFIX; s->function = equal;
|
||||
} else {
|
||||
s->type = TOK_ERROR;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
if (s->next++[0] == '=') {
|
||||
s->type = TOK_INFIX; s->function = lower_eq;
|
||||
} else {
|
||||
s->next--;
|
||||
s->type = TOK_INFIX; s->function = lower;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if (s->next++[0] == '=') {
|
||||
s->type = TOK_INFIX; s->function = greater_eq;
|
||||
} else {
|
||||
s->next--;
|
||||
s->type = TOK_INFIX; s->function = greater;
|
||||
}
|
||||
break;
|
||||
case '&':
|
||||
if (s->next++[0] == '&') {
|
||||
s->type = TOK_INFIX; s->function = logical_and;
|
||||
} else {
|
||||
s->type = TOK_ERROR;
|
||||
}
|
||||
break;
|
||||
case '|':
|
||||
if (s->next++[0] == '|') {
|
||||
s->type = TOK_INFIX; s->function = logical_or;
|
||||
} else {
|
||||
s->type = TOK_ERROR;
|
||||
}
|
||||
break;
|
||||
case '(': s->type = TOK_OPEN; break;
|
||||
case ')': s->type = TOK_CLOSE; break;
|
||||
case ',': s->type = TOK_SEP; break;
|
||||
@ -396,20 +454,48 @@ static te_expr *base(state *s) {
|
||||
|
||||
|
||||
static te_expr *power(state *s) {
|
||||
/* <power> = {("-" | "+")} <base> */
|
||||
/* <power> = {("-" | "+" | "!")} <base> */
|
||||
int sign = 1;
|
||||
while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) {
|
||||
if (s->function == sub) sign = -sign;
|
||||
next_token(s);
|
||||
}
|
||||
|
||||
int logical = 0;
|
||||
while (s->type == TOK_INFIX && (s->function == add || s->function == sub || s->function == logical_not)) {
|
||||
if (s->function == logical_not) {
|
||||
if (logical == 0) {
|
||||
logical = -1;
|
||||
} else {
|
||||
logical = -logical;
|
||||
}
|
||||
}
|
||||
next_token(s);
|
||||
}
|
||||
|
||||
te_expr *ret;
|
||||
|
||||
if (sign == 1) {
|
||||
ret = base(s);
|
||||
if (logical == 0) {
|
||||
ret = base(s);
|
||||
} else if (logical == -1) {
|
||||
ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
|
||||
ret->function = logical_not;
|
||||
} else {
|
||||
ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
|
||||
ret->function = logical_notnot;
|
||||
}
|
||||
} else {
|
||||
ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
|
||||
ret->function = negate;
|
||||
if (logical == 0) {
|
||||
ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
|
||||
ret->function = negate;
|
||||
} else if (logical == -1) {
|
||||
ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
|
||||
ret->function = negate_logical_not;
|
||||
} else {
|
||||
ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));
|
||||
ret->function = negate_logical_notnot;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -420,14 +506,16 @@ static te_expr *factor(state *s) {
|
||||
/* <factor> = <power> {"^" <power>} */
|
||||
te_expr *ret = power(s);
|
||||
|
||||
int neg = 0;
|
||||
const void *left_function = NULL;
|
||||
te_expr *insertion = 0;
|
||||
|
||||
if (ret->type == (TE_FUNCTION1 | TE_FLAG_PURE) && ret->function == negate) {
|
||||
if (ret->type == (TE_FUNCTION1 | TE_FLAG_PURE) &&
|
||||
(ret->function == negate || ret->function == logical_not || ret->function == logical_notnot ||
|
||||
ret->function == negate_logical_not || ret->function == negate_logical_notnot)) {
|
||||
left_function = ret->function;
|
||||
te_expr *se = ret->parameters[0];
|
||||
free(ret);
|
||||
ret = se;
|
||||
neg = 1;
|
||||
}
|
||||
|
||||
while (s->type == TOK_INFIX && (s->function == pow)) {
|
||||
@ -447,9 +535,9 @@ static te_expr *factor(state *s) {
|
||||
}
|
||||
}
|
||||
|
||||
if (neg) {
|
||||
if (left_function) {
|
||||
ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, ret);
|
||||
ret->function = negate;
|
||||
ret->function = left_function;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -487,7 +575,7 @@ static te_expr *term(state *s) {
|
||||
}
|
||||
|
||||
|
||||
static te_expr *expr(state *s) {
|
||||
static te_expr *sum_expr(state *s) {
|
||||
/* <expr> = <term> {("+" | "-") <term>} */
|
||||
te_expr *ret = term(s);
|
||||
|
||||
@ -502,6 +590,37 @@ static te_expr *expr(state *s) {
|
||||
}
|
||||
|
||||
|
||||
static te_expr *test_expr(state *s) {
|
||||
/* <expr> = <sum_expr> {(">" | ">=" | "<" | "<=" | "==" | "!=") <sum_expr>} */
|
||||
te_expr *ret = sum_expr(s);
|
||||
|
||||
while (s->type == TOK_INFIX && (s->function == greater || s->function == greater_eq ||
|
||||
s->function == lower || s->function == lower_eq || s->function == equal || s->function == not_equal)) {
|
||||
te_fun2 t = s->function;
|
||||
next_token(s);
|
||||
ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, sum_expr(s));
|
||||
ret->function = t;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static te_expr *expr(state *s) {
|
||||
/* <expr> = <test_expr> {("&&" | "||") <test_expr>} */
|
||||
te_expr *ret = test_expr(s);
|
||||
|
||||
while (s->type == TOK_INFIX && (s->function == logical_and || s->function == logical_or)) {
|
||||
te_fun2 t = s->function;
|
||||
next_token(s);
|
||||
ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, test_expr(s));
|
||||
ret->function = t;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static te_expr *list(state *s) {
|
||||
/* <list> = <expr> {"," <expr>} */
|
||||
te_expr *ret = expr(s);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user