%{ #include #include #include #include "lscan.h" #include "ltree.h" /* extern int error(const char *format, ...); */ void yyerror(const char *s); void generate(tree* t); void gencode(tree* t, int trueLabel, int falseLabel); %} %term ENDL %term NAME /* Name */ %term ICON /* Integer 123, 'a' */ %term LP /* ( */ %term RP /* ) */ %term SM /* ; */ %term CM /* , */ %left LOR %left LAND %left LNOT %left EQUOP RELOP %start f %% f : /* Empty */ | f lexpr ENDL { generate($2.t); release_tree($2.t); } | error ENDL ; lexpr : expr { $$ = $1; } | expr EQUOP expr { tree* node = allocate_node(); node->left = $1.t; node->right = $3.t; node->type = EQUOP_NODE; node->int_value = $2.int_value; $$.t = node; } | expr RELOP expr { tree* node = allocate_node(); node->left = $1.t; node->right = $3.t; node->type = RELOP_NODE; node->int_value = $2.int_value; $$.t = node; } | LP lexpr RP { $$ = $2; } | LNOT lexpr { tree* node = allocate_node(); node->left = $2.t; node->type = LNOT_NODE; $$.t = node; } | lexpr LOR lexpr { tree* node = allocate_node(); node->left = $1.t; node->right = $3.t; node->type = LOR_NODE; $$.t = node; } | lexpr LAND lexpr { tree* node = allocate_node(); node->left = $1.t; node->right = $3.t; node->type = LAND_NODE; $$.t = node; } ; expr : NAME { tree* node = allocate_node(); node->type = NAME_NODE; strcpy(node->name, $1.text_value); $$.t = node; } | ICON { tree* node = allocate_node(); node->type = ICON_NODE; node->int_value = $$.int_value; $$.t = node; } ; %% int main() { yyparse(); return 0; } void yyerror(const char *s) { printf("%s\n", s); } static int label = 100; void generate(tree* t) { int lab; print_tree(t, 0); /* debug printing */ lab = label++; printf("res = FALSE;\n"); gencode(t, 0, lab); printf("res = TRUE;\n"); printf("L%d: ;\n", lab); } /* Generate code for logical expression */ void gencode(tree* t, int trueLabel, int falseLabel) { int node; if (t == NULL) return; node = t->type; switch (node) { case NAME_NODE: { const char* rel = "=="; if (falseLabel == 0) rel = "!="; printf("if (%s %s 0) goto L%d;\n", t->name, rel, trueLabel + falseLabel); break; } case ICON_NODE: { if (falseLabel != 0 && t->int_value == 0) printf("goto L%d;\n", falseLabel); else if (trueLabel != 0 && t->int_value != 0) printf("goto L%d;\n", trueLabel); break; } case LAND_NODE: { if (falseLabel != 0) { gencode(t->left, 0, falseLabel); gencode(t->right, 0, falseLabel); } else { int lab = label++; gencode(t->left, 0, lab); gencode(t->right, trueLabel, 0); printf("L%d: ;\n", lab); } break; } case LOR_NODE: { if (trueLabel != 0) { gencode(t->left, trueLabel, 0); gencode(t->right, trueLabel, 0); } else { int lab = label++; gencode(t->left, lab, 0); gencode(t->right, 0, falseLabel); printf("L%d: ;\n", lab); } break; } case LNOT_NODE: { gencode(t->left, falseLabel, trueLabel); break; } case EQUOP_NODE: case RELOP_NODE: { const char* rel = "??"; if (trueLabel != 0) { switch (t->int_value) { // relation case EQ: rel = "=="; break; case NE: rel = "!="; break; case LT: rel = "<"; break; case LE: rel = "<="; break; case GT: rel = ">"; break; case GE: rel = ">="; break; } printf("if (%s %s ", node_value(t->left), rel); printf("%s) goto L%d;\n", node_value(t->right), trueLabel); } else { switch (t->int_value) { // relation case EQ: rel = "!="; break; // Inverse relation case NE: rel = "=="; break; case LT: rel = ">="; break; case LE: rel = ">"; break; case GT: rel = "<="; break; case GE: rel = "<"; break; } printf("if (%s %s ", node_value(t->left), rel); printf("%s) goto L%d;\n", node_value(t->right), falseLabel); } } /* end of RELOP_NODE */ } /* end of switch */ }