/*
 * Configurable ps-like program.
 * Definitions for expression parsing.
 *
 * Copyright (c) 2010 David I. Bell
 * Permission is granted to use, distribute, or modify this source,
 * provided that this copyright notice remains intact.
 */

#ifndef	EXPR_H
#define	EXPR_H

#include "ips.h"


#define	isLower(ch)	(((ch) >= 'a') && ((ch) <= 'z'))
#define	isUpper(ch)	(((ch) >= 'A') && ((ch) <= 'Z'))
#define	isOctal(ch)	(((ch) >= '0') && ((ch) <= '7'))

#define	isHex(ch)	((((ch) >= 'a') && ((ch) <= 'f')) || \
			(((ch) >= 'A') && ((ch) <= 'F')) || isDigit(ch))

#define	isBegSymbol(ch)	(isLower(ch) || isUpper(ch))
#define	isSymbol(ch)	(isBegSymbol(ch) || isDigit(ch) || ((ch) == '_'))


/*
 * The maximum number of children for a node.
 * This limits functions to this number of arguments.
 */
#define	CHILDS	3


/*
 * Function ids for use in expressions.
 * Encoded in the id is the number of arguments.
 */
#define	FUNCTION_BUILD(op, args)	(((op) * 10) + (args))
#define	FUNCTION_OP(func)		((func) / 10)
#define	FUNCTION_ARGS(func)		((func) % 10)


/*
 * Opcodes for expressions.
 */
typedef	int	OP;

#define	OP_NONE		((OP) 0)
#define	OP_NOT		((OP) 1)
#define	OP_ANDAND	((OP) 2)
#define	OP_OROR		((OP) 3)
#define	OP_COLUMN_BASE	((OP) 4)
#define	OP_COLUMN_SHOW	((OP) 5)
#define	OP_COLUMN_TEST	((OP) 6)
#define	OP_EQUAL	((OP) 7)
#define	OP_NOTEQUAL	((OP) 8)
#define	OP_LESS		((OP) 9)
#define	OP_LESSEQUAL	((OP) 10)
#define	OP_GREATER	((OP) 11)
#define	OP_GREATEREQUAL	((OP) 12)
#define	OP_ADD		((OP) 13)
#define	OP_SUBTRACT	((OP) 14)
#define	OP_MULTIPLY	((OP) 15)
#define	OP_DIVIDE	((OP) 16)
#define	OP_MODULO	((OP) 17)
#define	OP_NEGATE	((OP) 18)
#define	OP_AND		((OP) 19)
#define	OP_OR		((OP) 20)
#define	OP_COMPLEMENT	((OP) 21)
#define	OP_ALTERNATION	((OP) 22)
#define	OP_STRING	((OP) 23)
#define	OP_NUMBER	((OP) 24)
#define	OP_LEFTSHIFT	((OP) 25)
#define	OP_RIGHTSHIFT	((OP) 26)
#define	OP_XOR		((OP) 27)
#define	OP_FUNCTION	((OP) 28)


/*
 * Different token types.
 */
typedef	int	TOKEN;

#define	TOKEN_BAD		((TOKEN) 0)
#define	TOKEN_EOF		((TOKEN) 1)
#define	TOKEN_SYMBOL		((TOKEN) 2)
#define	TOKEN_NUMBER		((TOKEN) 3)
#define	TOKEN_COMMA		((TOKEN) 4)
#define	TOKEN_PERIOD		((TOKEN) 5)
#define	TOKEN_LEFTPAREN		((TOKEN) 6)
#define	TOKEN_RIGHTPAREN	((TOKEN) 7)
#define	TOKEN_NOT		((TOKEN) 8)
#define	TOKEN_COMPLEMENT	((TOKEN) 9)
#define	TOKEN_ANDAND		((TOKEN) 10)
#define	TOKEN_OROR		((TOKEN) 11)
#define	TOKEN_EQUAL		((TOKEN) 12)
#define	TOKEN_NOTEQUAL		((TOKEN) 13)
#define	TOKEN_LESS		((TOKEN) 14)
#define	TOKEN_LESSEQUAL		((TOKEN) 15)
#define	TOKEN_GREATER		((TOKEN) 16)
#define	TOKEN_GREATEREQUAL	((TOKEN) 17)
#define	TOKEN_STRING		((TOKEN) 18)
#define	TOKEN_PLUS		((TOKEN) 19)
#define	TOKEN_MINUS		((TOKEN) 20)
#define	TOKEN_MULTIPLY		((TOKEN) 21)
#define	TOKEN_DIVIDE		((TOKEN) 22)
#define	TOKEN_MODULO		((TOKEN) 23)
#define	TOKEN_AND		((TOKEN) 24)
#define	TOKEN_OR		((TOKEN) 25)
#define	TOKEN_XOR		((TOKEN) 26)
#define	TOKEN_QUESTIONMARK	((TOKEN) 27)
#define	TOKEN_COLON		((TOKEN) 28)
#define	TOKEN_LEFTSHIFT		((TOKEN) 29)
#define	TOKEN_RIGHTSHIFT	((TOKEN) 30)


/*
 * A node of the expression tree.
 * For non-leaf nodes, the node contains pointers to subnodes which are
 * evaluated first, and then operated on to construct this node's value.
 * For leaf nodes, the node contains the value to be returned.
 * This value can be a number, string, or column.
 */
typedef	struct	NODE	NODE;

struct	NODE
{
	OP	op;		/* operation for this node */
	NODE *	child[CHILDS];	/* children of this node */
	COLUMN *column;		/* named column */
	char *	strVal;		/* string value */
	long	intVal;		/* integer value */
};


/*
 * All the data associated with an expression tree.
 */
typedef	struct
{
	char *		expr;		/* expression string being parsed */
	char *		modExpr;	/* modifyable copy of expression */
	char *		cp;		/* current position being parsed */
	TOKEN		token;		/* current token */
	char *		tokenStr;	/* string value of current token */
	long		tokenInt;	/* integer value of current token */
	BOOL		rescanToken;	/* reread token next call */
	NODE *		root;		/* root of expression tree */
	const PROC *	proc;		/* process to evaluate for */
	int		depth;		/* depth of sub-expressions */
	BOOL		failed;		/* there is an error in the parse */
} TREE;


/*
 * External procedures.
 */
extern	BOOL	ParseTree(TREE * tree, const char * str, int depth);
extern	VALUE	EvaluateNode(TREE * tree, const NODE * node);
extern	USEFLAG	GetNodeUseFlags(const NODE * node);

#endif

/* END CODE */
