2018-05-21 00:12:57 +08:00
|
|
|
%{
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2018-05-21 01:56:44 +08:00
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
void yyerror(const char* msg);
|
2018-05-21 00:12:57 +08:00
|
|
|
extern FILE* yyin;
|
2018-05-21 01:56:44 +08:00
|
|
|
extern int yylex();
|
2018-05-21 00:12:57 +08:00
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{null, opera, var, val} NodeType;
|
2018-05-21 01:56:44 +08:00
|
|
|
typedef enum {false, true} bool;
|
2018-05-21 00:12:57 +08:00
|
|
|
typedef struct Node {
|
|
|
|
float val;
|
|
|
|
char * name; // val_name
|
|
|
|
char * opr; // operator
|
|
|
|
NodeType node_type;
|
|
|
|
struct Node * left;
|
|
|
|
struct Node * right;
|
|
|
|
} Node;
|
|
|
|
|
|
|
|
Node create_op_node(char * op){
|
|
|
|
Node node;
|
|
|
|
node.opr = op;
|
|
|
|
node.node_type = opera;
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node create_var_node(char * op){
|
|
|
|
Node node;
|
|
|
|
node.name = op;
|
|
|
|
node.node_type = var;
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node create_val_node(float value){
|
|
|
|
Node node;
|
|
|
|
node.val = value;
|
|
|
|
node.node_type = val;
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
void connect_node(Node* op, Node* l, Node* r){
|
|
|
|
op->left = l;
|
|
|
|
op->right = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
char * var_name = "";
|
|
|
|
|
|
|
|
void run_through_tree (Node *node){
|
|
|
|
switch (node->node_type){
|
|
|
|
case var:
|
|
|
|
printf("varable name:%s\n",node->name);
|
|
|
|
break;
|
|
|
|
case val:
|
|
|
|
printf("num value:%f\n",node->val);
|
|
|
|
break;
|
|
|
|
case opera:
|
|
|
|
printf("\noperator:%s\n",node->opr);
|
|
|
|
printf("LFS\n");
|
|
|
|
run_through_tree(node->left);
|
|
|
|
printf("RHS\n");
|
|
|
|
run_through_tree(node->right);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2018-05-21 01:56:44 +08:00
|
|
|
bool escape_recursion = false;
|
2018-05-21 00:12:57 +08:00
|
|
|
float eval_node(float var_val, Node * node){
|
2018-05-21 01:56:44 +08:00
|
|
|
|
2018-05-21 00:12:57 +08:00
|
|
|
switch ((*node).node_type){
|
|
|
|
case var:
|
2018-05-21 01:56:44 +08:00
|
|
|
if (strcmp(var_name,"")==0){
|
|
|
|
var_name = node->name;
|
2018-05-21 00:12:57 +08:00
|
|
|
return var_val;
|
|
|
|
}
|
2018-05-21 01:56:44 +08:00
|
|
|
else if (strcmp(var_name,node->name)==0){
|
2018-05-21 00:12:57 +08:00
|
|
|
return var_val;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
printf("Error: Too many variable, eg. %s, %s.\n",
|
|
|
|
var_name,node->name);
|
2018-05-21 01:56:44 +08:00
|
|
|
escape_recursion = true;
|
|
|
|
return NAN;
|
2018-05-21 00:12:57 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
case val:
|
|
|
|
return (*node).val;
|
|
|
|
break;
|
2018-05-21 01:56:44 +08:00
|
|
|
case opera:{
|
|
|
|
float left_num, right_num;
|
|
|
|
|
|
|
|
left_num = eval_node(var_val,node->left);
|
|
|
|
if (escape_recursion){return NAN; break;}
|
|
|
|
|
|
|
|
right_num = eval_node(var_val,node->right);
|
|
|
|
if (escape_recursion){return NAN; break;}
|
|
|
|
|
|
|
|
if (node->opr == "+"){
|
|
|
|
return left_num + right_num;
|
2018-05-21 00:12:57 +08:00
|
|
|
}
|
|
|
|
else if (node->opr == "-"){
|
2018-05-21 01:56:44 +08:00
|
|
|
return left_num - right_num;
|
2018-05-21 00:12:57 +08:00
|
|
|
}
|
|
|
|
else if (node->opr == "*"){
|
2018-05-21 01:56:44 +08:00
|
|
|
return left_num * right_num;
|
2018-05-21 00:12:57 +08:00
|
|
|
}
|
|
|
|
else if (node->opr == "/"){
|
2018-05-21 01:56:44 +08:00
|
|
|
return left_num / right_num;
|
2018-05-21 00:12:57 +08:00
|
|
|
}
|
2018-05-21 01:56:44 +08:00
|
|
|
break;}
|
|
|
|
|
2018-05-21 00:12:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Node * main_node;
|
2018-05-21 01:56:44 +08:00
|
|
|
float solve(Node * m_node){
|
|
|
|
escape_recursion = false;
|
|
|
|
var_name = "";
|
|
|
|
float x0 = 0.0;
|
|
|
|
float y0 = eval_node(x0,m_node);
|
|
|
|
float x1 = 1.0;
|
|
|
|
float y1 = eval_node(x1,m_node);
|
|
|
|
float x2 = 10.0;
|
|
|
|
float y2 = eval_node(x2,m_node);
|
|
|
|
|
|
|
|
if (isnan(y0) || isnan(y1) || isnan(y2)){
|
|
|
|
return NAN;
|
|
|
|
}
|
|
|
|
else if(strcmp(var_name,"")==0){
|
|
|
|
var_name = "[var]";
|
|
|
|
|
|
|
|
if (y0 == 0.0){
|
|
|
|
printf("%s can be any numbers; the following is just a solution.",
|
|
|
|
var_name);
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
return NAN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
|
|
|
|
float slope1 = (y1-y0) / (x1-x0);
|
|
|
|
float slope2 = (y2-y0) / (x2-x0);
|
|
|
|
|
|
|
|
if (slope1 == slope2){
|
|
|
|
if (slope1 == 0.0){
|
|
|
|
if (y0 == 0){
|
|
|
|
printf("%s can be any numbers; the following is just a solution.",
|
|
|
|
var_name);
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
return NAN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
float ans = -y0 / slope1;
|
|
|
|
return ans;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
printf("Error: the formula is not linear.\n");
|
|
|
|
return NAN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-05-21 00:12:57 +08:00
|
|
|
%}
|
|
|
|
|
|
|
|
%union{
|
|
|
|
float floatVal;
|
|
|
|
int intVal;
|
|
|
|
char * strVal;
|
|
|
|
struct Node *node;
|
|
|
|
}
|
|
|
|
|
|
|
|
%token T_VAR
|
|
|
|
%token T_NUM
|
|
|
|
%token T_ADD T_SUB T_MUL T_DIV T_LPATH T_RPATH T_NEWLINE
|
|
|
|
%left T_ADD T_SUB
|
|
|
|
%left T_MUL T_DIV
|
|
|
|
%left NEG
|
|
|
|
|
|
|
|
%type <floatVal> T_NUM
|
|
|
|
%type <strVal> T_VAR
|
|
|
|
%type <node> E
|
|
|
|
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
2018-05-21 01:56:44 +08:00
|
|
|
S : S E T_NEWLINE { main_node = $2;
|
|
|
|
printf("ANSWER: %s = %f",var_name,solve(main_node));}
|
2018-05-21 00:12:57 +08:00
|
|
|
| {}
|
|
|
|
;
|
|
|
|
|
2018-05-21 01:56:44 +08:00
|
|
|
E : E T_ADD E {Node * op_node = (Node *) malloc(sizeof(Node));
|
|
|
|
*op_node = create_op_node("+");
|
|
|
|
connect_node(op_node,$1,$3);$$ = op_node;}
|
|
|
|
| E T_SUB E {Node * op_node = (Node *) malloc(sizeof(Node));
|
|
|
|
*op_node = create_op_node("-");
|
|
|
|
connect_node(op_node,$1,$3);$$ = op_node;}
|
|
|
|
| E T_MUL E {Node * op_node = (Node *) malloc(sizeof(Node));
|
|
|
|
*op_node = create_op_node("*");
|
|
|
|
connect_node(op_node,$1,$3);$$ = op_node;}
|
|
|
|
| E T_DIV E {Node * op_node = (Node *) malloc(sizeof(Node));
|
|
|
|
*op_node = create_op_node("/");
|
|
|
|
connect_node(op_node,$1,$3);$$ = op_node;}
|
2018-05-21 00:12:57 +08:00
|
|
|
| T_SUB E %prec NEG {
|
|
|
|
Node * op_node = (Node *) malloc(sizeof(Node));
|
|
|
|
Node * zero_node = (Node *) malloc(sizeof(Node));
|
|
|
|
* zero_node = create_val_node(0.0);
|
|
|
|
* op_node = create_op_node("-");
|
|
|
|
connect_node(op_node,zero_node,$2);
|
|
|
|
$$ = op_node;}
|
2018-05-21 01:56:44 +08:00
|
|
|
| T_NUM {Node * val_node = (Node *) malloc(sizeof(Node));
|
|
|
|
* val_node = create_val_node($1);
|
|
|
|
$$ = val_node;}
|
|
|
|
| T_VAR {Node * var_node = (Node *) malloc(sizeof(Node));
|
|
|
|
* var_node = create_var_node($1);
|
|
|
|
$$ = var_node;}
|
2018-05-21 00:12:57 +08:00
|
|
|
| T_LPATH E T_RPATH {$$ = $2;}
|
|
|
|
;
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
int main(){
|
|
|
|
yyin = stdin;
|
|
|
|
do{
|
2018-05-21 01:56:44 +08:00
|
|
|
printf(
|
|
|
|
"A program to solve f(x) = 0 such that f(x) is a 1-var linear function.\n");
|
|
|
|
printf("Please Enter a 1-var linear function: ");
|
2018-05-21 00:12:57 +08:00
|
|
|
yyparse();
|
|
|
|
|
|
|
|
}while(!feof(yyin));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 01:56:44 +08:00
|
|
|
|
|
|
|
void yyerror (const char *msg)
|
|
|
|
{
|
|
|
|
|
|
|
|
fprintf (stderr, "%s\n", msg);
|
|
|
|
}
|