📄 parser.c
字号:
/***************************************************************************** * parser.c: ***************************************************************************** * Copyright (C) 2004 VideoLAN * $Id: parser.c 10101 2005-03-02 16:47:31Z robux4 $ * * Authors: Cyril Deguet <asmax@videolan.org> * code from projectM http://xmms-projectm.sourceforge.net * * 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, USA. *****************************************************************************//* parser.c */#include <stdio.h>#include <string.h>#include <stdlib.h>#include "common.h"#include "fatal.h"#include "splaytree_types.h"#include "splaytree.h"#include "tree_types.h"#include "expr_types.h"#include "eval.h"#include "param_types.h"#include "param.h"#include "func_types.h"#include "func.h"#include "preset_types.h"#include "builtin_funcs.h"#include "per_pixel_eqn_types.h"#include "per_pixel_eqn.h"#include "init_cond_types.h"#include "init_cond.h"#include "per_frame_eqn_types.h"#include "per_frame_eqn.h"#include "parser.h"#include "engine_vars.h"#include "custom_wave_types.h"#include "custom_wave.h"#include "custom_shape_types.h"#include "custom_shape.h"/* Strings that prefix (and denote the type of) equations */#define PER_FRAME_STRING "per_frame_"#define PER_FRAME_STRING_LENGTH 10#define PER_PIXEL_STRING "per_pixel_"#define PER_PIXEL_STRING_LENGTH 10#define PER_FRAME_INIT_STRING "per_frame_init_"#define PER_FRAME_INIT_STRING_LENGTH 15#define WAVECODE_STRING "wavecode_"#define WAVECODE_STRING_LENGTH 9#define WAVE_STRING "wave_"#define WAVE_STRING_LENGTH 5#define PER_POINT_STRING "per_point"#define PER_POINT_STRING_LENGTH 9#define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"#define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9#define SHAPECODE_STRING "shapecode_"#define SHAPECODE_STRING_LENGTH 10#define SHAPE_STRING "shape_"#define SHAPE_STRING_LENGTH 6#define SHAPE_INIT_STRING "init"#define SHAPE_INIT_STRING_LENGTH 4#define WAVE_INIT_STRING "init"#define WAVE_INIT_STRING_LENGTH 4/* Stores a line of a file as its being parsed */char string_line_buffer[STRING_LINE_SIZE]; /* The current position of the string line buffer (see above) */int string_line_buffer_index = 0;/* All infix operators (except '=') are prototyped here */extern infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult, * infix_or, * infix_and, * infix_mod, * infix_positive, * infix_negative;/* If the parser reads a line with a custom wave, this pointer is set to the custom wave of concern */custom_wave_t * current_wave = NULL;custom_shape_t * current_shape = NULL;/* Counts the number of lines parsed */unsigned int line_count = 1;int per_frame_eqn_count = 0;int per_frame_init_eqn_count = 0;typedef enum { NORMAL_LINE_MODE, PER_FRAME_LINE_MODE, PER_PIXEL_LINE_MODE, INIT_COND_LINE_MODE, CUSTOM_WAVE_PER_POINT_LINE_MODE, CUSTOM_WAVE_PER_FRAME_LINE_MODE, CUSTOM_WAVE_WAVECODE_LINE_MODE, CUSTOM_SHAPE_SHAPECODE_LINE_MODE,} line_mode_t;line_mode_t line_mode = NORMAL_LINE_MODE;/* Token enumeration type */typedef enum { tEOL, /* end of a line, usually a '/n' or '/r' */ tEOF, /* end of file */ tLPr, /* ( */ tRPr, /* ) */ tLBr, /* [ */ tRBr, /* ] */ tEq, /* = */ tPlus, /* + */ tMinus, /* - */ tMult, /* * */ tMod, /* % */ tDiv, /* / */ tOr, /* | */ tAnd, /* & */ tComma, /* , */ tPositive, /* + as a prefix operator */ tNegative, /* - as a prefix operator */ tSemiColon, /* ; */ tStringTooLong, /* special token to indicate an invalid string length */ tStringBufferFilled /* the string buffer for this line is maxed out */} token_t;int get_string_prefix_len(char * string);tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root);tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t ** root);token_t parseToken(FILE * fs, char * string);gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset);gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset);gen_expr_t * parse_sign_arg(FILE * fs);int parse_float(FILE * fs, double * float_ptr);int parse_int(FILE * fs, int * int_ptr);int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root);int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root);gen_expr_t * parse_gen_expr(FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset);per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset);init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database);int parse_wavecode_prefix(char * token, int * id, char ** var_string);int parse_wavecode(char * token, FILE * fs, preset_t * preset);int parse_wave_prefix(char * token, int * id, char ** eqn_string);int parse_shapecode(char * eqn_string, FILE * fs, preset_t * preset);int parse_shapecode_prefix(char * token, int * id, char ** var_string);int parse_wave(char * eqn_string, FILE * fs, preset_t * preset);int parse_shape(char * eqn_string, FILE * fs, preset_t * preset);int parse_shape_prefix(char * token, int * id, char ** eqn_string);int update_string_buffer(char * buffer, int * index);int string_to_float(char * string, double * float_ptr);/* Grabs the next token from the file. The second argument points to the raw string */token_t parseToken(FILE * fs, char * string) { char c; int i; if (string != NULL) memset(string, 0, MAX_TOKEN_SIZE); /* Loop until a delimiter is found, or the maximum string size is found */ for (i = 0; i < MAX_TOKEN_SIZE;i++) { c = fgetc(fs); /* If the string line buffer is full, quit */ if (string_line_buffer_index == (STRING_LINE_SIZE - 1)) return tStringBufferFilled; /* Otherwise add this character to the string line buffer */ string_line_buffer[string_line_buffer_index++] = c; /* Now interpret the character */ switch (c) { case '+': return tPlus; case '-': return tMinus; case '%': return tMod; case '/': /* check for line comment here */ if ((c = fgetc(fs)) == '/') { while(1) { c = fgetc(fs); if (c == EOF) { line_mode = NORMAL_LINE_MODE; return tEOF; } if (c == '\n') { line_mode = NORMAL_LINE_MODE; return tEOL; } } } /* Otherwise, just a regular division operator */ ungetc(c, fs); return tDiv; case '*': return tMult; case '|': return tOr; case '&': return tAnd; case '(': return tLPr; case ')': return tRPr; case '[': return tLBr; case ']': return tRBr; case '=': return tEq; // case '\r': //break; case '\n': line_count++; line_mode = NORMAL_LINE_MODE; return tEOL; case ',': return tComma; case ';': return tSemiColon; case ' ': /* space, skip the character */ i--; break; case EOF: line_count = 1; line_mode = NORMAL_LINE_MODE; return tEOF; default: if (string != NULL) string[i] = c; } } /* String reached maximum length, return special token error */ return tStringTooLong; }/* Parse input in the form of "exp, exp, exp, ...)" Returns a general expression list */gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset) { int i, j; gen_expr_t ** expr_list; /* List of arguments to function */ gen_expr_t * gen_expr; /* Malloc the expression list */ expr_list = (gen_expr_t**)malloc(sizeof(gen_expr_t*)*num_args); /* Malloc failed */ if (expr_list == NULL) return NULL; i = 0; while (i < num_args) { //if (PARSE_DEBUG) printf("parse_prefix_args: parsing argument %d...\n", i+1); /* Parse the ith expression in the list */ if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) { //if (PARSE_DEBUG) printf("parse_prefix_args: failed to get parameter # %d for function (LINE %d)\n", i+1, line_count); for (j = 0; j < i; j++) free_gen_expr(expr_list[j]); free(expr_list); return NULL; } /* Assign entry in expression list */ expr_list[i++] = gen_expr; } //if (PARSE_DEBUG) printf("parse_prefix_args: finished parsing %d arguments (LINE %d)\n", num_args, line_count); /* Finally, return the resulting expression list */ return expr_list; }/* Parses a comment at the top of the file. Stops when left bracket is found */int parse_top_comment(FILE * fs) { char string[MAX_TOKEN_SIZE]; token_t token; /* Process tokens until left bracket is found */ while ((token = parseToken(fs, string)) != tLBr) { if (token == tEOF) return PARSE_ERROR; } /* Done, return success */ return SUCCESS; } /* Right Bracket is parsed by this function. puts a new string into name */int parse_preset_name(FILE * fs, char * name) { token_t token; if (name == NULL) return FAILURE; if ((token = parseToken(fs, name)) != tRBr) return PARSE_ERROR; //if (PARSE_DEBUG) printf("parse_preset_name: parsed preset (name = \"%s\")\n", name); return SUCCESS;}/* Parses per pixel equations */int parse_per_pixel_eqn(FILE * fs, preset_t * preset) { char string[MAX_TOKEN_SIZE]; gen_expr_t * gen_expr; if (PARSE_DEBUG) printf("parse_per_pixel: per_pixel equation parsing start...(LINE %d)\n", line_count); if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */ if (PARSE_DEBUG) printf("parse_per_pixel: equal operator expected after per pixel operator \"%s\", but not found (LINE %d)\n", string, line_count); return PARSE_ERROR; } /* Parse right side of equation as an expression */ if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) { if (PARSE_DEBUG) printf("parse_per_pixel: equation evaluated to null? (LINE %d)\n", line_count); return PARSE_ERROR; } /* Add the per pixel equation */ if (add_per_pixel_eqn(string, gen_expr, preset) < 0) { free_gen_expr(gen_expr); return PARSE_ERROR; } return SUCCESS;}/* Parses an equation line, this function is way too big, should add some helper functions */int parse_line(FILE * fs, struct PRESET_T * preset) { char eqn_string[MAX_TOKEN_SIZE]; token_t token; init_cond_t * init_cond; per_frame_eqn_t * per_frame_eqn; /* Clear the string line buffer */ memset(string_line_buffer, 0, STRING_LINE_SIZE); string_line_buffer_index = 0; switch (token = parseToken(fs, eqn_string)) { /* Invalid Cases */ case tRBr: case tLPr: case tRPr: case tComma: case tLBr: case tPlus: case tMinus: case tMod: case tMult: case tOr: case tAnd: case tDiv: // if (PARSE_DEBUG) printf("parse_line: invalid token found at start of line (LINE %d)\n", line_count); /* Invalid token found, return a parse error */ return PARSE_ERROR;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -