⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 formula.c

📁 一个简单的解析器
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************
 Filename : formula.c
 Version  : Formula Language V1.1
 Author   : Shen Tu Hongnan
 Modify   :
 Date     : 2001/08/26
 Remark   :
 ***************************************/

#define UNIX

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdarg.h>
#include <time.h>

#ifdef UNIX
    #include <sys/types.h>
    #include <sys/times.h>
#endif

#include    "formula.h"

//#include    "d:\mds\formula.h"

/*************************************************************************/
/* 堆栈及变量 */
typedef struct  {
        FIELD   *sp;                            /* 运算堆栈指针 */
        FIELD   **vp;                           /* 赋值堆栈指针 */
        FIELD   *px;                            /* 输入变量组 */
        FIELD   *py;                            /* 输出变量组 */
        FIELD   *pz;                            /* 临时变量组 */
        } PACK;

/* 函数名,函数指针 */
typedef struct {
        char   name[16];
        int    (*addr)(PACK *pp);
        } FUN_LIST;

/* 运算符号 */
typedef struct  {
        int     op;                             /* 操作符 */
        short   level;                          /* 优先级 */
        } SIGN;

extern int      MaxFun;
extern FUN_LIST Fun[];

//#include    "d:\mds\function.c"

/*****************************************************************************/
static void Calc65(PACK *pp);
static void Calc66(PACK *pp);
static void Calc67(PACK *pp);
static void Calc68(PACK *pp);
static void Calc69(PACK *pp);
static void Calc70(PACK *pp);
static void Calc71(PACK *pp);
static void Calc72(PACK *pp);
static void Calc73(PACK *pp);
static void Calc74(PACK *pp);
static void Calc75(PACK *pp);
static void Calc76(PACK *pp);
static void Calc77(PACK *pp);

typedef struct {
        void   (*addr)(PACK *pp);
        } OPERATION;

static OPERATION Calc[13] = {
                 {Calc65,},
                 {Calc66,},
                 {Calc67,},
                 {Calc68,},
                 {Calc69,},
                 {Calc70,},
                 {Calc71,},
                 {Calc72,},
                 {Calc73,},
                 {Calc74,},
                 {Calc75,},
                 {Calc76,},
                 {Calc77,},
                 };

static short Level[12] = {2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 6};
/*65* ,66/,67+,68-,69<,70<=,71>,72>=,73==,74!=,75&&,76||,77=*/
/*************************************************************************
 Function: ReadRuleFile()
 Purpose : 从规则文件中读入公式行到运算规则 rule 中。
 Input   : 规则文件指针 fp,规则指针 rule。
 Return  : 返回 0,出错时返回非零的错误代码。
 Modify  : 无
 Remark  : 对公式语言进行了预编译
           错误代码:
           1...函数名错
           2...if....goto 语句错
           3...goto 语句错
           4...赋值表达式错
           5...下标超出范围
           6...标号错误
           7...无效字符
           8...逻辑非对象缺少括号
           9...配对符号错误
          10...常数太多
          11...规则文件超长
 *************************************************************************/

#define ERROR5  printf("第 %d 行:下标超出范围\n", line)
#define ERROR9  printf("第 %d 行:配对符号错误\n", line)

/*****************************************************************************/
int ReadRuleFile(FILE *fp, RULE *rule)
{
int     i = 0, np = 0, line = 0, par1 = 0, par2 = 0;
int     j, k, n, m, if_goto_flag;
char    *bp, *tp;
char    buf[256], tmp[64];

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
while (fgets(buf, sizeof(buf), fp) != (char *)NULL)
      {

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
      line++;

      /* 注释行或空行,忽略 */
      if  (*buf == '#' || *buf == '\n' || *buf == '\0')
          continue;

      /* 解析公式行 */
      bp = buf;
      if_goto_flag = 0;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
      while (*bp != '\n' && *bp != '\0')
            {

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
            /* # 号后为注释,忽略 */
            if  (*bp == '#')
                break;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
            /* 数值常量 */
            if  (isdigit(*bp) || *bp == '.')
                {
                if  (np >= 256)
                    {
                    printf("第 %d 行:常数太多\n", line);
                    return (10);
                    }

                /* 将常数串移入 tmp */
                tp = tmp;

                do {
                   *tp++ = *bp++;
                   } while (isdigit(*bp) || *bp == '.');

                *tp = '\0';

                /* 设置规则串并将值保存 */
                rule->str[i++] = '?';
                rule->str[i++] = np & 0x00FF;
                rule->num[np++] = atof(tmp);

                continue;
                }

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
            /* 大写字母开头的为函数名 */
            if  (isupper(*bp))
                {
                /* 取函数名 */
                tp = tmp;

                while (*bp != '(')
                      *tp++ = *bp++;

                *tp = '\0';

                /* 查找函数在数组中的下标 */
                n = 1;
                m = MaxFun;

                while (n <= m)
                      {
                      j = (m + n)/2;
                      if  ((k = strcmp(tmp, Fun[j].name)) == 0)
                          break;

                      if  (k > 0)
                          n = j + 1;
                      else
                          m = j - 1;
                      }

                if  (k != 0)
                    {
                    printf("第 %d 行:错误的函数名\n", line);
                    return (1);
                    }

                /* 置内部函数名 */
                rule->str[i++] = '@';
                rule->str[i++] = j & 0x00FF;
                rule->str[i++] = (j >> 8) & 0x00FF;

                continue;
                }

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
            /* 其他情形的解析 */
            switch (*bp)
                   {

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   /* 空白字符,忽略 */
                   case ' ':
                   case '\t':
                        bp++;
                        break;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   /* 字符串常量 */
                   case '"':
                        rule->str[i++] = *bp++;
                        while ((rule->str[i++] = *bp++) != '"');

                        continue;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   /* if 语句,置 if_goto_flag 标志 */
                   case 'i':
                        bp++;
                        if  (*bp++ == 'f' && if_goto_flag == 0)
                            if_goto_flag = 1;
                        else
                            {
                            printf("第 %d 行:if....goto 语句错\n", line);
                            return (2);
                            }

                        break;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   /* goto 语句 */
                   case 'g':
                        bp++;
                        if  (*bp++ != 'o' || if_goto_flag == 2)
                            {
                            printf("第 %d 行:goto 语句错\n", line);
                            return (3);
                            }

                        while (islower(*bp) || *bp == ' ' || *bp == '\t')
                              bp++;

                        /* goto 后面没有标号 */
                        if  (*bp++ != '@')
                            {
                            printf("第 %d 行:goto 语句错\n", line);
                            return (3);
                            }

                        /* R 条件转移,S 绝对转移 */
                        if  (if_goto_flag)
                            rule->str[i++] = 'R';
                        else
                            rule->str[i++] = 'S';

                        if_goto_flag = 2;

                        /* 计算标号 */
                        j = 0;
                        while (isdigit(*bp))
                              j = 10*j + *bp++ - 48;

                        if  (j >= RULE_ADDR_SIZE)
                            {
                            ERROR5;
                            return (5);
                            }

                        rule->str[i++] = j;

                        break;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   /* 变量 */
                   case 'x':
                   case 'y':
                   case 'z':
                        /* 改为大写字母 */
                        rule->str[i++] = *bp++ - 32;

                        /* 确定下标 */
                        j = 0;
                        while (isdigit(*bp))
                              j = 10*j + *bp++ - 48;

                        if  (j >= 256 || (rule->str[i-1] == 'Z' && j >= Zarray_SIZE))
                            {
                            ERROR5;
                            return (5);
                            }

                        rule->str[i++] = j;

                        /* 赋值对象,XYZ 改为UVW,并且跳过等号 */
                        while (*bp == ' ' || *bp == '\t')
                              bp++;

                        if  (*bp == '=' && *(bp+1) != '=')
                            {
                            rule->str[i-2] -= 3;
                            bp++;
                            }

                        break;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   /* 标号 */
                   case '@':
                        /* 取数字串 */
                        bp++;

                        j = 0;
                        while (isdigit(*bp))
                              j = 10*j + *bp++ - 48;

                        if  (j >= RULE_ADDR_SIZE)
                            {
                            ERROR5;
                            return (5);
                            }

                        while (*bp == ' ' || *bp == '\t') bp++;
                        if  (*bp++ != ':')
                            {
                            printf("第 %d 行:标号错误\n", line);
                            return (6);
                            }

                        /* 置跳转地址 */
                        rule->addr[j] = i;

                        break;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   /* 运算符 */
                   case '*':
      	                rule->str[i++] = 'A';
      	                bp++;

      	                break;

                   case '/':
      	                rule->str[i++] = 'B';
      	                bp++;

      	                break;

                   case '+':
      	                rule->str[i++] = 'C';
      	                bp++;

      	                break;

                   case '-':
      	                rule->str[i++] = 'D';
      	                bp++;

      	                break;

                   /* <, <= */
                   case '<':
                        rule->str[i++] = 'E';
                        if  (*(++bp) == '=')
                            {
                            bp++;
                            rule->str[i-1] = 'F';
                            }

                        break;

                   /* >, >= */
                   case '>':
                        rule->str[i++] = 'G';
                        if  (*(++bp) == '=')
                            {
                            bp++;
                            rule->str[i-1] = 'H';
                            }

                        break;

                   /* == */
                   case '=':
                        rule->str[i++] = 'I';
                        bp++;

                        if  (*bp++ != '=')
                            {
                            printf("第 %d 行:赋值表达式错\n", line);
                            return (4);
                            }

                        break;

                   /* !, != */
                   case '!':
                        if  (*(++bp) == '=')
                            {
                            bp++;
                            rule->str[i++] = 'J';
                            }
                        else
                            {
                            rule->str[i++] = '@';
                            rule->str[i++] = 0;
                            rule->str[i++] = 0;

                            while (*bp == ' ' || *bp == '\t') bp++;
                            if  (*bp != '(')
                                {
                                printf("第 %d 行:逻辑非对象缺少括号\n", line);
                                return (8);
                                }
                            }

                        break;

                   /* && */
                   case '&':
                        rule->str[i++] = 'K';
                        if  (*(++bp) == '&')
                            bp++;

                        break;

                   /* || */
                   case '|':
                        rule->str[i++] = 'L';
                        if  (*(++bp) == '|')
                            bp++;

                        break;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
                   /* 分隔符及括号 */
                   case '?':
                   case ':':
                   case ',':
      	                rule->str[i++] = 'N';
      	                bp++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -