Subversion Repositories filter_foundry

Rev

Blame | Last modification | View Log | RSS feed

%{

/*
        This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
    Copyright (C) 2003-5 Toby Thain, toby@telegraphics.com.au

    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 <c.h> // OS X?
#include "node.h"

void yyerror(char*);

#define DPARSE 

struct node *parsetree;
char *errstr;

enum{ 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("too many nested parentheses or function calls");
                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 TOK_FN1 TOK_FN2 TOK_FN3 TOK_VAR TOK_UNKNOWN TOK_BADCHAR

%left ','
%left '?'
%left LOGAND LOGOR
%left BITAND BITXOR BITOR
%left EQ NE
%left '<' LE '>' GE
%left SHLEFT SHRIGHT
%left '-' '+'
%left '*' '/' '%'
%left NEG LOGNOT BITNOT
%right '^'

%%

input : expr { parsetree = $1; } ;

expr : TOK_NUM 
        | TOK_VAR
        | expr ',' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
/*
        | expr '?' expr ':' expr
                { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; $$->child[2] = $5; }
*/
        | expr LOGAND expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
        | expr LOGOR expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
        | expr BITAND expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
        | expr BITXOR expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
        | expr BITOR expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
        | 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; }
        | expr SHLEFT expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
        | expr SHRIGHT 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; }
        | expr '/' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
        | '!' expr %prec NEG { $$ = $1; $$->child[0] = $2; }
        | '~' expr %prec NEG { $$ = $1; $$->child[0] = $2; }
        | expr '^' expr { $$ = $2; $$->child[0] = $1; $$->child[1] = $3; }
        | '-' expr %prec NEG { $$ = $1; $$->child[0] = 0; $$->child[1] = $2; }
        | '+' expr %prec NEG { $$ = $2; }
        | '(' {ENTERPAREN();} expr ')' { LEAVEPAREN(); $$ = $3; }
        | 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_UNKNOWN { yyerror("unknown identifier"); YYERROR; }
        | TOK_BADCHAR { yyerror("bad character"); YYERROR; }
        ;

%%

struct node *parseformula(char *s){
        arglistptr = 0;
        inarglist[arglistptr] = FALSE;

        yy_scan_string(s);
        return yyparse() ? 0 : parsetree;
}

void yyerror(char *msg){
        errstr = msg;
}