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

📄 intcode.cpp

📁 一个自定义简单脚本引擎的实现代码
💻 CPP
字号:
#include <stdio.h>
#include "symtab.h"
#include "synttree.h"
#include "intcode.h"

// Number: assigns line numbers to this block of intermediate code, starting with ln
void IntInstr::Number (int ln)   {
   IntInstr *num = this;
   while (num != NULL)   {
      num->n = ln++; num = num->next;
   }
}

// Names of the opcodes
char *op_name[] = {
   "OP_NOP", "OP_PUSH", "OP_GETTOP", "OP_DISCARD",
   "OP_PRINT", "OP_INPUT", "OP_JMP", "OP_JMPF",
   "OP_STR_EQUAL", "OP_BOOL_EQUAL", "OP_CONCAT",
   "OP_BOOL2STR", "JUMPTARGET"
};

// Show this block of intermediate code
void IntInstr::Show ()   {
   printf ("%2d: %s ", n, op_name[opcode]);
   if (str)     printf ("%s ", str->name);
   if (target)  printf ("%d", target->n);
   printf ("\n");
   if (next != NULL)   next->Show();
}

// Concatenates two blocks of instructions
IntInstr *Concatenate (IntInstr *blk1, IntInstr *blk2)  {
   IntInstr *search = blk1;
   while (search->next != NULL)   search = search->next;
   search->next = blk2;
   return blk1;
}

// Prefix a jump target to a block; returns the new block
IntInstr *PrefixJT (IntInstr *blk, IntInstr *ref_instr)   {
   IntInstr *jt = new IntInstr;
   jt->opcode = JUMPTARGET;
   jt->target = ref_instr;   // the referring instruction
   jt->next = blk;
   return jt;
}

// Recursively generate intermediate code
IntInstr *GenIntCode (SyntTree tree)  {
   TreeNode *root = tree;
   IntInstr *blk1, *blk2,
            *cond, *jump2else, *thenpart, *jump2end, *elsepart, *endif;

   switch (root->type)  {
   case STMT_LIST:
      blk1 = GenIntCode (root->child[0]);
      blk2 = GenIntCode (root->child[1]);
      Concatenate (blk1, blk2);
      return blk1;
   case EMPTY_STMT:
      return new IntInstr (OP_NOP);
   case EXPR_STMT:
      blk1 = GenIntCode (root->child[0]);
      blk2 = new IntInstr (OP_DISCARD);
      return Concatenate (blk1, blk2);
   case PRINT_STMT:
      blk1 = GenIntCode (root->child[0]);
      blk2 = new IntInstr (OP_PRINT);
      return Concatenate (blk1, blk2);
   case INPUT_STMT:
      return new IntInstr (OP_INPUT, root->symbol);
   case IFTHEN_STMT:
      // First, create the necessary code parts
      cond      = GenIntCode (root->child[0]);
      jump2end  = new IntInstr (OP_JMPF);      // set target below
      thenpart  = GenIntCode (root->child[1]);
      endif     = new IntInstr (JUMPTARGET, jump2end);
      jump2end->target = endif;

      // Now, concatenate them all
      Concatenate (cond, jump2end);
      Concatenate (jump2end, thenpart);
      Concatenate (thenpart, endif);
      return cond;
   case IFTHENELSE_STMT:
      // First, create the necessary code parts
      cond      = GenIntCode (root->child[0]);
      jump2else = new IntInstr (OP_JMPF);      // set target below
      thenpart  = GenIntCode (root->child[1]);
      elsepart  = PrefixJT (GenIntCode (root->child[2]), jump2else);
      jump2else->target = elsepart;
      jump2end  = new IntInstr (OP_JMP);       // set target below
      endif     = new IntInstr (JUMPTARGET, jump2end);
      jump2end->target = endif;

      // Now, concatenate them all
      Concatenate (cond, jump2else);
      Concatenate (jump2else, thenpart);
      Concatenate (thenpart, jump2end);
      Concatenate (jump2end, elsepart);
      Concatenate (elsepart, endif);
      return cond;
   case ERROR_STMT:
      return new IntInstr (OP_NOP);
   case EQUAL_EXPR:
      blk1 = GenIntCode (root->child[0]);
      blk2 = GenIntCode (root->child[1]);
      Concatenate (blk1, blk2);
      if (root->child[0]->rettype == T_STRING)
         return Concatenate (blk1, new IntInstr (OP_STR_EQUAL));
      else
         return Concatenate (blk1, new IntInstr (OP_BOOL_EQUAL));
   case ASSIGN_EXPR:
      blk1 = GenIntCode (root->child[0]);
      blk2 = new IntInstr (OP_GETTOP, root->symbol);
      return Concatenate (blk1, blk2);
   case CONCAT_EXPR:
      blk1 = GenIntCode (root->child[0]);
      blk2 = GenIntCode (root->child[1]);
      Concatenate (blk1, blk2);
      return Concatenate (blk1, new IntInstr (OP_CONCAT));
   case IDENT_EXPR:
   case STR_EXPR:
      return new IntInstr (OP_PUSH, root->symbol);
   case COERCE_TO_STR:
      blk1 = GenIntCode (root->child[0]);
      blk2 = new IntInstr (OP_BOOL2STR);
      return Concatenate (blk1, blk2);
   }
   return new IntInstr (OP_NOP); // shouldn't happen
}

⌨️ 快捷键说明

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