/************************************************************************
 * File: expr.c
 * Version: 0.01
 *
 * Posted at: www.donews.net/codez
 * Email: jay_zephyr2002#yahoo.com.cn
 * Written by codez @ Jan 162005
 *
 * Description:
 *   This program is a expression calculator. You can use it
 * to calculate expression. If you want to use a hex value in
 * calculating, with a prefix "0x" or "0X".
 *
 * Other:
 *    No float-point value support in this version.
 *
 * (C)opyright by codez! You can use it freely, but NO WARRANTY!!!
 *
 *----------------------------------------------------------------
 * e.g
 *
 *    your input can be:
 *    ------------------
 *    0xab+0x12-18*(21-(5+8)-0xa+0xb0)
 *
 *    output result is:
 *    -----------------
 *    Result is: -2943 42949643530xFFFFF481
 *
 *=================================================================
 *
 * ========
 * BNF Rule
 * ========
 * 
 * exp     := exp addop term | term
 * addop   := +|-
 * term    := term mulop factor | factor
 * mulop   := *|/
 * factor  := (exp) | num | hex
 * 
 * =========
 * EBNF Rule
 * =========
 * 
 * exp     ::= term {addop term}
 * addop   ::= +|-
 * term    ::= factor {mulop factor}
 * mulop   ::= *|/
 * factor  ::= (exp) | num | hex

 * ================
 * Other definition
 * ================
 * 
 * digit     [0-9]
 * num       {digit}+
 * 
 * hex_base  [0-9a-fA-F]
 * hex       0x{hex_base}+
 *
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>

/* calculator type */

/**
 * or you can use follw type

 typedef unsigned long VALUE_TYPE;

 */
typedef int VALUE_TYPE;

/* input buffer size */
#define MAX_SIZE     1024

/* if you only want to use hex value, set this for 1 */
#define     ALWAYS_USE_HEX     0

/* input buffer */
char buffer[MAX_SIZE];

/* token for advance input */
char token;

/* token iterator in buffer */
int _idx = 0;

/* get token */
void getToken(void)
{
     token = buffer[_idx++];
}

/* unget token */
/*
void ungetToken(void)
{
    if (_idx != 0) 
        buffer[--_idx] = token;
}
*/


/* function pre-declaration */
VALUE_TYPE expr();
VALUE_TYPE term();
VALUE_TYPE factor();
VALUE_TYPE get_value(int bHex);

int main()
{
     VALUE_TYPE temp = 0;

     printf("please input a expression:\n");
     scanf("%s", buffer);

     getToken();
     temp = expr();

     printf("=======================================================\n");
     printf("Result is: %d %uL 0x%X\n", temp, (long)temp, (long)temp);
     printf("=======================================================\n");

     return 0;
}

VALUE_TYPE expr()
{
     VALUE_TYPE temp = 0;

     temp = term();
     
     while (token)
     {
          if (token=='+')
          {
               getToken();
               temp += term();
          }
          else if (token=='-')
          {
               getToken();
               temp -= term();
          }
          else if (token==')' || token=='\0')
               break;
          else if (token==' ' || token=='\t' || token=='\r' || token=='\n')
          {
               getToken();
               continue;
          }
          else
          {
               fprintf(stderr, "Error: invalid token[%d] -> %02X in exp()!\n", _idx-1, token);
               exit(1);
          }
     }

     return temp;
}

VALUE_TYPE term()
{
     VALUE_TYPE temp = 0, divtmp;

     temp = factor();

     while (token)
     {
          if (token=='*')
          {
               getToken();
               temp *= factor();
          }
          else if (token=='/')
          {
               getToken();
               divtmp = factor();
               if (divtmp == 0)
               {
                    fprintf(stderr, "Error: divided by zero!");
                    exit(1);
               }

               temp /= divtmp;
          }
          else if (token==' ' || token=='\t' || token=='\r' || token=='\n')
          {
               getToken();
               continue;
          }
          else
               break;
     }

     return temp;
}

VALUE_TYPE factor()
{
     int bHex = 0;
     VALUE_TYPE temp = 0;

     if (token=='(')
     {
          /* skip left bracket */
          getToken();     
          temp = expr();
          /* skip right bracket */
          getToken();
     
          return temp;
     }
     
     if (token=='0')
     {
          getToken();
          if (token=='x' || token=='X') {
               getToken();
               bHex = 1;
          }
     }

     return get_value(bHex);
}

VALUE_TYPE get_value(int bHex)
{
     VALUE_TYPE ret = 0, temp, cf;

     bHex = ALWAYS_USE_HEX | bHex;
     cf = bHex ? 16:10;
     
     while (1)
     {
          if (bHex &&
               (     ( token>='A' && token<='F' ) ||
                    ( token>='a' && token<='f' )
               ))
          {
               token |= 0x20;
               temp = (VALUE_TYPE)(token - 'a' + 10);
          }
          else
          {
               if ( token>='0' && token<='9' )
                    temp = (VALUE_TYPE)(token-'0');
               else
                    break;
          }

          ret *= cf;
          ret += temp;

          getToken();
     }

     return ret;
}



Trackback: http://tb.donews.net/TrackBack.aspx?PostId=244518


[点击此处收藏本文]  发表于2005年01月17日 6:03 PM




正在读取评论……
添加评论
大名
网址


验证码
评论