Subversion Repositories psp

Rev

Rev 1353 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* Ãæ´Öµ­Ë¡ÅÅÂî -- calc */

%{
typedef float NumType;

#define YYSTYPE float
#define YYERROR_VERBOSE

#include <cmath>
#include <cctype>
#include <cstring>

#include <vector>
#include <sstream>

#include "calc.h"
#include "formula.h"
#include "formula-variables.h"

int yyerror(char* s);
int yylex();

const char* yyinStr;

typedef Formula<NumType> CalcFormula;
typedef Number<NumType> CalcNumber;
typedef Random<NumType> CalcRandom;
typedef Rank<NumType> CalcRank;
typedef Param<NumType> CalcParam;
typedef Operator CalcOperator;

namespace {
        CalcFormula* formula;
        std::vector<CalcFormula*> formulas;

        CalcFormula* f(float d) { return formulas[(int)d]; }

        int paramId;
}

%}

/* BISONÀë¸À */
%token NUM RAND RANK PARAM
%left '-' '+'
%left '*' '/'
%left NEG     /* negation--ñ¹à¥Þ¥¤¥Ê¥¹ */
%right '^'    /* ¤Ù¤­¾è´Ø¿ô        */

/* ʸˡµ¬Â§¤¬Â³¤¯ */
%%
input:    /* ¶õʸ»úÎó */
        | input line
;

line:     '\n'
| exp '\n'  { formula = f($1); return 0; }
;

exp:    NUM {
                $$ = formulas.size();
                formulas.push_back(new CalcFormula(new CalcNumber($1)));
        }
        | RAND {
                $$ = formulas.size();
            formulas.push_back(new CalcFormula(new CalcRandom()));
        }
        | RANK {
                        $$ = formulas.size();
                        formulas.push_back(new CalcFormula(new CalcRank()));
                }
        | PARAM {
                        $$ = formulas.size();
                        formulas.push_back(new CalcFormula(new CalcParam(paramId)));
                }
        | exp '+' exp {
                    $$ = formulas.size();
                        formulas.push_back(new CalcFormula(f($1), op_add, f($3)));
                }
        | exp '-' exp {
                    $$ = formulas.size();
                        formulas.push_back(new CalcFormula(f($1), op_sub, f($3)));
                }
        | exp '*' exp {
                    $$ = formulas.size();
                        formulas.push_back(new CalcFormula(f($1), op_mul, f($3)));
                }
        | exp '/' exp {
                    $$ = formulas.size();
                        formulas.push_back(new CalcFormula(f($1), op_div, f($3)));
                }
        | '-' exp  %prec NEG {
                    $$ = $2;
                        f($2)->setHeadSub();
                }
        | '(' exp ')' {
                    $$ = $2;
                }
;
%%

/**
 * »ú¶ç²òÀÏ´ï¤Ï¡¢¿ôÃͤòÆɤá¤Ð¡¢double·¿¤ÎÃͤò¥¹¥¿¥Ã¥¯¤ËÀѤó¤Ç
 * ¥È¡¼¥¯¥ó¡ÖNUM¡×¤òÊÖ¤·¡¢¿ôÃͰʳ°¤òÆɤá¤Ð¡¢¤½¤Îʸ»ú¤Î¥¢¥¹¥­¡¼Éä¹æ¤òÊÖ¤¹¡£
 * ¶õÇò¤È¥¿¥Ö¤ÏÆɤßÈô¤Ð¤µ¤ì¤ë¡£¥Õ¥¡¥¤¥ë¤¬½ª¤ï¤ë¤È0¤òÊÖ¤¹¡£
 */

#include <ctype.h>
#include <stdio.h>

int yylex ()
{
        int c;

        /* ¶õÇòÎà¤òÆɤßÈô¤Ð¤¹  */
        while ((c = *(yyinStr++)) == ' ' || c == '\t')
                ;
        /* ¿ôÃͤò½èÍý¤¹¤ë   */
        if (c == '.' || isdigit (c))
    {
                yyinStr--;
                sscanf (yyinStr, "%f", &yylval);
                while ((c = *(++yyinStr)) == '.' || isdigit(c)) {}
                return NUM;
    }

        // ÊÑ¿ô¤ò½èÍý¤¹¤ë */
        if (c == '$') {
                if (strncmp(yyinStr, "rand", 4) == 0) {
                        yyinStr += 4;
                        return RAND;
                }
                else if (strncmp(yyinStr, "rank", 4) == 0) {
                    yyinStr += 4;
                        return RANK;
        }
                else {
                        std::istringstream iss(std::string(yyinStr).substr(0, 1));
                        iss >> paramId;
                        yyinStr++;
                        return PARAM;
                }
        }

        /* ¥Õ¥¡¥¤¥ë¤Î½ª¤ï¤ê¤ò½èÍý¤¹¤ë  */
        if (c == '\0')
                return 0;
        /* 1ʸ»ú¤òÊÖ¤¹ */
        return c;
}

int yyerror(char* s) {
        printf("yyerror: %s\n", s);
        return 0;
}

std::auto_ptr<CalcFormula> calc(const std::string& str) {
        std::string fml = str + '\n';
        yyinStr = fml.c_str();
        yyparse();
        return std::auto_ptr<CalcFormula>(formula);
}