262 lines
6.8 KiB
C++
262 lines
6.8 KiB
C++
// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
|
|
//
|
|
// Declaration of a script's control structures.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include "englookup.h"
|
|
#include "englex.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Statement structures
|
|
|
|
// forward decls and collections
|
|
class Routine;
|
|
typedef Slots<Routine> Routines;
|
|
class Variable;
|
|
typedef Slots<Variable> Variables;
|
|
class ReferenceName;
|
|
typedef Slots<ReferenceName> ReferenceNames;
|
|
class VariableReference;
|
|
typedef Slots<VariableReference> VariableReferences;
|
|
class Statement;
|
|
typedef Slots<Statement> Statements;
|
|
class Value;
|
|
typedef Slots<Value> Values;
|
|
class Call;
|
|
typedef Slots<Call> Calls;
|
|
class ExprBlock;
|
|
typedef Slots<ExprBlock> ExprBlocks;
|
|
class IfBlock;
|
|
typedef Slots<IfBlock> IfBlocks;
|
|
class Assignment;
|
|
typedef Slots<Assignment> Assignments;
|
|
|
|
class Variable
|
|
{
|
|
public:
|
|
Variable(Strings::index _istrIdentifier, DISPID _dispid = DISPID_UNKNOWN) : istrIdentifier(_istrIdentifier), dispid(_dispid) {}
|
|
|
|
Strings::index istrIdentifier;
|
|
DISPID dispid; // this is set to a value other than DISPID_UNKNOWN if the variable is a member of the global dispatch instead of an item in the script itself
|
|
|
|
private:
|
|
friend class SmartRef::Vector<Variable>;
|
|
Variable() {}
|
|
};
|
|
|
|
// Names used in a sequence for dereferencing attributes or function calls.
|
|
// For example, a and b in "a.b" or x and y in "x.y(3)".
|
|
class ReferenceName
|
|
{
|
|
public:
|
|
ReferenceName(Strings::index _istrIdentifier) : istrIdentifier(_istrIdentifier) {}
|
|
|
|
Strings::index istrIdentifier; // -1 is used to end a sequence of names
|
|
|
|
private:
|
|
friend class SmartRef::Vector<ReferenceName>;
|
|
ReferenceName() {}
|
|
};
|
|
|
|
class VariableReference
|
|
{
|
|
public:
|
|
enum kind { _global, _local };
|
|
VariableReference(kind _k, ReferenceNames::index _irname, Variables::index _ivar)
|
|
: k(_k), irname(_irname), ivar(_ivar) {}
|
|
|
|
kind k;
|
|
ReferenceNames::index irname;
|
|
Variables::index ivar; // slot of the first name within (global/local/temporary) variables
|
|
|
|
private:
|
|
friend class SmartRef::Vector<VariableReference>;
|
|
VariableReference() {}
|
|
};
|
|
|
|
class Value
|
|
{
|
|
public:
|
|
// dummy types to differentiate constructors
|
|
enum cons_numvalue {};
|
|
enum cons_strvalue {};
|
|
enum cons_varref {};
|
|
|
|
enum kind { _numvalue, _strvalue, _varref };
|
|
|
|
Value(cons_numvalue e, int iVal) : k(_numvalue) { inumvalue = iVal; }
|
|
Value(cons_strvalue e, Strings::index iStr) : k(_strvalue) { istrvalue = iStr; }
|
|
Value(cons_varref e, VariableReferences::index _ivarref) : k(_varref) { ivarref = _ivarref; }
|
|
|
|
kind k;
|
|
union
|
|
{
|
|
int inumvalue;
|
|
Strings::index istrvalue;
|
|
VariableReferences::index ivarref;
|
|
};
|
|
|
|
private:
|
|
friend class SmartRef::Vector<Value>;
|
|
Value() {}
|
|
};
|
|
|
|
class Call
|
|
{
|
|
public:
|
|
// dummy types to differentiate constructors
|
|
enum cons_global {};
|
|
enum cons_dereferenced {};
|
|
|
|
enum kind { _global, _dereferenced };
|
|
|
|
Call() {} // all fields are set after creation
|
|
|
|
kind k;
|
|
union
|
|
{
|
|
Strings::index istrname; // _global
|
|
VariableReferences::index ivarref; // _dereferenced
|
|
};
|
|
ExprBlocks::index iexprParams; // doubly-terminated list of lists. each parameter is terminated with an _end block and the final parameter is also terminated with a second _end block.
|
|
};
|
|
|
|
class ExprBlock
|
|
{
|
|
public:
|
|
// dummy types to differentiate constructors
|
|
enum cons_end {};
|
|
enum cons_op {};
|
|
enum cons_val {};
|
|
enum cons_call {};
|
|
enum cons_omitted {}; // used only in a routine call, stands for an omitted parameter
|
|
|
|
enum kind { _end = 0, _op, _val, _call, _omitted };
|
|
|
|
// Note: For unary - (negation), TOKEN_sub is used instead of TOKEN_op_minus.
|
|
ExprBlock(cons_end e) : k(_end) {}
|
|
ExprBlock(cons_op e, Token __op) : k(_op) { op = __op; assert(CheckOperatorType(op, true, true, true, false) || op == TOKEN_sub); }
|
|
ExprBlock(cons_val e, Values::index _ival) : k(_val) { ival = _ival; }
|
|
ExprBlock(cons_call e, Calls::index _icall) : k(_call) { icall = _icall; }
|
|
ExprBlock(cons_omitted e) : k(_omitted) {}
|
|
|
|
operator bool() { return k != _end; }
|
|
|
|
kind k;
|
|
|
|
union
|
|
{
|
|
Token op;
|
|
Values::index ival;
|
|
Calls::index icall;
|
|
};
|
|
|
|
private:
|
|
friend class SmartRef::Vector<ExprBlock>;
|
|
friend class SmartRef::Stack<ExprBlock>;
|
|
ExprBlock() {}
|
|
};
|
|
|
|
class Assignment
|
|
{
|
|
public:
|
|
Assignment(bool _fSet, VariableReferences::index _ivarrefLHS, ExprBlocks::index _iexprRHS) : fSet(_fSet), ivarrefLHS(_ivarrefLHS), iexprRHS(_iexprRHS) {}
|
|
|
|
bool fSet;
|
|
VariableReferences::index ivarrefLHS;
|
|
ExprBlocks::index iexprRHS;
|
|
|
|
private:
|
|
friend class SmartRef::Vector<Assignment>;
|
|
Assignment() {}
|
|
};
|
|
|
|
class IfBlock
|
|
{
|
|
public:
|
|
// _end: end of blocks without an 'else'
|
|
// _else: end of blocks with an 'else'
|
|
// _cond: a conditional block, from 'if' (first one) or 'elseif' (later ones)
|
|
enum kind { _end = 0, _else, _cond };
|
|
|
|
IfBlock() : k(_end) {}
|
|
IfBlock(Statements::index _istmtBlock) : k(_else), istmtBlock(_istmtBlock) {}
|
|
IfBlock(ExprBlocks::index _iexprCondition, Statements::index _istmtBlock) : k(_cond), iexprCondition(_iexprCondition), istmtBlock(_istmtBlock) {}
|
|
|
|
kind k;
|
|
ExprBlocks::index iexprCondition; // only used by cond kind
|
|
Statements::index istmtBlock; // not used by end kind
|
|
};
|
|
|
|
class Statement
|
|
{
|
|
public:
|
|
typedef int index;
|
|
|
|
// dummy types to differentiate constructors
|
|
enum cons_end {};
|
|
enum cons_asgn {};
|
|
enum cons_if {};
|
|
enum cons_call {};
|
|
|
|
enum kind { _end = 0, _if, _asgn, _call }; // _end is used as a terminator for a block of statements
|
|
|
|
Statement(cons_end e, int _iLine) : k(_end), iLine(_iLine) {}
|
|
Statement(cons_asgn e, Assignments::index _iasgn, int _iLine) : k(_asgn), iLine(_iLine) { iasgn = _iasgn; }
|
|
Statement(cons_if e, int _iLine) : k(_if), iLine(_iLine) { iif = 0; istmtIfTail = 0; }
|
|
Statement(cons_call e, Calls::index _icall, int _iLine) : k(_call), iLine(_iLine) { icall = _icall; }
|
|
|
|
operator bool() { return k != _end; }
|
|
|
|
kind k;
|
|
int iLine;
|
|
union
|
|
{
|
|
Assignments::index iasgn;
|
|
struct
|
|
{
|
|
IfBlocks::index iif;
|
|
Statements::index istmtIfTail;
|
|
};
|
|
Calls::index icall;
|
|
};
|
|
|
|
private:
|
|
friend class SmartRef::Vector<Statement>;
|
|
Statement() {}
|
|
};
|
|
|
|
class Routine
|
|
{
|
|
public:
|
|
Routine(Strings::index _istrIdentifier) : istrIdentifier(_istrIdentifier), istmtBody(0), ivarNextLocal(0) {}
|
|
|
|
Strings::index istrIdentifier;
|
|
Statements::index istmtBody;
|
|
Variables::index ivarNextLocal; // while parsing, this is the next local slot to use. by runtime, this as the total number of local slots needed by the routine.
|
|
|
|
private:
|
|
friend class SmartRef::Vector<Routine>;
|
|
Routine() {}
|
|
};
|
|
|
|
class Script
|
|
{
|
|
public:
|
|
Script() {}
|
|
|
|
Routines routines;
|
|
Variables globals;
|
|
Strings strings;
|
|
Statements statements;
|
|
ReferenceNames rnames;
|
|
VariableReferences varrefs;
|
|
Values vals;
|
|
Calls calls;
|
|
ExprBlocks exprs;
|
|
IfBlocks ifs;
|
|
Assignments asgns;
|
|
};
|