-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparser.y
197 lines (164 loc) · 6.65 KB
/
parser.y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
%{
/*
This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
Copyright (C) 2003-2009 Toby Thain, [email protected]
Copyright (C) 2018-2024 Daniel Marschall, ViaThinkSoft
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#ifdef WIN_ENV
#include <windows.h> // for TCHAR
#else
#ifdef UNICODE
#define TCHAR wchar_t
#else
#define TCHAR char
#endif
#endif
#ifndef false
#define false 0
#define true 1
#endif
#include "node.h"
#include "y.tab.h"
//#ifdef MAC_ENV
int yyparse(void);
int yylex(void); // hack. correct prototype is buried in lex output
//#endif
// DM 29.04.2022
#define YY_(Msg) ((TCHAR*)TEXT(Msg))
void yyerror(TCHAR*);
int pushflag(int x);
struct node *parseexpr(char *s);
#define DPARSE
struct node *parsetree;
TCHAR *errstr;
#define PARENSTACK 100
int inarglist[PARENSTACK],arglistptr; // keep track of whether a comma is an function argument separator, or operator
int pushflag(int x){
if(arglistptr < (PARENSTACK-1)) {
inarglist[++arglistptr] = x;
} else {
yyerror((TCHAR*)TEXT("too many nested parentheses or function calls")); // TODO: translate
return true;
}
return false;
}
#define POP() --arglistptr
#define ENTERARGS() if(pushflag(true)) YYERROR
#define ENTERPAREN() if(pushflag(false)) YYERROR
#define LEAVEARGS POP
#define LEAVEPAREN POP
%}
%token TOK_NUM TOK_EOF TOK_ARGSEP
%token TOK_FN1 TOK_FN2 TOK_FN3 TOK_FN4 TOK_FN5 TOK_FN10
%token TOK_SPECIALVAR TOK_VAR TOK_UNKNOWN TOK_BADCHAR
%left ','
%right '?' ':'
%left LOGAND LOGOR
%left '&' '^' '|'
%left EQ NE
%left '<' LE '>' GE
%left SHLEFT SHRIGHT
%left '-' '+'
%left '*' '/' '%'
%right EXP
%left NEG
%%
input : expr { parsetree = $1; } ;
expr : TOK_NUM
| TOK_VAR
| TOK_SPECIALVAR
| TOK_FN1 '(' {ENTERARGS();} expr ')' {LEAVEARGS();}
{ $$ = $1; $$->child[0] = $4; }
| TOK_FN2 '(' {ENTERARGS();} expr TOK_ARGSEP expr ')' {LEAVEARGS();}
{ $$ = $1; $$->child[0] = $4; $$->child[1] = $6; }
| TOK_FN3 '(' {ENTERARGS();} expr TOK_ARGSEP expr TOK_ARGSEP expr ')' {LEAVEARGS();}
{ $$ = $1; $$->child[0] = $4; $$->child[1] = $6; $$->child[2] = $8; }
| TOK_FN4 '(' {ENTERARGS();} expr TOK_ARGSEP expr TOK_ARGSEP expr TOK_ARGSEP expr ')' {LEAVEARGS();}
{ $$ = $1; $$->child[0] = $4; $$->child[1] = $6; $$->child[2] = $8; $$->child[3] = $10; }
| TOK_FN5 '(' {ENTERARGS();} expr TOK_ARGSEP expr TOK_ARGSEP expr TOK_ARGSEP expr TOK_ARGSEP expr ')' {LEAVEARGS();}
{ $$ = $1; $$->child[0] = $4; $$->child[1] = $6; $$->child[2] = $8; $$->child[3] = $10; $$->child[4] = $12; }
| TOK_FN10 '(' {ENTERARGS();}
expr TOK_ARGSEP expr TOK_ARGSEP expr TOK_ARGSEP expr TOK_ARGSEP expr TOK_ARGSEP
expr TOK_ARGSEP expr TOK_ARGSEP expr TOK_ARGSEP expr TOK_ARGSEP expr
')' {LEAVEARGS();}
{ $$ = $1;
$$->child[0] = $4; $$->child[1] = $6; $$->child[2] = $8; $$->child[3] = $10; $$->child[4] = $12;
$$->child[5] = $14; $$->child[6] = $16; $$->child[7] = $18; $$->child[8] = $20; $$->child[9] = $22;
}
| '(' {ENTERPAREN();} expr ')' { LEAVEPAREN(); $$ = $3; }
/* arithmetic operators */
| expr '+' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr '-' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr '*' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr '/' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr '%' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
/* exponentiation (not in FF spec) */
| expr EXP expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
/* relational operators */
| expr EQ expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr NE expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr '<' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr LE expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr '>' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr GE expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
/* logical operators */
| expr LOGAND expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr LOGOR expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| '!' expr %prec NEG { $$ = $1; $$->child[0] = $2; }
/* conditional operator */
| expr '?' expr ':' expr
{ $$ = $2; $$->child[0] = $1; $$->child[1] = $3; $$->child[2] = $5; }
/* bitwise operators */
| expr '&' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr '^' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr '|' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr SHLEFT expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| expr SHRIGHT expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
| '~' expr %prec NEG { $$ = $1; $$->child[0] = $2; }
/* sequence operator */
| expr ',' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
/* unary operators */
| '-' expr %prec NEG { $$ = $1; $$->child[0] = 0; $$->child[1] = $2; }
| '+' expr %prec NEG { $$ = $2; }
/* error tokens */
| TOK_UNKNOWN { yyerror((TCHAR*)TEXT("unknown name")); YYERROR; } // TODO: translate
| TOK_BADCHAR { yyerror((TCHAR*)TEXT("disallowed character")); YYERROR; } // TODO: translate
;
%%
// Daniel 06 July 2021: Move these two lines out of the function parseexpr(), otherwise the code won't compile in G++
struct yy_buffer_state *yy_scan_string(const char*); // hack. correct prototype is buried in lex output
int yyparse(void); // hack. correct prototype appears just after this code, in yacc output
struct node *parseexpr(char *s){
extern int tokpos,tokstart;
tokstart = tokpos = 0;
if(s){
arglistptr = 0;
inarglist[arglistptr] = false;
node_list = 0;
yy_scan_string(s);
if(!yyparse()) {
return parsetree;
} else { /* ensure we don't leak memory, on an unsuccessful parse */
freeallnodes();
}
} else {
yyerror((TCHAR*)TEXT("null string???"));// TODO: translate
}
return 0;
}
void yyerror(TCHAR *msg){
errstr = msg;
}