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

📄 actions.cpp

📁 a LALR(1) grammar for C
💻 CPP
字号:
/*****************************************************
File: ACTIONS.CPP    Copyright 1989 by John M. Dlugosz
   the Actions called from the parser
*****************************************************/

#include "usual.hpp"
#include <assert.h>
#include <stream.hpp>
#include "atom.hpp"
#include "node.hpp"
#include "define.hpp"

// #define SHORT return 0    
/* short out actions for testing parser only.
   if something suddenly goes wrong, I can stub
   out all the actions to make sure I'm not walking
   on data somewhere.  */
#define SHORT
   // the normal case.

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

static char last_token[81];

void get_last_token()
{
/* copy last token from scanner into a nul-terminated string */
int len= 80;  //maximum sig. length
extern char *T_beg, *T_end;  //from the scanner
char* source= T_beg;
char* dest= last_token;

//cout << (unsigned)T_beg << "  " << T_end;
//for (int x= 0;  x < 5;  x++)   cout.put(T_beg[x]);

while (len-- && source < T_end) *dest++ = *source++;
*dest= '\0';
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

/* in a declaration, a storage class is the first thing I get.  This starts
   it off.  Then a ConstVol, a StoreType, and a second ConstVol.  The const
   or volatile keyword may appear before or after the type, with equal
   effect.  The two bits are ORed together for the final result.
   After this, I get one or more calls to Declaration.
*/

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

// the type I'm building
struct working_type {
   type_node* this_type;    //the tail
   type_node* root_type;    //the head
   int base_type;
   atom tag_name; // if base_type has a name
   atom name;  //The name of the thing being declared
   int storage_class;
   int const_vol;
   bool isfriend;  //this is declaration of a friend function
   working_type* next;
   enum { is_public, is_protected, is_private } protect_mode;
   type_node* forwarded_class;
   def_node_list* classbody;
   } MainType;

working_type* Tx= &MainType;
/* this is accessed through a pointer because a declarator can be encounted
   while parsing another declarator.  This lets me stack them.  */

static int aggr_form;  //union, struct, class

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

static int const_vol_stack[50];
static int const_vol_stacktop= 0;

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int IsFriend (int x ...)
{
Tx->isfriend= x;
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int ProtectionSpecifier (int x ...)
{
Tx->protect_mode= x;
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int Declaration (int x,...)
{
/* values for x:  1- global or local def.
                  2- parameters
                  3- struct/union list
*/
SHORT;
/* This finishes it off.  A complete declaration has been found. */
if (Tx->forwarded_class) Tx->this_type= Tx->forwarded_class;
else Tx->this_type->stuff_primary (Tx->base_type, Tx->tag_name);
Tx->this_type->flags |= Tx->const_vol;
// build the 'thing' from the type_node and the name.
store_thing (Tx->root_type, Tx->name, Tx->storage_class, x, Tx->isfriend, Tx->protect_mode);
// Tx->root_type->print();
// cout.put('\n');
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int StoreBaseConstVol (int x,...)
{
SHORT;
// the first two calls to ConstVol apply here.
Tx->const_vol =  const_vol_stack[--const_vol_stacktop];
Tx->const_vol |= const_vol_stack[--const_vol_stacktop];
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int StoreType (int x,...)
{
SHORT;
if (x == 13) {
  if (aggr_form == 0) Tx->base_type= 14;
  else {
     Tx->base_type= 13;
     Tx->protect_mode= (aggr_form == 1) ? is_public : is_private;
     }
  type_node* n= named_type_list->search(Tx->tag_name);  //present already?
  if (!n) {  //add it
     n= new type_node;
     n->primary= Tx->base_type;
     n->aggr= Tx->classbody;
     if (Tx->tag_name != -1) {
        n->tag= Tx->tag_name;
        named_type_list->add (n);
        }
     }
  else {  //already present
     // >> check for errors
     }
  Tx->forwarded_class= n;
  }
else {
   Tx->forwarded_class= NULL;
   Tx->base_type= x;
   if (x == 0) Tx->const_vol= 0;  // no call to StoreBaseConstVol made.
   }
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int StoreTag (int x,...)
{
SHORT;
/* called when a struct, union, or enum is parsed. The tag is the last
   token read.  After this call, the StoreType call is made with 'union'
   or whatever.  */
get_last_token();
Tx->tag_name= atoms[last_token];
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int AggrForm (int x, ...)
{
/* is this a class, struct, or union? */
SHORT;
aggr_form= x;
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int StoreStorage (int x,...)
{
SHORT;
/* this is the first thing called */
Tx->storage_class= x;
Tx->tag_name= -1;  //initialize
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int Dname (int x,...)
{
SHORT;
/* if x==1, the last token is the name of a thing being declared.  If
   x==0, there is no name and this is an abstact declarator.  Either
   way, build a type node and store the name.  This overwrites the type 
   node, as it will be the first thing called.  */

if (x) {
   get_last_token();
   Tx->name= atoms[last_token];
   }
Tx->this_type= new type_node;
Tx->root_type= Tx->this_type;
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int TypeModifier (int x,...)
{
SHORT;
/*  1 t()     2 t[]     3 *t     4 &t        */

switch (x) {
   case 1:
      Tx->this_type->primary= type_function;
      // attach parameter list
      Tx->this_type->aggr= completed_def_list;
      break;
   case 2:
      Tx->this_type->primary= type_array;
      // >> attach size
      break;
   case 3:
      Tx->this_type->primary= type_pointer;
      Tx->this_type->flags |= const_vol_stack[--const_vol_stacktop];
      break;
   case 4:
      Tx->this_type->primary= type_reference;
      Tx->this_type->flags |= const_vol_stack[--const_vol_stacktop];
      break;
   }
Tx->this_type->to_what= new type_node;
Tx->this_type= Tx->this_type->to_what;

return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int StoreAggrBody (int x ...)
{
SHORT;
/* this is called after the body of a class is parsed.  If there was
   no body, the parameter is 0 */
if (x) {
   Tx->classbody= completed_def_list;  //finish off type
   // >> check over completed type.
   }
else Tx->classbody= NULL;
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int ConstVol (int x,...)
{
SHORT;
/*  1-const  2-volatile  3-both  */
const_vol_stack[const_vol_stacktop++]= x;
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int ReachType (int x,...)
{
SHORT;
/* 0-default  1-near  2-far */
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int NestedType (int x, ...)
{
SHORT;
working_type* p;
if (x) {  //start nesting
   p= new working_type;
   p->next= Tx;
   Tx= p;
   }
else {  //restore old type
   p= Tx;
   Tx= Tx->next;
   delete p;
   }
parameter_list (x);  //pass on to DEFINE module
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

int AllDoneNow (int x, ...)
{
SHORT;
cout << "parser complete. \n";
for (int loop= 0;  loop < global_stuff.size();  loop++) {
   assert (global_stuff[loop]);
   global_stuff[loop]->print();
   cout.put ('\n');
   cout << global_stuff[loop]->mangled_name();
   cout.put ('\n');
   }
extern void dump_types();
dump_types();
return 0;
}

/* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */

⌨️ 快捷键说明

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