Subversion Repositories filter_foundry

Rev

Rev 495 | Rev 518 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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