mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 06:42:08 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom
This commit is contained in:
commit
904a027bd2
19 changed files with 1780 additions and 1207 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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).
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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*/ }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
};
|
||||
|
|
1866
tools/lemon/lemon.c
1866
tools/lemon/lemon.c
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue