This commit is contained in:
Christoph Oelckers 2016-03-21 01:31:32 +01:00
commit 904a027bd2
19 changed files with 1780 additions and 1207 deletions

View file

@ -758,15 +758,11 @@ else()
endif()
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y .
COMMAND lemon xlat_parser.y
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND lemon -C${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y
DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/xlat/xlat_parser.y )
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon .
COMMAND lemon zcc-parse.lemon
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND lemon -C${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon
DEPENDS lemon ${CMAKE_CURRENT_SOURCE_DIR}/zscript/zcc-parse.lemon )
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h
@ -1515,5 +1511,5 @@ source_group("Shared Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_sh
source_group("Versioning" FILES version.h win32/zdoom.rc)
source_group("Win32 Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/win32/.+")
source_group("Xlat" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/xlat/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c ${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.h)
source_group("ZScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/zscript/.+")
source_group("ZScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/zscript/.+" FILES ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.c ${CMAKE_CURRENT_BINARY_DIR}/zcc-parse.h)
source_group("Source Files" FILES ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h sc_man_scanner.re)

View file

@ -2711,6 +2711,7 @@ END_POINTERS
IMPLEMENT_POINTY_CLASS(PSymbolVMFunction)
DECLARE_POINTER(Function)
END_POINTERS
IMPLEMENT_CLASS(PSymbolTreeNode)
//==========================================================================
//
@ -2773,6 +2774,22 @@ PSymbol *PSymbolTable::FindSymbol (FName symname, bool searchparents) const
return value != NULL ? *value : NULL;
}
PSymbol *PSymbolTable::FindSymbolInTable(FName symname, PSymbolTable *&symtable)
{
PSymbol * const *value = Symbols.CheckKey(symname);
if (value == NULL)
{
if (ParentSymbolTable != NULL)
{
return ParentSymbolTable->FindSymbolInTable(symname, symtable);
}
symtable = NULL;
return NULL;
}
symtable = this;
return *value;
}
PSymbol *PSymbolTable::AddSymbol (PSymbol *sym)
{
// Symbols that already exist are not inserted.
@ -2783,3 +2800,19 @@ PSymbol *PSymbolTable::AddSymbol (PSymbol *sym)
Symbols.Insert(sym->SymbolName, sym);
return sym;
}
PSymbol *PSymbolTable::ReplaceSymbol(PSymbol *newsym)
{
// If a symbol with a matching name exists, take its place and return it.
PSymbol **symslot = Symbols.CheckKey(newsym->SymbolName);
if (symslot != NULL)
{
PSymbol *oldsym = *symslot;
*symslot = newsym;
return oldsym;
}
// Else, just insert normally and return NULL since there was no
// symbol to replace.
Symbols.Insert(newsym->SymbolName, newsym);
return NULL;
}

View file

@ -67,6 +67,18 @@ public:
PSymbolType() : PSymbol(NAME_None) {}
};
// A symbol for a compiler tree node ----------------------------------------
class PSymbolTreeNode : public PSymbol
{
DECLARE_CLASS(PSymbolTreeNode, PSymbol);
public:
struct ZCC_NamedNode *Node;
PSymbolTreeNode(FName name, struct ZCC_NamedNode *node) : PSymbol(name), Node(node) {}
PSymbolTreeNode() : PSymbol(NAME_None) {}
};
// A symbol table -----------------------------------------------------------
struct PSymbolTable
@ -85,11 +97,19 @@ struct PSymbolTable
// as well.
PSymbol *FindSymbol (FName symname, bool searchparents) const;
// Like FindSymbol with searchparents set true, but also returns the
// specific symbol table the symbol was found in.
PSymbol *FindSymbolInTable(FName symname, PSymbolTable *&symtable);
// Places the symbol in the table and returns a pointer to it or NULL if
// a symbol with the same name is already in the table. This symbol is
// not copied and will be freed when the symbol table is destroyed.
PSymbol *AddSymbol (PSymbol *sym);
// Similar to AddSymbol but always succeeds. Returns the symbol that used
// to be in the table with this name, if any.
PSymbol *ReplaceSymbol(PSymbol *sym);
// Frees all symbols from this table.
void ReleaseSymbols();

View file

@ -28,8 +28,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkelMissile)
return 0;
A_FaceTarget (self);
missile = P_SpawnMissileZ (self, self->Z() + 48*FRACUNIT,
self->target, PClass::FindActor("RevenantTracer"));
self->AddZ(16*FRACUNIT);
missile = P_SpawnMissile (self, self->target, PClass::FindActor("RevenantTracer"));
self->AddZ(-16*FRACUNIT);
if (missile != NULL)
{

View file

@ -30,7 +30,7 @@ void AdjustPlayerAngle (AActor *pmo, FTranslatedLineTarget *t)
angle_t angle;
int difference;
angle = t->angleFromSource;
angle = pmo->AngleTo(t->linetarget);
difference = (int)angle - (int)pmo->angle;
if (abs(difference) > MAX_ANGLE_ADJUST)
{

View file

@ -710,7 +710,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnFizzle)
{
PARAM_ACTION_PROLOGUE;
fixed_t dist = 5*FRACUNIT;
fixed_t speed = self->Speed;
fixed_t speed = self->Speed >> FRACBITS;
angle_t rangle;
AActor *mo;
int ix;

View file

@ -143,15 +143,15 @@ void DEarthquake::Tick ()
angle_t an = victim->angle + ANGLE_1*pr_quake();
if (m_IntensityX == m_IntensityY)
{ // Thrust in a circle
P_ThrustMobj (victim, an, m_IntensityX << (FRACBITS-1));
P_ThrustMobj (victim, an, m_IntensityX/2);
}
else
{ // Thrust in an ellipse
an >>= ANGLETOFINESHIFT;
// So this is actually completely wrong, but it ought to be good
// enough. Otherwise, I'd have to use tangents and square roots.
victim->vel.x += FixedMul(m_IntensityX << (FRACBITS-1), finecosine[an]);
victim->vel.y += FixedMul(m_IntensityY << (FRACBITS-1), finesine[an]);
victim->vel.x += FixedMul(m_IntensityX/2, finecosine[an]);
victim->vel.y += FixedMul(m_IntensityY/2, finesine[an]);
}
}
}

View file

@ -4940,7 +4940,7 @@ bool P_TalkFacing(AActor *player)
if (t.linetarget != NULL)
{
if (t.linetarget->health > 0 && // Dead things can't talk.
t.linetarget->flags4 & MF4_INCOMBAT && // Fighting things don't talk either.
!(t.linetarget->flags4 & MF4_INCOMBAT) && // Fighting things don't talk either.
t.linetarget->Conversation != NULL)
{
// Give the NPC a chance to play a brief animation

View file

@ -109,6 +109,18 @@ CUSTOM_CVAR (Float, snd_waterlp, 250, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
}
}
CUSTOM_CVAR (Int, snd_streambuffersize, 64, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self < 16)
{
self = 16;
}
else if (self > 1024)
{
self = 1024;
}
}
#ifndef NO_FMOD
#if FMOD_VERSION < 0x43400
#define FMOD_OPENSTATE_PLAYING FMOD_OPENSTATE_STREAMING
@ -1168,9 +1180,7 @@ bool FMODSoundRenderer::Init()
}
Sys->set3DSettings(0.5f, 96.f, 1.f);
Sys->set3DRolloffCallback(RolloffCallback);
// The default is 16k, which periodically starves later FMOD versions
// when streaming FLAC files.
Sys->setStreamBufferSize(64*1024, FMOD_TIMEUNIT_RAWBYTES);
Sys->setStreamBufferSize(snd_streambuffersize * 1024, FMOD_TIMEUNIT_RAWBYTES);
snd_sfxvolume.Callback ();
return true;
}

View file

@ -1148,7 +1148,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, i
sc.MustGetStringName(",");
sc.MustGetNumber();
b = sc.Number;
sc.MustGetStringName(",");
//sc.MustGetStringName(","); This was never supposed to be here.
part.Blend = MAKERGB(r, g, b);
}
// Blend.a may never be 0 here.

View file

@ -202,10 +202,7 @@ special_args(Z) ::= . /* empty */
Z.args[3] = 0;
Z.args[4] = 0;
}
special_args(Z) ::= multi_special_arg(A).
{
Z = A;
}
special_args(Z) ::= multi_special_arg(Z).
//==========================================================================
//

View file

@ -281,7 +281,7 @@ static void PrintClass(FLispString &out, ZCC_TreeNode *node)
ZCC_Class *cnode = (ZCC_Class *)node;
out.Break();
out.Open("class");
out.AddName(cnode->ClassName);
out.AddName(cnode->NodeName);
PrintNodes(out, cnode->ParentName);
PrintNodes(out, cnode->Replaces);
out.AddHex(cnode->Flags);
@ -294,7 +294,7 @@ static void PrintStruct(FLispString &out, ZCC_TreeNode *node)
ZCC_Struct *snode = (ZCC_Struct *)node;
out.Break();
out.Open("struct");
out.AddName(snode->StructName);
out.AddName(snode->NodeName);
PrintNodes(out, snode->Body, false, true);
out.Close();
}
@ -304,7 +304,7 @@ static void PrintEnum(FLispString &out, ZCC_TreeNode *node)
ZCC_Enum *enode = (ZCC_Enum *)node;
out.Break();
out.Open("enum");
out.AddName(enode->EnumName);
out.AddName(enode->NodeName);
PrintBuiltInType(out, enode->EnumType);
out.Add(enode->Elements == NULL ? "nil" : "...", 3);
out.Close();
@ -733,7 +733,7 @@ static void PrintConstantDef(FLispString &out, ZCC_TreeNode *node)
ZCC_ConstantDef *dnode = (ZCC_ConstantDef *)node;
out.Break();
out.Open("constant-def");
out.AddName(dnode->Name);
out.AddName(dnode->NodeName);
PrintNodes(out, dnode->Value, false);
out.Close();
}

View file

@ -90,7 +90,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line)
for (int j = 1; j < YYERRORSYMBOL; ++j)
{
int k = i + j;
if (k >= 0 && k < YY_SZ_ACTTAB && yy_lookahead[k] == j)
if (k >= 0 && k < YY_ACTTAB_COUNT && yy_lookahead[k] == j)
{
expecting << (expecting.IsEmpty() ? "Expecting " : " or ") << ZCCTokenName(j);
}
@ -128,15 +128,15 @@ main ::= translation_unit(A). { stat->TopNode = A; stat->sc.ScriptMessage("Parse
%type translation_unit {ZCC_TreeNode *}
translation_unit(X) ::= . { X = NULL; }
translation_unit(X) ::= translation_unit(A) external_declaration(B). { SAFE_APPEND(A,B); X = A; }
translation_unit(X) ::= translation_unit(A) EOF. { X = A; }
translation_unit(X) ::= translation_unit(X) external_declaration(B). { SAFE_APPEND(X,B); }
translation_unit(X) ::= translation_unit(X) EOF.
translation_unit(X) ::= error. { X = NULL; }
%type external_declaration {ZCC_TreeNode *}
external_declaration(X) ::= class_definition(A). { X = A; }
external_declaration(X) ::= struct_def(A). { X = A; }
external_declaration(X) ::= enum_def(A). { X = A; }
external_declaration(X) ::= const_def(A). { X = A; }
external_declaration(X) ::= class_definition(A). { X = A; /*X-overwrites-A*/ }
external_declaration(X) ::= struct_def(A). { X = A; /*X-overwrites-A*/ }
external_declaration(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ }
external_declaration(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ }
/* Optional bits. */
opt_semicolon ::= .
@ -150,10 +150,7 @@ opt_expr(X) ::= .
{
X = NULL;
}
opt_expr(X) ::= expr(A).
{
X = A;
}
opt_expr(X) ::= expr(X).
/************ Class Definition ************/
@ -168,13 +165,13 @@ opt_expr(X) ::= expr(A).
class_definition(X) ::= class_head(A) class_body(B).
{
A->Body = B;
X = A;
X = A; /*X-overwrites-A*/
}
class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C).
{
NEW_AST_NODE(Class,head,T);
head->ClassName = A.Name();
head->NodeName = A.Name();
head->ParentName = B;
head->Flags = C.Flags;
head->Replaces = C.Replaces;
@ -183,7 +180,7 @@ class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C).
%type class_ancestry{ZCC_Identifier *}
class_ancestry(X) ::= . { X = NULL; }
class_ancestry(X) ::= COLON dottable_id(A). { X = A; }
class_ancestry(X) ::= COLON dottable_id(A). { X = A; /*X-overwrites-A*/ }
%type class_flags{ClassFlagsBlock}
class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; }
@ -207,7 +204,7 @@ dottable_id(X) ::= dottable_id(A) DOT IDENTIFIER(B).
NEW_AST_NODE(Identifier,id2,A);
id2->Id = B.Name();
A->AppendSibling(id2);
X = A;
X = A; /*X-overwrites-A*/
}
/*------ Class Body ------*/
@ -220,23 +217,23 @@ dottable_id(X) ::= dottable_id(A) DOT IDENTIFIER(B).
// * constants
// * defaults
class_body(X) ::= SEMICOLON class_innards(A) EOF. { X = A; }
class_body(X) ::= LBRACE class_innards(A) RBRACE. { X = A; }
class_body(X) ::= SEMICOLON class_innards(A) EOF. { X = A; /*X-overwrites-A*/ }
class_body(X) ::= LBRACE class_innards(A) RBRACE. { X = A; /*X-overwrites-A*/ }
class_innards(X) ::= . { X = NULL; }
class_innards(X) ::= class_innards(A) class_member(B). { SAFE_APPEND(A,B); X = A; }
class_innards(X) ::= class_innards(X) class_member(B). { SAFE_APPEND(X,B); }
%type struct_def{ZCC_Struct *}
%type enum_def {ZCC_Enum *}
%type states_def {ZCC_States *}
%type const_def {ZCC_ConstantDef *}
class_member(X) ::= declarator(A). { X = A; }
class_member(X) ::= enum_def(A). { X = A; }
class_member(X) ::= struct_def(A). { X = A; }
class_member(X) ::= states_def(A). { X = A; }
class_member(X) ::= default_def(A). { X = A; }
class_member(X) ::= const_def(A). { X = A; }
class_member(X) ::= declarator(A). { X = A; /*X-overwrites-A*/ }
class_member(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ }
class_member(X) ::= struct_def(A). { X = A; /*X-overwrites-A*/ }
class_member(X) ::= states_def(A). { X = A; /*X-overwrites-A*/ }
class_member(X) ::= default_def(A). { X = A; /*X-overwrites-A*/ }
class_member(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ }
/*----- Struct Definition -----*/
/* Structs can define variables and enums. */
@ -248,28 +245,28 @@ class_member(X) ::= const_def(A). { X = A; }
struct_def(X) ::= STRUCT(T) IDENTIFIER(A) LBRACE opt_struct_body(B) RBRACE opt_semicolon.
{
NEW_AST_NODE(Struct,def,T);
def->StructName = A.Name();
def->NodeName = A.Name();
def->Body = B;
X = def;
}
opt_struct_body(X) ::= . { X = NULL; }
opt_struct_body(X) ::= struct_body(A). { X = A; }
opt_struct_body(X) ::= struct_body(X).
struct_body(X) ::= error. { X = NULL; }
struct_body(X) ::= struct_member(A). { X = A; }
struct_body(X) ::= struct_member(A) struct_body(B). { X = A; A->AppendSibling(B); }
struct_body(X) ::= struct_member(X).
struct_body(X) ::= struct_member(A) struct_body(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); }
struct_member(X) ::= declarator_no_fun(A). { X = A; }
struct_member(X) ::= enum_def(A). { X = A; }
struct_member(X) ::= const_def(A). { X = A; }
struct_member(X) ::= declarator_no_fun(A). { X = A; /*X-overwrites-A*/ }
struct_member(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ }
struct_member(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ }
/*----- Constant Definition ------*/
/* Like UnrealScript, a constant's type is implied by its value's type. */
const_def(X) ::= CONST(T) IDENTIFIER(A) EQ expr(B) SEMICOLON.
{
NEW_AST_NODE(ConstantDef,def,T);
def->Name = A.Name();
def->NodeName = A.Name();
def->Value = B;
def->Symbol = NULL;
X = def;
@ -286,7 +283,7 @@ const_def(X) ::= CONST(T) IDENTIFIER(A) EQ expr(B) SEMICOLON.
enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRACE(U) opt_semicolon.
{
NEW_AST_NODE(Enum,def,T);
def->EnumName = A.Name();
def->NodeName = A.Name();
def->EnumType = (EZCCBuiltinType)B.Int;
def->Elements = C;
@ -324,7 +321,7 @@ enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRAC
NEW_INTCONST_NODE(one, TypeSInt32, 1, T);
NEW_AST_NODE(ExprID, label, node);
label->Operation = PEX_ID;
label->Identifier = prev->Name;
label->Identifier = prev->NodeName;
label->Type = NULL;
BINARY_EXPR(label, one, PEX_Add);
@ -343,19 +340,19 @@ enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRAC
}
enum_type(X) ::= . { X.Int = ZCC_IntAuto; X.SourceLoc = stat->sc.GetMessageLine(); }
enum_type(X) ::= COLON int_type(A). { X = A; }
enum_type(X) ::= COLON int_type(A). { X = A; /*X-overwrites-A*/ }
enum_list(X) ::= error. { X = NULL; }
enum_list(X) ::= enumerator(A). { X = A; }
enum_list(X) ::= enum_list(A) COMMA enumerator(B). { X = A; A->AppendSibling(B); }
enum_list(X) ::= enumerator(X).
enum_list(X) ::= enum_list(A) COMMA enumerator(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); }
opt_enum_list(X) ::= . { X = NULL; }
opt_enum_list(X) ::= enum_list(A) opt_comma. { X = A; }
opt_enum_list(X) ::= enum_list(X) opt_comma.
enumerator(X) ::= IDENTIFIER(A).
{
NEW_AST_NODE(ConstantDef,node,A);
node->Name = A.Name();
node->NodeName = A.Name();
node->Value = NULL;
node->Symbol = NULL;
X = node;
@ -363,7 +360,7 @@ enumerator(X) ::= IDENTIFIER(A).
enumerator(X) ::= IDENTIFIER(A) EQ expr(B). /* Expression must be constant. */
{
NEW_AST_NODE(ConstantDef,node,A);
node->Name = A.Name();
node->NodeName = A.Name();
node->Value = B;
node->Symbol = NULL;
X = node;
@ -405,9 +402,9 @@ scanner_mode ::= . { stat->sc.SetStateMode(true); }
states_body(X) ::= . { X = NULL; }
states_body(X) ::= error. { X = NULL; }
states_body(X) ::= states_body(A) state_line(B). { SAFE_APPEND(A,B); X = A; }
states_body(X) ::= states_body(A) state_label(B). { SAFE_APPEND(A,B); X = A; }
states_body(X) ::= states_body(A) state_flow(B). { SAFE_APPEND(A,B); X = A; }
states_body(X) ::= states_body(X) state_line(B). { SAFE_APPEND(X,B); }
states_body(X) ::= states_body(X) state_label(B). { SAFE_APPEND(X,B); }
states_body(X) ::= states_body(X) state_flow(B). { SAFE_APPEND(X,B); }
state_label(X) ::= NWS(A) COLON.
{
@ -416,7 +413,7 @@ state_label(X) ::= NWS(A) COLON.
X = label;
}
state_flow(X) ::= state_flow_type(A) scanner_mode SEMICOLON. { X = A; }
state_flow(X) ::= state_flow_type(X) scanner_mode SEMICOLON.
state_flow_type(X) ::= STOP(A). { NEW_AST_NODE(StateStop, flow, A); X = flow; }
state_flow_type(X) ::= WAIT(A). { NEW_AST_NODE(StateWait, flow, A); X = flow; }
@ -431,7 +428,7 @@ state_flow_type(X) ::= GOTO(T) dottable_id(A) state_goto_offset(B).
}
state_goto_offset(X) ::= . { X = NULL; }
state_goto_offset(X) ::= PLUS expr(A). { X = A; } /* Must evaluate to a non-negative integer constant. */
state_goto_offset(X) ::= PLUS expr(A). { X = A; /*X-overwrites-A*/ } /* Must evaluate to a non-negative integer constant. */
state_line(X) ::= NWS(A) NWS(B) expr state_opts(C) state_action(D).
{
@ -457,21 +454,21 @@ state_line(X) ::= NWS(A) NWS(B) expr state_opts(C) state_action(D).
}
state_opts(X) ::= . { StateOpts opts; opts.Zero(); X = opts; }
state_opts(X) ::= state_opts(A) BRIGHT. { A.Bright = true; X = A; }
state_opts(X) ::= state_opts(A) FAST. { A.Fast = true; X = A; }
state_opts(X) ::= state_opts(A) SLOW. { A.Slow = true; X = A; }
state_opts(X) ::= state_opts(A) NODELAY. { A.NoDelay = true; X = A; }
state_opts(X) ::= state_opts(A) CANRAISE. { A.CanRaise = true; X = A; }
state_opts(X) ::= state_opts(A) OFFSET LPAREN expr(B) COMMA expr(C) RPAREN. { A.Offset = B; B->AppendSibling(C); X = A; }
state_opts(X) ::= state_opts(A) LIGHT LPAREN light_list RPAREN. { X = A; } ///FIXME: GZDoom would want to know this
state_opts(X) ::= state_opts(A) BRIGHT. { A.Bright = true; X = A; /*X-overwrites-A*/ }
state_opts(X) ::= state_opts(A) FAST. { A.Fast = true; X = A; /*X-overwrites-A*/ }
state_opts(X) ::= state_opts(A) SLOW. { A.Slow = true; X = A; /*X-overwrites-A*/ }
state_opts(X) ::= state_opts(A) NODELAY. { A.NoDelay = true; X = A; /*X-overwrites-A*/ }
state_opts(X) ::= state_opts(A) CANRAISE. { A.CanRaise = true; X = A; /*X-overwrites-A*/ }
state_opts(X) ::= state_opts(A) OFFSET LPAREN expr(B) COMMA expr(C) RPAREN. { A.Offset = B; B->AppendSibling(C); X = A; /*X-overwrites-A*/ }
state_opts(X) ::= state_opts(A) LIGHT LPAREN light_list RPAREN. { X = A; /*X-overwrites-A*/ } ///FIXME: GZDoom would want to know this
light_list ::= STRCONST.
light_list ::= light_list COMMA STRCONST.
/* A state action can be either a compound statement or a single action function call. */
state_action(X) ::= LBRACE statement_list(A) scanner_mode RBRACE. { X = A; }
state_action(X) ::= LBRACE statement_list(A) scanner_mode RBRACE. { X = A; /*X-overwrites-A*/ }
state_action(X) ::= LBRACE error scanner_mode RBRACE. { X = NULL; }
state_action(X) ::= state_call(A) scanner_mode SEMICOLON. { X = A; }
state_action(X) ::= state_call(A) scanner_mode SEMICOLON. { X = A; /*X-overwrites-A*/ }
state_call(X) ::= . { X = NULL; }
state_call(X) ::= IDENTIFIER(A) state_call_params(B).
@ -488,11 +485,11 @@ state_call(X) ::= IDENTIFIER(A) state_call_params(B).
}
state_call_params(X) ::= . { X = NULL; }
state_call_params(X) ::= LPAREN func_expr_list(A) RPAREN. { X = A; }
state_call_params(X) ::= LPAREN func_expr_list(A) RPAREN. { X = A; /*X-overwrites-A*/ }
/* Definition of a default class instance. */
%type default_def {ZCC_CompoundStmt *}
default_def(X) ::= DEFAULT compound_statement(A). { X = A; }
default_def(X) ::= DEFAULT compound_statement(A). { X = A; /*X-overwrites-A*/ }
/* Type names */
%type type_name {ZCC_BasicType *}
@ -505,7 +502,7 @@ int_type(X) ::= INT(T). { X.Int = ZCC_SInt32; X.SourceLoc = T.SourceLoc; }
int_type(X) ::= UINT(T). { X.Int = ZCC_UInt32; X.SourceLoc = T.SourceLoc; }
type_name1(X) ::= BOOL(T). { X.Int = ZCC_Bool; X.SourceLoc = T.SourceLoc; }
type_name1(X) ::= int_type(A). { X = A; }
type_name1(X) ::= int_type(X).
type_name1(X) ::= FLOAT(T). { X.Int = ZCC_FloatAuto; X.SourceLoc = T.SourceLoc; }
type_name1(X) ::= DOUBLE(T). { X.Int = ZCC_Float64; X.SourceLoc = T.SourceLoc; }
type_name1(X) ::= STRING(T). { X.Int = ZCC_String; X.SourceLoc = T.SourceLoc; }
@ -540,6 +537,7 @@ type_name(X) ::= DOT dottable_id(A).
* (Well, actually, I'm not sure if 4D ones are going to happen
* straight away.)
*/
%token_class intconst INTCONST|UINTCONST.
vector_size(X) ::= . { X.Int = ZCC_Vector3; X.SourceLoc = stat->sc.GetMessageLine(); }
vector_size(X) ::= LT intconst(A) GT.
{
@ -554,8 +552,6 @@ vector_size(X) ::= LT intconst(A) GT.
}
X.SourceLoc = A.SourceLoc;
}
intconst(X) ::= INTCONST(A). { X = A; }
intconst(X) ::= UINTCONST(A). { X = A; }
/* Type names can also be used as identifiers in contexts where type names
* are not normally allowed. */
@ -594,19 +590,19 @@ aggregate_type(X) ::= CLASS(T) class_restrictor(A). /* class<type> */
X = cls;
}
class_restrictor(X) ::= . { X = NULL; }
class_restrictor(X) ::= LT dottable_id(A) GT. { X = A; }
class_restrictor(X) ::= LT dottable_id(A) GT. { X = A; /*X-overwrites-A*/ }
type(X) ::= type_name(A). { X = A; A->ArraySize = NULL; }
type(X) ::= aggregate_type(A). { X = A; A->ArraySize = NULL; }
type(X) ::= type_name(A). { X = A; /*X-overwrites-A*/ X->ArraySize = NULL; }
type(X) ::= aggregate_type(A). { X = A; /*X-overwrites-A*/ X->ArraySize = NULL; }
type_or_array(X) ::= type(A). { X = A; }
type_or_array(X) ::= type(A) array_size(B). { X = A; A->ArraySize = B; }
type_or_array(X) ::= type(X).
type_or_array(X) ::= type(A) array_size(B). { X = A; /*X-overwrites-A*/ X->ArraySize = B; }
type_list(X) ::= type_or_array(A). { X = A; }/* A comma-separated list of types */
type_list(X) ::= type_list(A) COMMA type_or_array(B). { X = A; A->AppendSibling(B); }
type_list(X) ::= type_or_array(X). /* A comma-separated list of types */
type_list(X) ::= type_list(A) COMMA type_or_array(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); }
type_list_or_void(X) ::= VOID. { X = NULL; }
type_list_or_void(X) ::= type_list(A). { X = A; }
type_list_or_void(X) ::= type_list(X).
array_size_expr(X) ::= LBRACKET opt_expr(A) RBRACKET.
{
@ -622,14 +618,11 @@ array_size_expr(X) ::= LBRACKET opt_expr(A) RBRACKET.
X = A;
}
}
array_size(X) ::= array_size_expr(A).
{
X = A;
}
array_size(X) ::= array_size_expr(X).
array_size(X) ::= array_size(A) array_size_expr(B).
{
A->AppendSibling(B);
X = A;
X = A; /*X-overwrites-A*/
}
%type variables_or_function {VarOrFun}
@ -738,14 +731,11 @@ variable_name(X) ::= IDENTIFIER(A) array_size(B).
X = var;
}
variable_list(X) ::= variable_name(A).
{
X = A;
}
variable_list(X) ::= variable_name(X).
variable_list(X) ::= variable_list(A) COMMA variable_name(B).
{
A->AppendSibling(B);
X = A;
X = A; /*X-overwrites-A*/
}
decl_flags(X) ::= . { X.Int = 0; X.SourceLoc = 0; }
@ -764,7 +754,7 @@ func_const(X) ::= . { X.Int = 0; X.SourceLoc = stat->sc.GetMessageLine();
func_const(X) ::= CONST(T). { X.Int = ZCC_FuncConst; X.SourceLoc = T.SourceLoc; }
opt_func_body(X) ::= SEMICOLON. { X = NULL; }
opt_func_body(X) ::= function_body(A). { X = A; }
opt_func_body(X) ::= function_body(X).
%type func_params {ZCC_FuncParamDecl *}
%type func_param_list {ZCC_FuncParamDecl *}
@ -772,10 +762,10 @@ opt_func_body(X) ::= function_body(A). { X = A; }
func_params(X) ::= . /* empty */ { X = NULL; }
func_params(X) ::= VOID. { X = NULL; }
func_params(X) ::= func_param_list(A). { X = A; }
func_params(X) ::= func_param_list(X).
func_param_list(X) ::= func_param(A). { X = A; }
func_param_list(X) ::= func_param_list(A) COMMA func_param(B). { X = A; A->AppendSibling(B); }
func_param_list(X) ::= func_param(X).
func_param_list(X) ::= func_param_list(A) COMMA func_param(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); }
func_param(X) ::= func_param_flags(A) type(B) IDENTIFIER(C).
{
@ -819,10 +809,7 @@ primary(X) ::= SUPER(T).
expr->Type = NULL;
X = expr;
}
primary(X) ::= constant(A).
{
X = A;
}
primary(X) ::= constant(A). { X = A; /*X-overwrites-A*/ }
primary(X) ::= SELF(T).
{
NEW_AST_NODE(Expression, expr, T);
@ -832,7 +819,7 @@ primary(X) ::= SELF(T).
}
primary(X) ::= LPAREN expr(A) RPAREN.
{
X = A;
X = A; /*X-overwrites-A*/
}
primary ::= LPAREN error RPAREN.
primary(X) ::= primary(A) LPAREN func_expr_list(B) RPAREN. [DOT] // Function call
@ -881,10 +868,7 @@ primary(X) ::= SCOPE primary(B).
*/
/*----- Unary Expressions -----*/
unary_expr(X) ::= primary(A).
{
X = A;
}
unary_expr(X) ::= primary(X).
unary_expr(X) ::= SUB unary_expr(A). [UNARY]
{
ZCC_ExprConstant *con = static_cast<ZCC_ExprConstant *>(A);
@ -959,10 +943,7 @@ unary_expr(X) ::= ALIGNOF unary_expr(A). [UNARY]
/*----- Binary Expressions -----*/
expr(X) ::= unary_expr(A).
{
X = A;
}
expr(X) ::= unary_expr(X).
expr(X) ::= expr(A) ADD expr(B). /* a + b */
{
BINARY_EXPR(A,B,PEX_Add);
@ -1118,14 +1099,11 @@ expr(X) ::= expr(A) QUESTION expr(B) COLON expr(C).
%type expr_list{ZCC_Expression *}
expr_list(X) ::= expr(A).
{
X = A;
}
expr_list(X) ::= expr(X).
expr_list(X) ::= expr_list(A) COMMA expr(B).
{
X = A;
A->AppendSibling(B);
X = A; /*X-overwrites-A*/
X->AppendSibling(B);
}
/*----- Function argument lists -----*/
@ -1137,10 +1115,7 @@ expr_list(X) ::= expr_list(A) COMMA expr(B).
%type func_expr_item{ZCC_FuncParm *}
%type named_expr{ZCC_FuncParm *}
func_expr_list(X) ::= func_expr_item(A).
{
X = A;
}
func_expr_list(X) ::= func_expr_item(X).
func_expr_list(X) ::= func_expr_list(A) COMMA(T) func_expr_item(B).
{
// Omitted parameters still need to appear as nodes in the list.
@ -1158,18 +1133,15 @@ func_expr_list(X) ::= func_expr_list(A) COMMA(T) func_expr_item(B).
nil_b->Label = NAME_None;
B = nil_b;
}
X = A;
A->AppendSibling(B);
X = A; /*X-overwrites-A*/
X->AppendSibling(B);
}
func_expr_item(X) ::= .
{
X = NULL;
}
func_expr_item(X) ::= named_expr(A).
{
X = A;
}
func_expr_item(X) ::= named_expr(X).
named_expr(X) ::= IDENTIFIER(A) COLON expr(B).
{
@ -1208,10 +1180,7 @@ string_constant(X) ::= string_constant(A) STRCONST(B).
X = strconst;
}
constant(X) ::= string_constant(A).
{
X = A;
}
constant(X) ::= string_constant(X).
constant(X) ::= INTCONST(A).
{
NEW_INTCONST_NODE(intconst, TypeSInt32, A.Int, A);
@ -1251,18 +1220,18 @@ constant(X) ::= TRUE(A).
/************ Statements ************/
function_body(X) ::= compound_statement(A). { X = A; }
function_body(X) ::= compound_statement(X).
%type statement{ZCC_Statement *}
statement(X) ::= SEMICOLON. { X = NULL; }
statement(X) ::= labeled_statement(A). { X = A; }
statement(X) ::= compound_statement(A). { X = A; }
statement(X) ::= expression_statement(A) SEMICOLON. { X = A; }
statement(X) ::= selection_statement(A). { X = A; }
statement(X) ::= iteration_statement(A). { X = A; }
statement(X) ::= jump_statement(A). { X = A; }
statement(X) ::= assign_statement(A) SEMICOLON. { X = A; }
statement(X) ::= local_var(A) SEMICOLON. { X = A; }
statement(X) ::= labeled_statement(A). { X = A; /*X-overwrites-A*/ }
statement(X) ::= compound_statement(A). { X = A; /*X-overwrites-A*/ }
statement(X) ::= expression_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ }
statement(X) ::= selection_statement(X).
statement(X) ::= iteration_statement(X).
statement(X) ::= jump_statement(X).
statement(X) ::= assign_statement(A) SEMICOLON. { X = A; /*X-overwrites-A*/ }
statement(X) ::= local_var(A) SEMICOLON. { X = A; /*X-overwrites-A*/ }
statement(X) ::= error SEMICOLON. { X = NULL; }
/*----- Jump Statements -----*/
@ -1318,12 +1287,11 @@ compound_statement(X) ::= LBRACE(T) error RBRACE.
statement_list(X) ::= statement(A).
{
X = A;
X = A; /*X-overwrites-A*/
}
statement_list(X) ::= statement_list(A) statement(B).
statement_list(X) ::= statement_list(X) statement(B).
{
SAFE_APPEND(A,B);
X = A;
SAFE_APPEND(X,B);
}
/*----- Expression Statements -----*/
@ -1407,13 +1375,13 @@ while_or_until(X) ::= UNTIL(T).
}
%type for_init{ZCC_Statement *}
for_init(X) ::= local_var(A). { X = A; }
for_init(X) ::= for_bump(A). { X = A; }
for_init(X) ::= local_var(A). { X = A /*X-overwrites-A*/; }
for_init(X) ::= for_bump(A). { X = A /*X-overwrites-A*/; }
%type for_bump{ZCC_Statement *}
for_bump(X) ::= . { X = NULL; }
for_bump(X) ::= expression_statement(A). { X = A; }
for_bump(X) ::= assign_statement(A). { X = A; }
for_bump(X) ::= expression_statement(A). { X = A; /*X-overwrites-A*/ }
for_bump(X) ::= assign_statement(A). { X = A; /*X-overwrites-A*/ }
/*----- If Statements -----*/
@ -1428,12 +1396,12 @@ for_bump(X) ::= assign_statement(A). { X = A; }
selection_statement(X) ::= if_front(A). [IF]
{
X = A;
X = A; /*X-overwrites-A*/
}
selection_statement(X) ::= if_front(A) ELSE statement(B). [ELSE]
{
A->FalsePath = B;
X = A;
X = A; /*X-overwrites-A*/
}
if_front(X) ::= IF(T) LPAREN expr(A) RPAREN statement(B).
@ -1512,4 +1480,4 @@ local_var(X) ::= type(A) variable_list(B) var_init(C).
%type var_init{ZCC_Expression *}
var_init(X) ::= . { X = NULL; }
var_init(X) ::= EQ expr_list(A). { X = A; }
var_init(X) ::= EQ expr_list(A). { X = A; /*X-overwrites-A*/ }

View file

@ -19,7 +19,7 @@
//==========================================================================
ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols)
: Outer(_outer), Symbols(_symbols), AST(ast), ErrorCount(0), WarnCount(0)
: Outer(_outer), Symbols(&_symbols), AST(ast), ErrorCount(0), WarnCount(0)
{
// Group top-level nodes by type
if (ast.TopNode != NULL)
@ -30,29 +30,23 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols)
switch (node->NodeType)
{
case AST_Class:
if (AddNamedNode(static_cast<ZCC_Class *>(node)->ClassName, node))
{
Classes.Push(static_cast<ZCC_Class *>(node));
}
break;
case AST_Struct:
if (AddNamedNode(static_cast<ZCC_Struct *>(node)->StructName, node))
case AST_ConstantDef:
if (AddNamedNode(static_cast<ZCC_NamedNode *>(node)))
{
Structs.Push(static_cast<ZCC_Struct *>(node));
switch (node->NodeType)
{
case AST_Class: Classes.Push(static_cast<ZCC_Class *>(node)); break;
case AST_Struct: Structs.Push(static_cast<ZCC_Struct *>(node)); break;
case AST_ConstantDef: Constants.Push(static_cast<ZCC_ConstantDef *>(node)); break;
default: assert(0 && "Default case is just here to make GCC happy. It should never be reached");
}
}
break;
case AST_Enum: break;
case AST_EnumTerminator:break;
case AST_ConstantDef:
if (AddNamedNode(static_cast<ZCC_ConstantDef *>(node)->Name, node))
{
Constants.Push(static_cast<ZCC_ConstantDef *>(node));
}
break;
default:
assert(0 && "Unhandled AST node type");
break;
@ -72,55 +66,76 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols)
//
//==========================================================================
bool ZCCCompiler::AddNamedNode(FName name, ZCC_TreeNode *node)
bool ZCCCompiler::AddNamedNode(ZCC_NamedNode *node)
{
ZCC_TreeNode **check = NamedNodes.CheckKey(name);
if (check != NULL && *check != NULL)
FName name = node->NodeName;
PSymbol *check = Symbols->FindSymbol(name, false);
if (check != NULL)
{
Message(node, ERR_symbol_redefinition, "Attempt to redefine '%s'", name.GetChars());
Message(*check, ERR_original_definition, " Original definition is here");
assert(check->IsA(RUNTIME_CLASS(PSymbolTreeNode)));
Error(node, "Attempt to redefine '%s'", name.GetChars());
Error(static_cast<PSymbolTreeNode *>(check)->Node, " Original definition is here");
return false;
}
else
{
NamedNodes.Insert(name, node);
Symbols->AddSymbol(new PSymbolTreeNode(name, node));
return true;
}
}
//==========================================================================
//
// ZCCCompiler :: Message
// ZCCCompiler :: Warn
//
// Prints a warning or error message, and increments the appropriate
// counter.
// Prints a warning message, and increments WarnCount.
//
//==========================================================================
void ZCCCompiler::Message(ZCC_TreeNode *node, EZCCError errnum, const char *msg, ...)
void ZCCCompiler::Warn(ZCC_TreeNode *node, const char *msg, ...)
{
va_list argptr;
va_start(argptr, msg);
MessageV(node, TEXTCOLOR_ORANGE, msg, argptr);
va_end(argptr);
WarnCount++;
}
//==========================================================================
//
// ZCCCompiler :: Error
//
// Prints an error message, and increments ErrorCount.
//
//==========================================================================
void ZCCCompiler::Error(ZCC_TreeNode *node, const char *msg, ...)
{
va_list argptr;
va_start(argptr, msg);
MessageV(node, TEXTCOLOR_RED, msg, argptr);
va_end(argptr);
ErrorCount++;
}
//==========================================================================
//
// ZCCCompiler :: MessageV
//
// Prints a message, annotated with the source location for the tree node.
//
//==========================================================================
void ZCCCompiler::MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr)
{
FString composed;
composed.Format("%s%s, line %d: ",
errnum & ZCCERR_ERROR ? TEXTCOLOR_RED : TEXTCOLOR_ORANGE,
node->SourceName->GetChars(), node->SourceLoc);
va_list argptr;
va_start(argptr, msg);
composed.Format("%s%s, line %d: ", txtcolor, node->SourceName->GetChars(), node->SourceLoc);
composed.VAppendFormat(msg, argptr);
va_end(argptr);
composed += '\n';
PrintString(PRINT_HIGH, composed);
if (errnum & ZCCERR_ERROR)
{
ErrorCount++;
}
else
{
WarnCount++;
}
}
//==========================================================================
@ -133,7 +148,7 @@ void ZCCCompiler::Message(ZCC_TreeNode *node, EZCCError errnum, const char *msg,
int ZCCCompiler::Compile()
{
CompileConstants();
CompileConstants(Constants);
return ErrorCount;
}
@ -145,14 +160,14 @@ int ZCCCompiler::Compile()
//
//==========================================================================
void ZCCCompiler::CompileConstants()
void ZCCCompiler::CompileConstants(const TArray<ZCC_ConstantDef *> &defs)
{
for (unsigned i = 0; i < Constants.Size(); ++i)
for (unsigned i = 0; i < defs.Size(); ++i)
{
ZCC_ConstantDef *def = Constants[i];
ZCC_ConstantDef *def = defs[i];
if (def->Symbol == NULL)
{
CompileConstant(def);
PSymbolConst *sym = CompileConstant(def);
}
}
}
@ -180,33 +195,32 @@ PSymbolConst *ZCCCompiler::CompileConstant(ZCC_ConstantDef *def)
ZCC_ExprConstant *cval = static_cast<ZCC_ExprConstant *>(val);
if (cval->Type == TypeString)
{
sym = new PSymbolConstString(def->Name, *(cval->StringVal));
sym = new PSymbolConstString(def->NodeName, *(cval->StringVal));
}
else if (cval->Type->IsA(RUNTIME_CLASS(PInt)))
{
sym = new PSymbolConstNumeric(def->Name, cval->Type, cval->IntVal);
sym = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal);
}
else if (cval->Type->IsA(RUNTIME_CLASS(PFloat)))
{
sym = new PSymbolConstNumeric(def->Name, cval->Type, cval->DoubleVal);
sym = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->DoubleVal);
}
else
{
Message(def->Value, ERR_bad_const_def_type, "Bad type for constant definiton");
Error(def->Value, "Bad type for constant definiton");
}
}
else
{
Message(def->Value, ERR_const_def_not_constant, "Constant definition requires a constant value");
Error(def->Value, "Constant definition requires a constant value");
}
if (sym == NULL)
{
// Create a dummy constant so we don't make any undefined value warnings.
sym = new PSymbolConstNumeric(def->Name, TypeError, 0);
sym = new PSymbolConstNumeric(def->NodeName, TypeError, 0);
}
def->Symbol = sym;
PSymbol *addsym = Symbols.AddSymbol(sym);
assert(NULL != addsym && "Symbol was redefined (but we shouldn't have even had the chance to do so)");
Symbols->ReplaceSymbol(sym);
return sym;
}
@ -307,17 +321,18 @@ ZCC_Expression *ZCCCompiler::SimplifyMemberAccess(ZCC_ExprMemberAccess *dotop)
if (dotop->Left->Operation == PEX_TypeRef)
{ // Type refs can be evaluated now.
PType *ref = static_cast<ZCC_ExprTypeRef *>(dotop->Left)->RefType;
PSymbol *sym = ref->Symbols.FindSymbol(dotop->Right, true);
PSymbolTable *symtable;
PSymbol *sym = ref->Symbols.FindSymbolInTable(dotop->Right, symtable);
if (sym == NULL)
{
Message(dotop, ERR_not_a_member, "'%s' is not a valid member", FName(dotop->Right).GetChars());
Error(dotop, "'%s' is not a valid member", FName(dotop->Right).GetChars());
}
else
{
ZCC_Expression *expr = NodeFromSymbol(sym, dotop);
ZCC_Expression *expr = NodeFromSymbol(sym, dotop, symtable);
if (expr == NULL)
{
Message(dotop, ERR_bad_symbol, "Unhandled symbol type encountered");
Error(dotop, "Unhandled symbol type encountered");
}
else
{
@ -361,7 +376,7 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop)
{
if (parmcount != 1)
{
Message(callop, ERR_cast_needs_1_parm, "Type cast requires one parameter");
Error(callop, "Type cast requires one parameter");
callop->ToErrorNode();
}
else
@ -371,8 +386,8 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop)
int routelen = parm->Value->Type->FindConversion(dest, route, countof(route));
if (routelen < 0)
{
// FIXME: Need real type names
Message(callop, ERR_cast_not_possible, "Cannot convert type 1 to type 2");
///FIXME: Need real type names
Error(callop, "Cannot convert type 1 to type 2");
callop->ToErrorNode();
}
else
@ -483,53 +498,79 @@ ZCC_Expression *ZCCCompiler::AddCastNode(PType *type, ZCC_Expression *expr)
ZCC_Expression *ZCCCompiler::IdentifyIdentifier(ZCC_ExprID *idnode)
{
// First things first: Check the symbol table.
PSymbol *sym;
if (NULL != (sym = Symbols.FindSymbol(idnode->Identifier, true)))
// Check the symbol table for the identifier.
PSymbolTable *table;
PSymbol *sym = Symbols->FindSymbolInTable(idnode->Identifier, table);
if (sym != NULL)
{
ZCC_Expression *node = NodeFromSymbol(sym, idnode);
ZCC_Expression *node = NodeFromSymbol(sym, idnode, table);
if (node != NULL)
{
return node;
}
}
else
{ // Check nodes that haven't had symbols created for them yet.
ZCC_TreeNode **node = NamedNodes.CheckKey(idnode->Identifier);
if (node != NULL && *node != NULL)
{
if ((*node)->NodeType == AST_ConstantDef)
{
ZCC_ConstantDef *def = static_cast<ZCC_ConstantDef *>(*node);
PSymbolConst *sym = def->Symbol;
if (sym == DEFINING_CONST)
{
Message(idnode, ERR_recursive_definition, "Definition of '%s' is infinitely recursive", FName(idnode->Identifier).GetChars());
sym = NULL;
}
else
{
assert(sym == NULL);
sym = CompileConstant(def);
}
return NodeFromSymbolConst(sym, idnode);
}
}
{
Error(idnode, "Unknown identifier '%s'", FName(idnode->Identifier).GetChars());
}
// Identifier didn't refer to anything good, so type error it.
idnode->ToErrorNode();
return idnode;
}
//==========================================================================
//
// ZCCCompiler :: CompileNode
//
//==========================================================================
PSymbol *ZCCCompiler::CompileNode(ZCC_NamedNode *node)
{
assert(node != NULL);
if (node->NodeType == AST_ConstantDef)
{
ZCC_ConstantDef *def = static_cast<ZCC_ConstantDef *>(node);
PSymbolConst *sym = def->Symbol;
if (sym == DEFINING_CONST)
{
Error(node, "Definition of '%s' is infinitely recursive", FName(node->NodeName).GetChars());
sym = NULL;
}
else
{
assert(sym == NULL);
sym = CompileConstant(def);
}
return sym;
}
else if (node->NodeType == AST_Struct)
{
}
return NULL;
}
//==========================================================================
//
// ZCCCompiler :: NodeFromSymbol
//
//==========================================================================
ZCC_Expression *ZCCCompiler::NodeFromSymbol(PSymbol *sym, ZCC_Expression *source)
ZCC_Expression *ZCCCompiler::NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table)
{
assert(sym != NULL);
if (sym->IsA(RUNTIME_CLASS(PSymbolTreeNode)))
{
PSymbolTable *prevtable = Symbols;
Symbols = table;
sym = CompileNode(static_cast<PSymbolTreeNode *>(sym)->Node);
Symbols = prevtable;
if (sym == NULL)
{
return NULL;
}
}
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
{
return NodeFromSymbolConst(static_cast<PSymbolConst *>(sym), source);

View file

@ -1,8 +1,6 @@
#ifndef ZCC_COMPILE_H
#define ZCC_COMPILE_H
#include "zcc_errors.h"
class ZCCCompiler
{
public:
@ -10,15 +8,14 @@ public:
int Compile();
private:
void CompileConstants();
void CompileConstants(const TArray<ZCC_ConstantDef *> &defs);
PSymbolConst *CompileConstant(ZCC_ConstantDef *def);
TArray<ZCC_ConstantDef *> Constants;
TArray<ZCC_Struct *> Structs;
TArray<ZCC_Class *> Classes;
TMap<FName, ZCC_TreeNode *> NamedNodes;
bool AddNamedNode(FName name, ZCC_TreeNode *node);
bool AddNamedNode(ZCC_NamedNode *node);
ZCC_Expression *Simplify(ZCC_Expression *root);
ZCC_Expression *SimplifyUnary(ZCC_ExprUnary *unary);
@ -37,14 +34,18 @@ private:
ZCC_Expression *AddCastNode(PType *type, ZCC_Expression *expr);
ZCC_Expression *IdentifyIdentifier(ZCC_ExprID *idnode);
ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source);
ZCC_Expression *NodeFromSymbol(PSymbol *sym, ZCC_Expression *source, PSymbolTable *table);
ZCC_ExprConstant *NodeFromSymbolConst(PSymbolConst *sym, ZCC_Expression *idnode);
ZCC_ExprTypeRef *NodeFromSymbolType(PSymbolType *sym, ZCC_Expression *idnode);
PSymbol *CompileNode(ZCC_NamedNode *node);
void Message(ZCC_TreeNode *node, EZCCError errnum, const char *msg, ...);
void Warn(ZCC_TreeNode *node, const char *msg, ...);
void Error(ZCC_TreeNode *node, const char *msg, ...);
void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr);
DObject *Outer;
PSymbolTable &Symbols;
PSymbolTable *Symbols;
ZCC_AST &AST;
int ErrorCount;
int WarnCount;

View file

@ -1,14 +0,0 @@
#define ZCCERR_ERROR 0x40000000
enum EZCCError
{
ERR_const_def_not_constant = 20000 | ZCCERR_ERROR,
ERR_bad_const_def_type = 20001 | ZCCERR_ERROR,
ERR_symbol_redefinition = 20002 | ZCCERR_ERROR,
ERR_original_definition = 20003 | ZCCERR_ERROR,
ERR_recursive_definition = 20004 | ZCCERR_ERROR,
ERR_not_a_member = 20005 | ZCCERR_ERROR,
ERR_bad_symbol = 20006 | ZCCERR_ERROR,
ERR_cast_needs_1_parm = 20007 | ZCCERR_ERROR,
ERR_cast_not_possible = 20008 | ZCCERR_ERROR,
};

View file

@ -174,24 +174,26 @@ struct ZCC_Identifier : ZCC_TreeNode
ENamedName Id;
};
struct ZCC_Class : ZCC_TreeNode
struct ZCC_NamedNode : ZCC_TreeNode
{
ENamedName NodeName;
};
struct ZCC_Class : ZCC_NamedNode
{
ENamedName ClassName;
ZCC_Identifier *ParentName;
ZCC_Identifier *Replaces;
VM_UWORD Flags;
ZCC_TreeNode *Body;
};
struct ZCC_Struct : ZCC_TreeNode
struct ZCC_Struct : ZCC_NamedNode
{
ENamedName StructName;
ZCC_TreeNode *Body;
};
struct ZCC_Enum : ZCC_TreeNode
struct ZCC_Enum : ZCC_NamedNode
{
ENamedName EnumName;
EZCCBuiltinType EnumType;
struct ZCC_ConstantDef *Elements;
};
@ -432,9 +434,8 @@ struct ZCC_FuncParamDecl : ZCC_TreeNode
int Flags;
};
struct ZCC_ConstantDef : ZCC_TreeNode
struct ZCC_ConstantDef : ZCC_NamedNode
{
ENamedName Name;
ZCC_Expression *Value;
PSymbolConst *Symbol;
};

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,27 @@
/* Driver template for the LEMON parser generator.
** The author disclaims copyright to this source code.
/*
** 2000-05-29
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** Driver template for the LEMON parser generator.
**
** The "lemon" program processes an LALR(1) input grammar file, then uses
** this template to construct a parser. The "lemon" program inserts text
** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
** interstitial "-" characters) contained in this template is changed into
** the value of the %name directive from the grammar. Otherwise, the content
** of this template is copied straight through into the generate parser
** source file.
**
** The following is the concatenation of all %include directives from the
** input grammar file:
*/
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */
#include <stdio.h>
#include <string.h>
#include <assert.h>
@ -13,65 +32,70 @@
#define CDECL
#endif
/************ Begin %include sections from the grammar ************************/
%%
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
/*
** These constants (all generated automatically by the parser generator)
** specify the various kinds of tokens (terminals) that the parser
** understands.
**
** Each symbol here is a terminal symbol in the grammar.
*/
/**************** End of %include directives **********************************/
/* These constants specify the various numeric values for terminal symbols
** in a format understandable to "makeheaders". This section is blank unless
** "lemon" is run with the "-m" command-line option.
***************** Begin makeheaders token definitions *************************/
%%
/* Make sure the INTERFACE macro is defined.
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/* The next thing included is series of defines which control
/**************** End makeheaders token definitions ***************************/
/* The next section is a series of control #defines.
** various aspects of the generated parser.
** YYCODETYPE is the data type used for storing terminal
** and nonterminal numbers. "unsigned char" is
** used if there are fewer than 250 terminals
** and nonterminals. "int" is used otherwise.
** YYNOCODE is a number of type YYCODETYPE which corresponds
** to no legal terminal or nonterminal number. This
** number is used to fill in empty slots of the hash
** table.
** YYCODETYPE is the data type used to store the integer codes
** that represent terminal and non-terminal symbols.
** "unsigned char" is used if there are fewer than
** 256 symbols. Larger types otherwise.
** YYNOCODE is a number of type YYCODETYPE that is not used for
** any terminal or nonterminal symbol.
** YYFALLBACK If defined, this indicates that one or more tokens
** have fall-back values which should be used if the
** original value of the token will not parse.
** YYACTIONTYPE is the data type used for storing terminal
** and nonterminal numbers. "unsigned char" is
** used if there are fewer than 250 rules and
** states combined. "int" is used otherwise.
** ParseTOKENTYPE is the data type used for minor tokens given
** directly to the parser from the tokenizer.
** YYMINORTYPE is the data type used for all minor tokens.
** (also known as: "terminal symbols") have fall-back
** values which should be used if the original symbol
** would not parse. This permits keywords to sometimes
** be used as identifiers, for example.
** YYACTIONTYPE is the data type used for "action codes" - numbers
** that indicate what to do in response to the next
** token.
** ParseTOKENTYPE is the data type used for minor type for terminal
** symbols. Background: A "minor type" is a semantic
** value associated with a terminal or non-terminal
** symbols. For example, for an "ID" terminal symbol,
** the minor type might be the name of the identifier.
** Each non-terminal can have a different minor type.
** Terminal symbols all have the same minor type, though.
** This macros defines the minor type for terminal
** symbols.
** YYMINORTYPE is the data type used for all minor types.
** This is typically a union of many types, one of
** which is ParseTOKENTYPE. The entry in the union
** for base tokens is called "yy0".
** for terminal symbols is called "yy0".
** YYSTACKDEPTH is the maximum depth of the parser's stack. If
** zero the stack is dynamically sized using realloc()
** ParseARG_SDECL A static variable declaration for the %extra_argument
** ParseARG_PDECL A parameter declaration for the %extra_argument
** ParseARG_STORE Code to store %extra_argument into yypParser
** ParseARG_FETCH Code to extract %extra_argument from yypParser
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
** YYNSTATE the combined number of states.
** YYNRULE the number of rules in the grammar
** YY_MAX_SHIFT Maximum value for shift actions
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
** YY_MIN_REDUCE Maximum value for reduce actions
** YY_ERROR_ACTION The yy_action[] code for syntax error
** YY_ACCEPT_ACTION The yy_action[] code for accept
** YY_NO_ACTION The yy_action[] code for no-op
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/************* Begin control #defines *****************************************/
%%
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
static const YYMINORTYPE yyzerominor = { 0 };
/************* End control #defines *******************************************/
/* Define the yytestcase() macro to be a no-op if is not already defined
** otherwise.
@ -94,16 +118,20 @@ static const YYMINORTYPE yyzerominor = { 0 };
** Suppose the action integer is N. Then the action is determined as
** follows
**
** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
** token onto the stack and goto state N.
**
** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
**
** N == YYNSTATE+YYNRULE A syntax error has occurred.
** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
** and YY_MAX_REDUCE
** N == YY_ERROR_ACTION A syntax error has occurred.
**
** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
** N == YY_ACCEPT_ACTION The parser accepts its input.
**
** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
** N == YY_NO_ACTION No such action. Denotes unused
** slots in the yy_action[] table.
**
** The action table is constructed as a single large table named yy_action[].
@ -132,12 +160,13 @@ static const YYMINORTYPE yyzerominor = { 0 };
** yy_reduce_ofst[] For each state, the offset into yy_action for
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
**
*********** Begin parsing tables **********************************************/
%%
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
/********** End of lemon-generated parsing tables *****************************/
/* The next table maps tokens into fallback tokens. If a construct
** like the following:
/* The next table maps tokens (terminal symbols) into fallback tokens.
** If a construct like the following:
**
** %fallback ID X Y Z.
**
@ -145,6 +174,10 @@ static const YYMINORTYPE yyzerominor = { 0 };
** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
** but it does not parse, the type of the token is changed to ID and
** the parse is retried before an error is thrown.
**
** This feature can be used, for example, to cause some keywords in a language
** to revert to identifiers if they keyword does not apply in the context where
** it appears.
*/
#ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = {
@ -163,9 +196,13 @@ static const YYCODETYPE yyFallback[] = {
** + The semantic value stored at this level of the stack. This is
** the information used by the action routines in the grammar.
** It is sometimes called the "minor" token.
**
** After the "shift" half of a SHIFTREDUCE action, the stateno field
** actually contains the reduce action for the second half of the
** SHIFTREDUCE.
*/
struct yyStackEntry {
YYACTIONTYPE stateno; /* The state-number */
YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
YYCODETYPE major; /* The major token value. This is the code
** number for the token at this stack level */
YYMINORTYPE minor; /* The user-supplied minor token value. This
@ -180,7 +217,9 @@ struct yyParser {
#ifdef YYTRACKMAXSTACKDEPTH
int yyidxMax; /* Maximum value of yyidx */
#endif
#ifndef YYNOERRORRECOVERY
int yyerrcnt; /* Shifts left before out of the error */
#endif
ParseARG_SDECL /* A place to hold %extra_argument */
#if YYSTACKDEPTH<=0
int yystksz; /* Current side of the stack */
@ -262,6 +301,15 @@ static void yyGrowStack(yyParser *p){
}
#endif
/* Datatype of the argument to the memory allocated passed as the
** second argument to ParseAlloc() below. This can be changed by
** putting an appropriate #define in the %include section of the input
** grammar.
*/
#ifndef YYMALLOCARGTYPE
# define YYMALLOCARGTYPE size_t
#endif
/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
@ -274,9 +322,9 @@ static void yyGrowStack(yyParser *p){
** A pointer to a parser. This pointer is used in subsequent calls
** to Parse and ParseFree.
*/
void *ParseAlloc(void *(CDECL *mallocProc)(size_t)){
void *ParseAlloc(void *(CDECL *mallocProc)(YYMALLOCARGTYPE)){
yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
if( pParser ){
pParser->yyidx = -1;
#ifdef YYTRACKMAXSTACKDEPTH
@ -291,10 +339,12 @@ void *ParseAlloc(void *(CDECL *mallocProc)(size_t)){
return pParser;
}
/* The following function deletes the value associated with a
** symbol. The symbol can be either a terminal or nonterminal.
** "yymajor" is the symbol code, and "yypminor" is a pointer to
** the value.
/* The following function deletes the "minor type" or semantic value
** associated with a symbol. The symbol can be either a terminal
** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
** a pointer to the value to be deleted. The code used to do the
** deletions is derived from the %destructor and/or %token_destructor
** directives of the input grammar.
*/
static void yy_destructor(
yyParser *yypParser, /* The parser */
@ -310,10 +360,12 @@ static void yy_destructor(
** being destroyed before it is finished parsing.
**
** Note: during a reduce, the only symbols destroyed are those
** which appear on the RHS of the rule, but which are not used
** which appear on the RHS of the rule, but which are *not* used
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
%%
/********* End destructor definitions *****************************************/
default: break; /* If no destructor action specified: do nothing */
}
}
@ -323,45 +375,37 @@ static void yy_destructor(
**
** If there is a destructor routine associated with the token which
** is popped from the stack, then call it.
**
** Return the major token number for the symbol popped.
*/
static int yy_pop_parser_stack(yyParser *pParser){
YYCODETYPE yymajor;
yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
if( pParser->yyidx<0 ) return 0;
static void yy_pop_parser_stack(yyParser *pParser){
yyStackEntry *yytos;
assert( pParser->yyidx>=0 );
yytos = &pParser->yystack[pParser->yyidx--];
#ifndef NDEBUG
if( yyTraceFILE && pParser->yyidx>=0 ){
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sPopping %s\n",
yyTracePrompt,
yyTokenName[yytos->major]);
}
#endif
yymajor = yytos->major;
yy_destructor(pParser, yymajor, &yytos->minor);
pParser->yyidx--;
return yymajor;
yy_destructor(pParser, yytos->major, &yytos->minor);
}
/*
** Deallocate and destroy a parser. Destructors are all called for
/*
** Deallocate and destroy a parser. Destructors are called for
** all stack elements before shutting the parser down.
**
** Inputs:
** <ul>
** <li> A pointer to the parser. This should be a pointer
** obtained from ParseAlloc.
** <li> A pointer to a function used to reclaim memory obtained
** from malloc.
** </ul>
*
** If the YYPARSEFREENEVERNULL macro exists (for example because it
** is defined in a %include section of the input grammar) then it is
** assumed that the input pointer is never NULL.
*/
void ParseFree(
void *p, /* The parser to be deleted */
void (CDECL *freeProc)(void*) /* Function used to reclaim memory */
){
yyParser *pParser = (yyParser*)p;
#ifndef YYPARSEFREENEVERNULL
if( pParser==0 ) return;
#endif
while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
free(pParser->yystack);
@ -382,66 +426,72 @@ int ParseStackPeak(void *p){
/*
** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead. If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_shift_action(
static unsigned int yy_find_shift_action(
yyParser *pParser, /* The parser */
YYCODETYPE iLookAhead /* The look-ahead token */
){
int i;
int stateno = pParser->yystack[pParser->yyidx].stateno;
if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
return yy_default[stateno];
}
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
if( iLookAhead>0 ){
if( stateno>=YY_MIN_REDUCE ) return stateno;
assert( stateno <= YY_SHIFT_COUNT );
do{
i = yy_shift_ofst[stateno];
if( i==YY_SHIFT_USE_DFLT ) return yy_default[stateno];
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
if( iLookAhead>0 ){
#ifdef YYFALLBACK
YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
&& (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
}
#endif
return yy_find_shift_action(pParser, iFallback);
}
#endif
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
if( j>=0 && j<YY_SZ_ACTTAB && yy_lookahead[j]==YYWILDCARD ){
YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
&& (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
}
#endif
assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
iLookAhead = iFallback;
continue;
}
#endif
#ifdef YYWILDCARD
{
int j = i - iLookAhead + YYWILDCARD;
if(
#if YY_SHIFT_MIN+YYWILDCARD<0
j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
j<YY_ACTTAB_COUNT &&
#endif
yy_lookahead[j]==YYWILDCARD
){
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
yyTracePrompt, yyTokenName[iLookAhead],
yyTokenName[YYWILDCARD]);
}
#endif /* NDEBUG */
return yy_action[j];
}
#endif /* NDEBUG */
return yy_action[j];
}
}
#endif /* YYWILDCARD */
}
return yy_default[stateno];
}else{
return yy_action[i];
}
return yy_default[stateno];
}else{
return yy_action[i];
}
}while(1);
}
/*
** Find the appropriate action for a parser given the non-terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead. If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_reduce_action(
int stateno, /* Current state number */
@ -449,22 +499,22 @@ static int yy_find_reduce_action(
){
int i;
#ifdef YYERRORSYMBOL
if( stateno>YY_REDUCE_MAX ){
if( stateno>YY_REDUCE_COUNT ){
return yy_default[stateno];
}
#else
assert( stateno<=YY_REDUCE_MAX );
assert( stateno<=YY_REDUCE_COUNT );
#endif
i = yy_reduce_ofst[stateno];
assert( i!=YY_REDUCE_USE_DFLT );
assert( iLookAhead!=YYNOCODE );
i += iLookAhead;
#ifdef YYERRORSYMBOL
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
return yy_default[stateno];
}
#else
assert( i>=0 && i<YY_SZ_ACTTAB );
assert( i>=0 && i<YY_ACTTAB_COUNT );
assert( yy_lookahead[i]==iLookAhead );
#endif
return yy_action[i];
@ -473,7 +523,7 @@ static int yy_find_reduce_action(
/*
** The following routine is called if the stack overflows.
*/
static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
static void yyStackOverflow(yyParser *yypParser){
ParseARG_FETCH;
yypParser->yyidx--;
#ifndef NDEBUG
@ -484,10 +534,32 @@ static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack ever overflows */
/******** Begin %stack_overflow code ******************************************/
%%
/******** End %stack_overflow code ********************************************/
ParseARG_STORE; /* Suppress warning about unused %extra_argument var */
}
/*
** Print tracing information for a SHIFT action
*/
#ifndef NDEBUG
static void yyTraceShift(yyParser *yypParser, int yyNewState){
if( yyTraceFILE ){
if( yyNewState<YYNSTATE ){
fprintf(yyTraceFILE,"%sShift '%s', go to state %d\n",
yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major],
yyNewState);
}else{
fprintf(yyTraceFILE,"%sShift '%s'\n",
yyTracePrompt,yyTokenName[yypParser->yystack[yypParser->yyidx].major]);
}
}
}
#else
# define yyTraceShift(X,Y)
#endif
/*
** Perform a shift action.
*/
@ -495,7 +567,7 @@ static void yy_shift(
yyParser *yypParser, /* The parser to be shifted */
int yyNewState, /* The new state to shift in */
int yyMajor, /* The major token to shift in */
YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */
ParseTOKENTYPE yyMinor /* The minor token to shift in */
){
yyStackEntry *yytos;
yypParser->yyidx++;
@ -506,14 +578,14 @@ static void yy_shift(
#endif
#if YYSTACKDEPTH>0
if( yypParser->yyidx>=YYSTACKDEPTH ){
yyStackOverflow(yypParser, yypMinor);
yyStackOverflow(yypParser);
return;
}
#else
if( yypParser->yyidx>=yypParser->yystksz ){
yyGrowStack(yypParser);
if( yypParser->yyidx>=yypParser->yystksz ){
yyStackOverflow(yypParser, yypMinor);
yyStackOverflow(yypParser);
return;
}
}
@ -521,17 +593,8 @@ static void yy_shift(
yytos = &yypParser->yystack[yypParser->yyidx];
yytos->stateno = (YYACTIONTYPE)yyNewState;
yytos->major = (YYCODETYPE)yyMajor;
yytos->minor = *yypMinor;
#ifndef NDEBUG
if( yyTraceFILE && yypParser->yyidx>0 ){
int i;
fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE," (%d)%s",yypParser->yystack[i].stateno,yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"\n");
}
#endif
yytos->minor.yy0 = yyMinor;
yyTraceShift(yypParser, yyNewState);
}
/* The following table contains information about every rule that
@ -552,39 +615,46 @@ static void yy_accept(yyParser*); /* Forward Declaration */
*/
static void yy_reduce(
yyParser *yypParser, /* The parser */
int yyruleno /* Number of the rule by which to reduce */
unsigned int yyruleno /* Number of the rule by which to reduce */
){
int yygoto; /* The next state */
int yyact; /* The next action */
YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
yyStackEntry *yymsp; /* The top of the parser's stack */
int yysize; /* Amount to pop the stack */
ParseARG_FETCH;
yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
if( yyTraceFILE && yyruleno>=0
&& yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
yyRuleName[yyruleno]);
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfo[yyruleno].nrhs;
fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt,
yyRuleName[yyruleno], yymsp[-yysize].stateno);
}
#endif /* NDEBUG */
/* Silence complaints from purify about yygotominor being uninitialized
** in some cases when it is copied into the stack after the following
** switch. yygotominor is uninitialized when a rule reduces that does
** not set the value of its left-hand side nonterminal. Leaving the
** value of the nonterminal uninitialized is utterly harmless as long
** as the value is never used. So really the only thing this code
** accomplishes is to quieten purify.
**
** 2007-01-16: The wireshark project (www.wireshark.org) reports that
** without this code, their parser segfaults. I'm not sure what there
** parser is doing to make this happen. This is the second bug report
** from wireshark this week. Clearly they are stressing Lemon in ways
** that it has not been previously stressed... (SQLite ticket #2172)
*/
/*memset(&yygotominor, 0, sizeof(yygotominor));*/
yygotominor = yyzerominor;
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
if( yyRuleInfo[yyruleno].nrhs==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( yypParser->yyidx>yypParser->yyidxMax ){
yypParser->yyidxMax = yypParser->yyidx;
}
#endif
#if YYSTACKDEPTH>0
if( yypParser->yyidx>=YYSTACKDEPTH-1 ){
yyStackOverflow(yypParser);
return;
}
#else
if( yypParser->yyidx>=yypParser->yystksz-1 ){
yyGrowStack(yypParser);
if( yypParser->yyidx>=yypParser->yystksz-1 ){
yyStackOverflow(yypParser);
return;
}
}
#endif
}
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
@ -595,31 +665,24 @@ static void yy_reduce(
** #line <lineno> <thisfile>
** break;
*/
/********** Begin reduce actions **********************************************/
%%
/********** End reduce actions ************************************************/
};
assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
if( yyact < YYNSTATE ){
#ifdef NDEBUG
/* If we are not debugging and the reduce action popped at least
** one element off the stack, then we can push the new element back
** onto the stack here, and skip the stack overflow test in yy_shift().
** That gives a significant speed improvement. */
if( yysize ){
yypParser->yyidx++;
yymsp -= yysize-1;
yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto;
yymsp->minor = yygotominor;
}else
#endif
{
yy_shift(yypParser,yyact,yygoto,&yygotominor);
}
if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact>YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
yypParser->yyidx -= yysize - 1;
yymsp -= yysize-1;
yymsp->stateno = (YYACTIONTYPE)yyact;
yymsp->major = (YYCODETYPE)yygoto;
yyTraceShift(yypParser, yyact);
}else{
assert( yyact == YYNSTATE + YYNRULE + 1 );
assert( yyact == YY_ACCEPT_ACTION );
yypParser->yyidx -= yysize;
yy_accept(yypParser);
}
}
@ -640,7 +703,9 @@ static void yy_parse_failed(
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser fails */
/************ Begin %parse_failure code ***************************************/
%%
/************ End %parse_failure code *****************************************/
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
#endif /* YYNOERRORRECOVERY */
@ -651,11 +716,13 @@ static void yy_parse_failed(
static void yy_syntax_error(
yyParser *yypParser, /* The parser */
int yymajor, /* The major type of the error token */
YYMINORTYPE yyminor /* The minor type of the error token */
ParseTOKENTYPE yyminor /* The minor type of the error token */
){
ParseARG_FETCH;
#define TOKEN (yyminor.yy0)
#define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/
%%
/************ End %syntax_error code ******************************************/
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
@ -674,7 +741,9 @@ static void yy_accept(
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will be executed whenever the
** parser accepts */
/*********** Begin %parse_accept code *****************************************/
%%
/*********** End %parse_accept code *******************************************/
ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
@ -704,8 +773,10 @@ void Parse(
ParseARG_PDECL /* Optional %extra_argument parameter */
){
YYMINORTYPE yyminorunion;
int yyact; /* The parser action. */
unsigned int yyact; /* The parser action. */
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
int yyendofinput; /* True if we are at the end of input */
#endif
#ifdef YYERRORSYMBOL
int yyerrorhit = 0; /* True if yymajor has invoked an error */
#endif
@ -716,41 +787,51 @@ void Parse(
if( yypParser->yyidx<0 ){
#if YYSTACKDEPTH<=0
if( yypParser->yystksz <=0 ){
/*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
yyminorunion = yyzerominor;
yyStackOverflow(yypParser, &yyminorunion);
yyStackOverflow(yypParser);
return;
}
#endif
yypParser->yyidx = 0;
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt = -1;
#endif
yypParser->yystack[0].stateno = 0;
yypParser->yystack[0].major = 0;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sInitialize. Empty stack. State 0\n",
yyTracePrompt);
}
#endif
}
yyminorunion.yy0 = yyminor;
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
yyendofinput = (yymajor==0);
#endif
ParseARG_STORE;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]);
}
#endif
do{
yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
if( yyact<YYNSTATE ){
assert( !yyendofinput ); /* Impossible to shift the $ token */
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
if( yyact <= YY_MAX_SHIFTREDUCE ){
if( yyact > YY_MAX_SHIFT ) yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
yy_shift(yypParser,yyact,yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
yypParser->yyerrcnt--;
#endif
yymajor = YYNOCODE;
}else if( yyact < YYNSTATE + YYNRULE ){
yy_reduce(yypParser,yyact-YYNSTATE);
}else if( yyact <= YY_MAX_REDUCE ){
yy_reduce(yypParser,yyact-YY_MIN_REDUCE);
}else{
#ifdef YYERRORSYMBOL
int yymx;
#endif
assert( yyact == YY_ERROR_ACTION );
yyminorunion.yy0 = yyminor;
#ifndef NDEBUG
if( yyTraceFILE ){
fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
@ -759,7 +840,7 @@ void Parse(
#ifdef YYERRORSYMBOL
/* A syntax error has occurred.
** The response to an error depends upon whether or not the
** grammar defines an error token "ERROR".
** grammar defines an error token "ERROR".
**
** This is what we do if the grammar does define ERROR:
**
@ -777,7 +858,7 @@ void Parse(
**
*/
if( yypParser->yyerrcnt<0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
yy_syntax_error(yypParser,yymajor,yyminor);
}
yymx = yypParser->yystack[yypParser->yyidx].major;
if( yymx==YYERRORSYMBOL || yyerrorhit ){
@ -787,15 +868,15 @@ void Parse(
yyTracePrompt,yyTokenName[yymajor]);
}
#endif
yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
yymajor = YYNOCODE;
}else{
while(
while(
yypParser->yyidx >= 0 &&
yymx != YYERRORSYMBOL &&
(yyact = yy_find_reduce_action(
yypParser->yystack[yypParser->yyidx].stateno,
YYERRORSYMBOL)) >= YYNSTATE
YYERRORSYMBOL)) >= YY_MIN_REDUCE
){
yy_pop_parser_stack(yypParser);
}
@ -804,9 +885,7 @@ void Parse(
yy_parse_failed(yypParser);
yymajor = YYNOCODE;
}else if( yymx!=YYERRORSYMBOL ){
YYMINORTYPE u2;
u2.YYERRSYMDT = 0;
yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor);
}
}
yypParser->yyerrcnt = 3;
@ -819,7 +898,7 @@ void Parse(
** Applications can set this macro (for example inside %include) if
** they intend to abandon the parse upon the first syntax error seen.
*/
yy_syntax_error(yypParser,yymajor,yyminorunion);
yy_syntax_error(yypParser,yymajor, yyminor);
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yymajor = YYNOCODE;
@ -834,7 +913,7 @@ void Parse(
** three input tokens have been successfully shifted.
*/
if( yypParser->yyerrcnt<=0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
yy_syntax_error(yypParser,yymajor, yyminor);
}
yypParser->yyerrcnt = 3;
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
@ -845,5 +924,15 @@ void Parse(
#endif
}
}while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
#ifndef NDEBUG
if( yyTraceFILE ){
int i;
fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
for(i=1; i<=yypParser->yyidx; i++)
fprintf(yyTraceFILE,"%c%s", i==1 ? '[' : ' ',
yyTokenName[yypParser->yystack[i].major]);
fprintf(yyTraceFILE,"]\n");
}
#endif
return;
}