📄 actions.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 + -