mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-07 10:21:31 +00:00
DIRECTOR: LINGO: Rewrite grammar to build AST
This commit is contained in:
parent
34d8aabc4b
commit
f726a6ed89
191
engines/director/lingo/lingo-ast.cpp
Normal file
191
engines/director/lingo/lingo-ast.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "director/lingo/lingo.h"
|
||||
#include "director/lingo/lingo-ast.h"
|
||||
#include "director/lingo/lingo-code.h"
|
||||
#include "director/lingo/lingo-object.h"
|
||||
|
||||
namespace Director {
|
||||
|
||||
/* ScriptNode */
|
||||
|
||||
void ScriptNode::compile() {
|
||||
for (uint i = 0; i < nodes->size(); i++) {
|
||||
(*nodes)[i]->compile();
|
||||
}
|
||||
}
|
||||
|
||||
/* FactoryNode */
|
||||
|
||||
void FactoryNode::compile() {
|
||||
g_lingo->_inFactory = true;
|
||||
ScriptContext *mainContext = g_lingo->_assemblyContext;
|
||||
g_lingo->_assemblyContext = new ScriptContext(mainContext->getName(), mainContext->_archive, mainContext->_scriptType, mainContext->_id);
|
||||
|
||||
g_lingo->codeFactory(*name);
|
||||
for (uint i = 0; i < methods->size(); i++) {
|
||||
(*methods)[i]->compile();
|
||||
}
|
||||
|
||||
g_lingo->_inFactory = false;
|
||||
g_lingo->_assemblyContext = mainContext;
|
||||
}
|
||||
|
||||
/* HandlerNode */
|
||||
|
||||
void HandlerNode::compile() {
|
||||
g_lingo->_indef = true;
|
||||
VarTypeHash *mainMethodVars = g_lingo->_methodVars;
|
||||
g_lingo->_methodVars = new VarTypeHash;
|
||||
|
||||
for (VarTypeHash::iterator i = mainMethodVars->begin(); i != mainMethodVars->end(); ++i) {
|
||||
if (i->_value == kVarGlobal || i->_value == kVarProperty)
|
||||
(*g_lingo->_methodVars)[i->_key] = i->_value;
|
||||
}
|
||||
if (g_lingo->_inFactory) {
|
||||
for (DatumHash::iterator i = g_lingo->_assemblyContext->_properties.begin(); i != g_lingo->_assemblyContext->_properties.end(); ++i) {
|
||||
(*g_lingo->_methodVars)[i->_key] = kVarInstance;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < args->size(); i++) { // TODO: eliminate argstack
|
||||
g_lingo->codeArg((*args)[i]);
|
||||
}
|
||||
|
||||
uint start = g_lingo->_currentAssembly->size(); // TODO: should always be zero
|
||||
for (uint i = 0; i < stmts->size(); i++) {
|
||||
(*stmts)[i]->compile();
|
||||
}
|
||||
|
||||
g_lingo->code1(LC::c_procret);
|
||||
g_lingo->codeDefine(*name, start, args->size());
|
||||
|
||||
g_lingo->clearArgStack();
|
||||
g_lingo->_indef = false;
|
||||
delete g_lingo->_methodVars;
|
||||
g_lingo->_methodVars = mainMethodVars;
|
||||
}
|
||||
|
||||
/* CmdNode */
|
||||
|
||||
void CmdNode::compile() {
|
||||
for (uint i = 0; i < args->size(); i++) {
|
||||
(*args)[i]->compile();
|
||||
}
|
||||
g_lingo->codeCmd(name, args->size());
|
||||
}
|
||||
|
||||
/* GlobalNode */
|
||||
|
||||
void GlobalNode::compile() {
|
||||
for (uint i = 0; i < names->size(); i++) {
|
||||
g_lingo->registerMethodVar(*(*names)[i], kVarGlobal);
|
||||
}
|
||||
}
|
||||
|
||||
/* PropertyNode */
|
||||
|
||||
void PropertyNode::compile() {
|
||||
for (uint i = 0; i < names->size(); i++) {
|
||||
g_lingo->registerMethodVar(*(*names)[i], kVarProperty);
|
||||
}
|
||||
}
|
||||
|
||||
/* InstanceNode */
|
||||
|
||||
void InstanceNode::compile() {
|
||||
for (uint i = 0; i < names->size(); i++) {
|
||||
g_lingo->registerMethodVar(*(*names)[i], kVarInstance);
|
||||
}
|
||||
}
|
||||
|
||||
/* IntNode */
|
||||
|
||||
void IntNode::compile() {
|
||||
g_lingo->code1(LC::c_intpush);
|
||||
g_lingo->codeInt(val);
|
||||
}
|
||||
|
||||
/* FloatNode */
|
||||
|
||||
void FloatNode::compile() {
|
||||
g_lingo->code1(LC::c_floatpush);
|
||||
g_lingo->codeFloat(val);
|
||||
}
|
||||
|
||||
/* SymbolNode */
|
||||
|
||||
void SymbolNode::compile() {
|
||||
g_lingo->code1(LC::c_symbolpush);
|
||||
g_lingo->codeString(val->c_str());
|
||||
}
|
||||
|
||||
/* StringNode */
|
||||
|
||||
void StringNode::compile() {
|
||||
g_lingo->code1(LC::c_stringpush);
|
||||
g_lingo->codeString(val->c_str());
|
||||
}
|
||||
|
||||
/* FuncNode */
|
||||
|
||||
void FuncNode::compile() {
|
||||
for (uint i = 0; i < args->size(); i++) {
|
||||
(*args)[i]->compile();
|
||||
}
|
||||
g_lingo->codeFunc(name, args->size());
|
||||
}
|
||||
|
||||
/* VarNode */
|
||||
|
||||
void VarNode::compile() {
|
||||
if (g_lingo->_builtinConsts.contains(*name)) {
|
||||
g_lingo->code1(LC::c_constpush);
|
||||
} else {
|
||||
g_lingo->code1(LC::c_eval);
|
||||
}
|
||||
g_lingo->codeString(name->c_str());
|
||||
}
|
||||
|
||||
/* ParensNode */
|
||||
|
||||
void ParensNode::compile() {
|
||||
expr->compile();
|
||||
}
|
||||
|
||||
/* UnaryOpNode */
|
||||
|
||||
void UnaryOpNode::compile() {
|
||||
arg->compile();
|
||||
g_lingo->code1(op);
|
||||
}
|
||||
|
||||
/* BinaryOpNode */
|
||||
|
||||
void BinaryOpNode::compile() {
|
||||
a->compile();
|
||||
b->compile();
|
||||
g_lingo->code1(op);
|
||||
}
|
||||
|
||||
} // End of namespace Director
|
300
engines/director/lingo/lingo-ast.h
Normal file
300
engines/director/lingo/lingo-ast.h
Normal file
@ -0,0 +1,300 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DIRECTOR_LINGO_LINGO_AST_H
|
||||
#define DIRECTOR_LINGO_LINGO_AST_H
|
||||
|
||||
namespace Director {
|
||||
|
||||
struct Node;
|
||||
|
||||
typedef Common::Array<Node *> NodeList;
|
||||
typedef Common::Array<Common::String *> IDList;
|
||||
|
||||
typedef void (*inst)(void);
|
||||
|
||||
template <typename T>
|
||||
void deleteList(Common::Array<T> *list) {
|
||||
for (uint i = 0; i < list->size(); i++) {
|
||||
delete (*list)[i];
|
||||
}
|
||||
delete list;
|
||||
}
|
||||
|
||||
enum NodeType {
|
||||
kScriptNode,
|
||||
kFactoryNode,
|
||||
kHandlerNode,
|
||||
kCmdNode,
|
||||
kGlobalNode,
|
||||
kPropertyNode,
|
||||
kInstanceNode,
|
||||
kIntNode,
|
||||
kFloatNode,
|
||||
kSymbolNode,
|
||||
kStringNode,
|
||||
kFuncNode,
|
||||
kVarNode,
|
||||
kParensNode,
|
||||
kUnaryOpNode,
|
||||
kBinaryOpNode
|
||||
};
|
||||
|
||||
/* Node */
|
||||
|
||||
struct Node {
|
||||
NodeType type;
|
||||
bool isExpression;
|
||||
bool isStatement;
|
||||
|
||||
Node(NodeType t) : type(t), isExpression(false), isStatement(false) {}
|
||||
virtual ~Node() = default;
|
||||
virtual void compile() {}
|
||||
};
|
||||
|
||||
/* ExprNode */
|
||||
|
||||
struct ExprNode : Node {
|
||||
ExprNode(NodeType t) : Node(t) {
|
||||
isExpression = true;
|
||||
}
|
||||
virtual ~ExprNode() = default;
|
||||
};
|
||||
|
||||
/* StmtNode */
|
||||
|
||||
struct StmtNode : Node {
|
||||
StmtNode(NodeType t) : Node(t) {
|
||||
isStatement = true;
|
||||
}
|
||||
virtual ~StmtNode() = default;
|
||||
};
|
||||
|
||||
/* ScriptNode */
|
||||
|
||||
struct ScriptNode : Node {
|
||||
NodeList *nodes;
|
||||
|
||||
ScriptNode(NodeList *nodesIn): Node(kScriptNode), nodes(nodesIn) {}
|
||||
virtual ~ScriptNode() {
|
||||
deleteList(nodes);
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* FactoryNode */
|
||||
|
||||
struct FactoryNode : Node {
|
||||
Common::String *name;
|
||||
NodeList *methods;
|
||||
|
||||
FactoryNode(Common::String *nameIn, NodeList *methodsIn)
|
||||
: Node(kFactoryNode), name(nameIn), methods(methodsIn) {}
|
||||
virtual ~FactoryNode() {
|
||||
delete name;
|
||||
deleteList(methods);
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* HandlerNode */
|
||||
|
||||
struct HandlerNode : Node {
|
||||
Common::String *name;
|
||||
IDList *args;
|
||||
NodeList *stmts;
|
||||
|
||||
HandlerNode(Common::String *nameIn, IDList *argsIn, NodeList *stmtsIn)
|
||||
: Node(kHandlerNode), name(nameIn), args(argsIn), stmts(stmtsIn) {}
|
||||
virtual ~HandlerNode() {
|
||||
delete name;
|
||||
deleteList(args);
|
||||
deleteList(stmts);
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* CmdNode */
|
||||
|
||||
struct CmdNode : StmtNode {
|
||||
Common::String *name;
|
||||
NodeList *args;
|
||||
|
||||
CmdNode(Common::String *nameIn, NodeList *argsIn)
|
||||
: StmtNode(kCmdNode), name(nameIn), args(argsIn) {}
|
||||
virtual ~CmdNode() {
|
||||
delete name;
|
||||
deleteList(args);
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* GlobalNode */
|
||||
|
||||
struct GlobalNode : StmtNode {
|
||||
IDList *names;
|
||||
|
||||
GlobalNode(IDList *namesIn) : StmtNode(kGlobalNode), names(namesIn) {}
|
||||
virtual ~GlobalNode() {
|
||||
delete names;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* PropertyNode */
|
||||
|
||||
struct PropertyNode : StmtNode {
|
||||
IDList *names;
|
||||
|
||||
PropertyNode(IDList *namesIn) : StmtNode(kPropertyNode), names(namesIn) {}
|
||||
virtual ~PropertyNode() {
|
||||
delete names;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* InstanceNode */
|
||||
|
||||
struct InstanceNode : StmtNode {
|
||||
IDList *names;
|
||||
|
||||
InstanceNode(IDList *namesIn) : StmtNode(kInstanceNode), names(namesIn) {}
|
||||
virtual ~InstanceNode() {
|
||||
delete names;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* IntNode */
|
||||
|
||||
struct IntNode : ExprNode {
|
||||
int val;
|
||||
|
||||
IntNode(int valIn) : ExprNode(kIntNode), val(valIn) {}
|
||||
virtual ~IntNode() = default;
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* FloatNode */
|
||||
|
||||
struct FloatNode : ExprNode {
|
||||
double val;
|
||||
|
||||
FloatNode(double valIn) : ExprNode(kFloatNode), val(valIn) {}
|
||||
virtual ~FloatNode() = default;
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* SymbolNode */
|
||||
|
||||
struct SymbolNode : ExprNode {
|
||||
Common::String *val;
|
||||
|
||||
SymbolNode(Common::String *valIn) : ExprNode(kSymbolNode), val(valIn) {}
|
||||
virtual ~SymbolNode() {
|
||||
delete val;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* StringNode */
|
||||
|
||||
struct StringNode : ExprNode {
|
||||
Common::String *val;
|
||||
|
||||
StringNode(Common::String *valIn) : ExprNode(kStringNode), val(valIn) {}
|
||||
virtual ~StringNode() {
|
||||
delete val;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* FuncNode */
|
||||
|
||||
struct FuncNode : StmtNode {
|
||||
Common::String *name;
|
||||
NodeList *args;
|
||||
|
||||
FuncNode(Common::String *nameIn, NodeList *argsIn)
|
||||
: StmtNode(kFuncNode), name(nameIn), args(argsIn) {}
|
||||
virtual ~FuncNode() {
|
||||
delete name;
|
||||
deleteList(args);
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* VarNode */
|
||||
|
||||
struct VarNode : ExprNode {
|
||||
Common::String *name;
|
||||
|
||||
VarNode(Common::String *nameIn) : ExprNode(kVarNode), name(nameIn) {}
|
||||
virtual ~VarNode() {
|
||||
delete name;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* ParensNode */
|
||||
|
||||
struct ParensNode : ExprNode {
|
||||
Node *expr;
|
||||
|
||||
ParensNode(Node *exprIn) : ExprNode(kParensNode), expr(exprIn) {}
|
||||
virtual ~ParensNode() {
|
||||
delete expr;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* UnaryOpNode */
|
||||
|
||||
struct UnaryOpNode : ExprNode {
|
||||
inst op;
|
||||
Node *arg;
|
||||
|
||||
UnaryOpNode(inst opIn, Node *argIn) : ExprNode(kUnaryOpNode), op(opIn), arg(argIn) {}
|
||||
virtual ~UnaryOpNode() {
|
||||
delete arg;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
/* BinaryOpNode */
|
||||
|
||||
struct BinaryOpNode : ExprNode {
|
||||
inst op;
|
||||
Node *a;
|
||||
Node *b;
|
||||
|
||||
BinaryOpNode(inst opIn, Node *aIn, Node *bIn) : ExprNode(kBinaryOpNode), op(opIn), a(aIn), b(bIn) {}
|
||||
virtual ~BinaryOpNode() {
|
||||
delete a;
|
||||
delete b;
|
||||
}
|
||||
virtual void compile();
|
||||
};
|
||||
|
||||
} // End of namespace Director
|
||||
|
||||
#endif
|
@ -264,6 +264,17 @@ void Lingo::processIf(int toplabel, int endlabel) {
|
||||
}
|
||||
}
|
||||
|
||||
void Lingo::registerMethodVar(const Common::String &name, VarType type) {
|
||||
if (!g_lingo->_methodVars->contains(name)) {
|
||||
(*g_lingo->_methodVars)[name] = type;
|
||||
if (type == kVarProperty || type == kVarInstance) {
|
||||
g_lingo->_assemblyContext->_properties[name] = Datum();
|
||||
} else if (type == kVarGlobal) {
|
||||
g_lingo->varCreate(name, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lingo::varCreate(const Common::String &name, bool global, DatumHash *localvars) {
|
||||
if (localvars == nullptr) {
|
||||
localvars = _localvars;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
||||
/* A Bison parser, made by GNU Bison 3.7.1. */
|
||||
/* A Bison parser, made by GNU Bison 3.7.6. */
|
||||
|
||||
/* Bison interface for Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
|
||||
Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
@ -16,7 +16,7 @@
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
@ -54,93 +54,81 @@ extern int yydebug;
|
||||
YYEOF = 0, /* "end of file" */
|
||||
YYerror = 256, /* error */
|
||||
YYUNDEF = 257, /* "invalid token" */
|
||||
UNARY = 258, /* UNARY */
|
||||
VOID = 259, /* VOID */
|
||||
VAR = 260, /* VAR */
|
||||
POINT = 261, /* POINT */
|
||||
RECT = 262, /* RECT */
|
||||
ARRAY = 263, /* ARRAY */
|
||||
OBJECT = 264, /* OBJECT */
|
||||
LEXERROR = 265, /* LEXERROR */
|
||||
PARRAY = 266, /* PARRAY */
|
||||
CASTREF = 267, /* CASTREF */
|
||||
FIELDREF = 268, /* FIELDREF */
|
||||
CHUNKREF = 269, /* CHUNKREF */
|
||||
INT = 270, /* INT */
|
||||
ARGC = 271, /* ARGC */
|
||||
ARGCNORET = 272, /* ARGCNORET */
|
||||
THEENTITY = 273, /* THEENTITY */
|
||||
THEENTITYWITHID = 274, /* THEENTITYWITHID */
|
||||
THEMENUITEMENTITY = 275, /* THEMENUITEMENTITY */
|
||||
THEMENUITEMSENTITY = 276, /* THEMENUITEMSENTITY */
|
||||
FLOAT = 277, /* FLOAT */
|
||||
THEFUNC = 278, /* THEFUNC */
|
||||
THEFUNCINOF = 279, /* THEFUNCINOF */
|
||||
VARID = 280, /* VARID */
|
||||
STRING = 281, /* STRING */
|
||||
SYMBOL = 282, /* SYMBOL */
|
||||
ENDCLAUSE = 283, /* ENDCLAUSE */
|
||||
tPLAYACCEL = 284, /* tPLAYACCEL */
|
||||
tMETHOD = 285, /* tMETHOD */
|
||||
THEOBJECTPROP = 286, /* THEOBJECTPROP */
|
||||
tCAST = 287, /* tCAST */
|
||||
tFIELD = 288, /* tFIELD */
|
||||
tSCRIPT = 289, /* tSCRIPT */
|
||||
tWINDOW = 290, /* tWINDOW */
|
||||
tDOWN = 291, /* tDOWN */
|
||||
tELSE = 292, /* tELSE */
|
||||
tELSIF = 293, /* tELSIF */
|
||||
tEXIT = 294, /* tEXIT */
|
||||
tGLOBAL = 295, /* tGLOBAL */
|
||||
tGO = 296, /* tGO */
|
||||
tGOLOOP = 297, /* tGOLOOP */
|
||||
tIF = 298, /* tIF */
|
||||
tIN = 299, /* tIN */
|
||||
tINTO = 300, /* tINTO */
|
||||
tMACRO = 301, /* tMACRO */
|
||||
tMOVIE = 302, /* tMOVIE */
|
||||
tNEXT = 303, /* tNEXT */
|
||||
tOF = 304, /* tOF */
|
||||
tPREVIOUS = 305, /* tPREVIOUS */
|
||||
tPUT = 306, /* tPUT */
|
||||
tREPEAT = 307, /* tREPEAT */
|
||||
tSET = 308, /* tSET */
|
||||
tTHEN = 309, /* tTHEN */
|
||||
tTO = 310, /* tTO */
|
||||
tWHEN = 311, /* tWHEN */
|
||||
tWITH = 312, /* tWITH */
|
||||
tWHILE = 313, /* tWHILE */
|
||||
tFACTORY = 314, /* tFACTORY */
|
||||
tOPEN = 315, /* tOPEN */
|
||||
tPLAY = 316, /* tPLAY */
|
||||
tINSTANCE = 317, /* tINSTANCE */
|
||||
tGE = 318, /* tGE */
|
||||
tLE = 319, /* tLE */
|
||||
tEQ = 320, /* tEQ */
|
||||
tNEQ = 321, /* tNEQ */
|
||||
tAND = 322, /* tAND */
|
||||
tOR = 323, /* tOR */
|
||||
tNOT = 324, /* tNOT */
|
||||
tMOD = 325, /* tMOD */
|
||||
tAFTER = 326, /* tAFTER */
|
||||
tBEFORE = 327, /* tBEFORE */
|
||||
tCONCAT = 328, /* tCONCAT */
|
||||
tCONTAINS = 329, /* tCONTAINS */
|
||||
tSTARTS = 330, /* tSTARTS */
|
||||
tCHAR = 331, /* tCHAR */
|
||||
tITEM = 332, /* tITEM */
|
||||
tLINE = 333, /* tLINE */
|
||||
tWORD = 334, /* tWORD */
|
||||
tSPRITE = 335, /* tSPRITE */
|
||||
tINTERSECTS = 336, /* tINTERSECTS */
|
||||
tWITHIN = 337, /* tWITHIN */
|
||||
tTELL = 338, /* tTELL */
|
||||
tPROPERTY = 339, /* tPROPERTY */
|
||||
tON = 340, /* tON */
|
||||
tENDIF = 341, /* tENDIF */
|
||||
tENDREPEAT = 342, /* tENDREPEAT */
|
||||
tENDTELL = 343, /* tENDTELL */
|
||||
tASSERTERROR = 344 /* tASSERTERROR */
|
||||
tUNARY = 258, /* tUNARY */
|
||||
tLEXERROR = 259, /* tLEXERROR */
|
||||
tINT = 260, /* tINT */
|
||||
tTHEENTITY = 261, /* tTHEENTITY */
|
||||
tTHEENTITYWITHID = 262, /* tTHEENTITYWITHID */
|
||||
tTHEMENUITEMENTITY = 263, /* tTHEMENUITEMENTITY */
|
||||
tTHEMENUITEMSENTITY = 264, /* tTHEMENUITEMSENTITY */
|
||||
tFLOAT = 265, /* tFLOAT */
|
||||
tTHEFUNC = 266, /* tTHEFUNC */
|
||||
tTHEFUNCINOF = 267, /* tTHEFUNCINOF */
|
||||
tVARID = 268, /* tVARID */
|
||||
tSTRING = 269, /* tSTRING */
|
||||
tSYMBOL = 270, /* tSYMBOL */
|
||||
tENDCLAUSE = 271, /* tENDCLAUSE */
|
||||
tPLAYACCEL = 272, /* tPLAYACCEL */
|
||||
tTHEOBJECTPROP = 273, /* tTHEOBJECTPROP */
|
||||
tCAST = 274, /* tCAST */
|
||||
tFIELD = 275, /* tFIELD */
|
||||
tSCRIPT = 276, /* tSCRIPT */
|
||||
tWINDOW = 277, /* tWINDOW */
|
||||
tDOWN = 278, /* tDOWN */
|
||||
tELSE = 279, /* tELSE */
|
||||
tELSIF = 280, /* tELSIF */
|
||||
tEXIT = 281, /* tEXIT */
|
||||
tGLOBAL = 282, /* tGLOBAL */
|
||||
tGO = 283, /* tGO */
|
||||
tGOLOOP = 284, /* tGOLOOP */
|
||||
tIF = 285, /* tIF */
|
||||
tIN = 286, /* tIN */
|
||||
tINTO = 287, /* tINTO */
|
||||
tMACRO = 288, /* tMACRO */
|
||||
tMOVIE = 289, /* tMOVIE */
|
||||
tNEXT = 290, /* tNEXT */
|
||||
tOF = 291, /* tOF */
|
||||
tPREVIOUS = 292, /* tPREVIOUS */
|
||||
tPUT = 293, /* tPUT */
|
||||
tREPEAT = 294, /* tREPEAT */
|
||||
tSET = 295, /* tSET */
|
||||
tTHEN = 296, /* tTHEN */
|
||||
tTO = 297, /* tTO */
|
||||
tWHEN = 298, /* tWHEN */
|
||||
tWITH = 299, /* tWITH */
|
||||
tWHILE = 300, /* tWHILE */
|
||||
tFACTORY = 301, /* tFACTORY */
|
||||
tOPEN = 302, /* tOPEN */
|
||||
tPLAY = 303, /* tPLAY */
|
||||
tINSTANCE = 304, /* tINSTANCE */
|
||||
tGE = 305, /* tGE */
|
||||
tLE = 306, /* tLE */
|
||||
tEQ = 307, /* tEQ */
|
||||
tNEQ = 308, /* tNEQ */
|
||||
tAND = 309, /* tAND */
|
||||
tOR = 310, /* tOR */
|
||||
tNOT = 311, /* tNOT */
|
||||
tMOD = 312, /* tMOD */
|
||||
tAFTER = 313, /* tAFTER */
|
||||
tBEFORE = 314, /* tBEFORE */
|
||||
tCONCAT = 315, /* tCONCAT */
|
||||
tCONTAINS = 316, /* tCONTAINS */
|
||||
tSTARTS = 317, /* tSTARTS */
|
||||
tCHAR = 318, /* tCHAR */
|
||||
tITEM = 319, /* tITEM */
|
||||
tLINE = 320, /* tLINE */
|
||||
tWORD = 321, /* tWORD */
|
||||
tSPRITE = 322, /* tSPRITE */
|
||||
tINTERSECTS = 323, /* tINTERSECTS */
|
||||
tWITHIN = 324, /* tWITHIN */
|
||||
tTELL = 325, /* tTELL */
|
||||
tPROPERTY = 326, /* tPROPERTY */
|
||||
tON = 327, /* tON */
|
||||
tMETHOD = 328, /* tMETHOD */
|
||||
tENDIF = 329, /* tENDIF */
|
||||
tENDREPEAT = 330, /* tENDREPEAT */
|
||||
tENDTELL = 331, /* tENDTELL */
|
||||
tASSERTERROR = 332 /* tASSERTERROR */
|
||||
};
|
||||
typedef enum yytokentype yytoken_kind_t;
|
||||
#endif
|
||||
@ -149,22 +137,23 @@ extern int yydebug;
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
union YYSTYPE
|
||||
{
|
||||
#line 180 "engines/director/lingo/lingo-gr.y"
|
||||
#line 109 "engines/director/lingo/lingo-gr.y"
|
||||
|
||||
Common::String *s;
|
||||
int i;
|
||||
double f;
|
||||
int e[2]; // Entity + field
|
||||
int code;
|
||||
int narg; /* number of arguments */
|
||||
Director::DatumArray *arr;
|
||||
|
||||
struct {
|
||||
Common::String *obj;
|
||||
Common::String *prop;
|
||||
} objectprop;
|
||||
|
||||
#line 168 "engines/director/lingo/lingo-gr.h"
|
||||
Director::IDList *idlist;
|
||||
Director::Node *node;
|
||||
Director::NodeList *nodelist;
|
||||
|
||||
#line 157 "engines/director/lingo/lingo-gr.h"
|
||||
|
||||
};
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -756,6 +756,7 @@ char *yytext;
|
||||
|
||||
#include "director/director.h"
|
||||
#include "director/lingo/lingo.h"
|
||||
#include "director/lingo/lingo-ast.h"
|
||||
#include "director/lingo/lingo-gr.h"
|
||||
#include "director/lingo/lingo-the.h"
|
||||
|
||||
@ -812,8 +813,8 @@ static Common::String *cleanupString(const char *s) {
|
||||
return res;
|
||||
}
|
||||
|
||||
#line 815 "engines/director/lingo/lingo-lex.cpp"
|
||||
#line 816 "engines/director/lingo/lingo-lex.cpp"
|
||||
#line 817 "engines/director/lingo/lingo-lex.cpp"
|
||||
|
||||
#define INITIAL 0
|
||||
|
||||
@ -1033,10 +1034,10 @@ YY_DECL
|
||||
}
|
||||
|
||||
{
|
||||
#line 105 "engines/director/lingo/lingo-lex.l"
|
||||
#line 106 "engines/director/lingo/lingo-lex.l"
|
||||
|
||||
|
||||
#line 1039 "engines/director/lingo/lingo-lex.cpp"
|
||||
#line 1040 "engines/director/lingo/lingo-lex.cpp"
|
||||
|
||||
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
|
||||
{
|
||||
@ -1092,67 +1093,67 @@ do_action: /* This label is used only to access EOF actions. */
|
||||
|
||||
case 1:
|
||||
YY_RULE_SETUP
|
||||
#line 107 "engines/director/lingo/lingo-lex.l"
|
||||
#line 108 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); }
|
||||
YY_BREAK
|
||||
case 2:
|
||||
YY_RULE_SETUP
|
||||
#line 109 "engines/director/lingo/lingo-lex.l"
|
||||
#line 110 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); yylval.s = new Common::String(yytext + 1); return SYMBOL; } // D3, skip '#'
|
||||
YY_BREAK
|
||||
case 3:
|
||||
YY_RULE_SETUP
|
||||
#line 111 "engines/director/lingo/lingo-lex.l"
|
||||
#line 112 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tAFTER; } // D3
|
||||
YY_BREAK
|
||||
case 4:
|
||||
YY_RULE_SETUP
|
||||
#line 112 "engines/director/lingo/lingo-lex.l"
|
||||
#line 113 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tAND; }
|
||||
YY_BREAK
|
||||
case 5:
|
||||
YY_RULE_SETUP
|
||||
#line 113 "engines/director/lingo/lingo-lex.l"
|
||||
#line 114 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tBEFORE; } // D3
|
||||
YY_BREAK
|
||||
case 6:
|
||||
YY_RULE_SETUP
|
||||
#line 114 "engines/director/lingo/lingo-lex.l"
|
||||
#line 115 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tCAST; }
|
||||
YY_BREAK
|
||||
case 7:
|
||||
YY_RULE_SETUP
|
||||
#line 115 "engines/director/lingo/lingo-lex.l"
|
||||
#line 116 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tCHAR; } // D3
|
||||
YY_BREAK
|
||||
case 8:
|
||||
YY_RULE_SETUP
|
||||
#line 116 "engines/director/lingo/lingo-lex.l"
|
||||
#line 117 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tCONTAINS; }
|
||||
YY_BREAK
|
||||
case 9:
|
||||
YY_RULE_SETUP
|
||||
#line 117 "engines/director/lingo/lingo-lex.l"
|
||||
#line 118 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tDOWN; }
|
||||
YY_BREAK
|
||||
case 10:
|
||||
YY_RULE_SETUP
|
||||
#line 118 "engines/director/lingo/lingo-lex.l"
|
||||
#line 119 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tIF; }
|
||||
YY_BREAK
|
||||
case 11:
|
||||
YY_RULE_SETUP
|
||||
#line 119 "engines/director/lingo/lingo-lex.l"
|
||||
#line 120 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tELSIF; }
|
||||
YY_BREAK
|
||||
case 12:
|
||||
YY_RULE_SETUP
|
||||
#line 120 "engines/director/lingo/lingo-lex.l"
|
||||
#line 121 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tELSE; }
|
||||
YY_BREAK
|
||||
case 13:
|
||||
YY_RULE_SETUP
|
||||
#line 121 "engines/director/lingo/lingo-lex.l"
|
||||
#line 122 "engines/director/lingo/lingo-lex.l"
|
||||
{
|
||||
count();
|
||||
|
||||
@ -1169,182 +1170,182 @@ YY_RULE_SETUP
|
||||
|
||||
yylval.s = new Common::String(ptr);
|
||||
|
||||
return ENDCLAUSE;
|
||||
return tENDCLAUSE;
|
||||
}
|
||||
YY_BREAK
|
||||
case 14:
|
||||
YY_RULE_SETUP
|
||||
#line 139 "engines/director/lingo/lingo-lex.l"
|
||||
#line 140 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tFACTORY; }
|
||||
YY_BREAK
|
||||
case 15:
|
||||
YY_RULE_SETUP
|
||||
#line 140 "engines/director/lingo/lingo-lex.l"
|
||||
#line 141 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tEXIT; }
|
||||
YY_BREAK
|
||||
case 16:
|
||||
YY_RULE_SETUP
|
||||
#line 141 "engines/director/lingo/lingo-lex.l"
|
||||
#line 142 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tFIELD; }
|
||||
YY_BREAK
|
||||
case 17:
|
||||
YY_RULE_SETUP
|
||||
#line 142 "engines/director/lingo/lingo-lex.l"
|
||||
#line 143 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tGLOBAL; }
|
||||
YY_BREAK
|
||||
case 18:
|
||||
YY_RULE_SETUP
|
||||
#line 143 "engines/director/lingo/lingo-lex.l"
|
||||
#line 144 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tGO; }
|
||||
YY_BREAK
|
||||
case 19:
|
||||
YY_RULE_SETUP
|
||||
#line 144 "engines/director/lingo/lingo-lex.l"
|
||||
#line 145 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tGO; }
|
||||
YY_BREAK
|
||||
case 20:
|
||||
YY_RULE_SETUP
|
||||
#line 145 "engines/director/lingo/lingo-lex.l"
|
||||
#line 146 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tGOLOOP; }
|
||||
YY_BREAK
|
||||
case 21:
|
||||
YY_RULE_SETUP
|
||||
#line 146 "engines/director/lingo/lingo-lex.l"
|
||||
#line 147 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tINSTANCE; }
|
||||
YY_BREAK
|
||||
case 22:
|
||||
YY_RULE_SETUP
|
||||
#line 147 "engines/director/lingo/lingo-lex.l"
|
||||
#line 148 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tINTERSECTS;}
|
||||
YY_BREAK
|
||||
case 23:
|
||||
YY_RULE_SETUP
|
||||
#line 148 "engines/director/lingo/lingo-lex.l"
|
||||
#line 149 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tINTO; }
|
||||
YY_BREAK
|
||||
case 24:
|
||||
YY_RULE_SETUP
|
||||
#line 149 "engines/director/lingo/lingo-lex.l"
|
||||
#line 150 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tIN; }
|
||||
YY_BREAK
|
||||
case 25:
|
||||
YY_RULE_SETUP
|
||||
#line 150 "engines/director/lingo/lingo-lex.l"
|
||||
#line 151 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tITEM; }
|
||||
YY_BREAK
|
||||
case 26:
|
||||
YY_RULE_SETUP
|
||||
#line 151 "engines/director/lingo/lingo-lex.l"
|
||||
#line 152 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tLINE; }
|
||||
YY_BREAK
|
||||
case 27:
|
||||
YY_RULE_SETUP
|
||||
#line 152 "engines/director/lingo/lingo-lex.l"
|
||||
#line 153 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tMACRO;; }
|
||||
YY_BREAK
|
||||
case 28:
|
||||
YY_RULE_SETUP
|
||||
#line 153 "engines/director/lingo/lingo-lex.l"
|
||||
#line 154 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tMETHOD; }
|
||||
YY_BREAK
|
||||
case 29:
|
||||
YY_RULE_SETUP
|
||||
#line 154 "engines/director/lingo/lingo-lex.l"
|
||||
#line 155 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tMOD;}
|
||||
YY_BREAK
|
||||
case 30:
|
||||
YY_RULE_SETUP
|
||||
#line 155 "engines/director/lingo/lingo-lex.l"
|
||||
#line 156 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tMOVIE; }
|
||||
YY_BREAK
|
||||
case 31:
|
||||
YY_RULE_SETUP
|
||||
#line 156 "engines/director/lingo/lingo-lex.l"
|
||||
#line 157 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tNEXT; }
|
||||
YY_BREAK
|
||||
case 32:
|
||||
YY_RULE_SETUP
|
||||
#line 157 "engines/director/lingo/lingo-lex.l"
|
||||
#line 158 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tNOT; }
|
||||
YY_BREAK
|
||||
case 33:
|
||||
YY_RULE_SETUP
|
||||
#line 158 "engines/director/lingo/lingo-lex.l"
|
||||
#line 159 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tOF; }
|
||||
YY_BREAK
|
||||
case 34:
|
||||
YY_RULE_SETUP
|
||||
#line 159 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tON } // D3
|
||||
#line 160 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tON; } // D3
|
||||
YY_BREAK
|
||||
case 35:
|
||||
YY_RULE_SETUP
|
||||
#line 160 "engines/director/lingo/lingo-lex.l"
|
||||
#line 161 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tOPEN; }
|
||||
YY_BREAK
|
||||
case 36:
|
||||
YY_RULE_SETUP
|
||||
#line 161 "engines/director/lingo/lingo-lex.l"
|
||||
#line 162 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tOR; }
|
||||
YY_BREAK
|
||||
case 37:
|
||||
YY_RULE_SETUP
|
||||
#line 162 "engines/director/lingo/lingo-lex.l"
|
||||
#line 163 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tPLAY; }
|
||||
YY_BREAK
|
||||
case 38:
|
||||
YY_RULE_SETUP
|
||||
#line 163 "engines/director/lingo/lingo-lex.l"
|
||||
#line 164 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tPLAY; }
|
||||
YY_BREAK
|
||||
case 39:
|
||||
YY_RULE_SETUP
|
||||
#line 164 "engines/director/lingo/lingo-lex.l"
|
||||
#line 165 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tPLAYACCEL; }
|
||||
YY_BREAK
|
||||
case 40:
|
||||
YY_RULE_SETUP
|
||||
#line 165 "engines/director/lingo/lingo-lex.l"
|
||||
#line 166 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tPREVIOUS; }
|
||||
YY_BREAK
|
||||
case 41:
|
||||
YY_RULE_SETUP
|
||||
#line 166 "engines/director/lingo/lingo-lex.l"
|
||||
#line 167 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tPROPERTY; } // D4
|
||||
YY_BREAK
|
||||
case 42:
|
||||
YY_RULE_SETUP
|
||||
#line 167 "engines/director/lingo/lingo-lex.l"
|
||||
#line 168 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tPUT; }
|
||||
YY_BREAK
|
||||
case 43:
|
||||
YY_RULE_SETUP
|
||||
#line 168 "engines/director/lingo/lingo-lex.l"
|
||||
#line 169 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tREPEAT; }
|
||||
YY_BREAK
|
||||
case 44:
|
||||
YY_RULE_SETUP
|
||||
#line 169 "engines/director/lingo/lingo-lex.l"
|
||||
#line 170 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tSCRIPT; }
|
||||
YY_BREAK
|
||||
case 45:
|
||||
YY_RULE_SETUP
|
||||
#line 170 "engines/director/lingo/lingo-lex.l"
|
||||
#line 171 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tSET; }
|
||||
YY_BREAK
|
||||
case 46:
|
||||
YY_RULE_SETUP
|
||||
#line 171 "engines/director/lingo/lingo-lex.l"
|
||||
#line 172 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tSTARTS; }
|
||||
YY_BREAK
|
||||
case 47:
|
||||
YY_RULE_SETUP
|
||||
#line 172 "engines/director/lingo/lingo-lex.l"
|
||||
#line 173 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tTELL; }
|
||||
YY_BREAK
|
||||
case 48:
|
||||
YY_RULE_SETUP
|
||||
#line 173 "engines/director/lingo/lingo-lex.l"
|
||||
#line 174 "engines/director/lingo/lingo-lex.l"
|
||||
{
|
||||
count();
|
||||
|
||||
@ -1368,22 +1369,22 @@ YY_RULE_SETUP
|
||||
yylval.e[0] = kTheMenuItems;
|
||||
yylval.e[1] = g_lingo->_theEntityFields[key]->field;
|
||||
|
||||
return THEMENUITEMSENTITY;
|
||||
return tTHEMENUITEMSENTITY;
|
||||
}
|
||||
|
||||
yylval.s = new Common::String(Common::String::format("numberOf%s", field.c_str()));
|
||||
|
||||
if (g_lingo->_builtinFuncs.contains(*yylval.s)) {
|
||||
return THEFUNCINOF;
|
||||
return tTHEFUNCINOF;
|
||||
} else {
|
||||
warning("LEXER: Unhandled chunk expression '%s'", yylval.s->c_str());
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
}
|
||||
YY_BREAK
|
||||
case 49:
|
||||
YY_RULE_SETUP
|
||||
#line 208 "engines/director/lingo/lingo-lex.l"
|
||||
#line 209 "engines/director/lingo/lingo-lex.l"
|
||||
{
|
||||
count();
|
||||
|
||||
@ -1400,16 +1401,16 @@ YY_RULE_SETUP
|
||||
yylval.s = new Common::String(Common::String::format("last%sOf", field.c_str()));
|
||||
|
||||
if (g_lingo->_builtinFuncs.contains(*yylval.s)) {
|
||||
return THEFUNCINOF;
|
||||
return tTHEFUNCINOF;
|
||||
} else {
|
||||
warning("LEXER: Unhandled chunk expression '%s'", yylval.s->c_str());
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
}
|
||||
YY_BREAK
|
||||
case 50:
|
||||
YY_RULE_SETUP
|
||||
#line 230 "engines/director/lingo/lingo-lex.l"
|
||||
#line 231 "engines/director/lingo/lingo-lex.l"
|
||||
{
|
||||
count();
|
||||
|
||||
@ -1434,12 +1435,12 @@ YY_RULE_SETUP
|
||||
|
||||
if (!g_lingo->_theEntityFields.contains(field)) {
|
||||
warning("LEXER: Unhandled the field %s of %s", field.c_str(), ptr);
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
|
||||
if (g_lingo->_theEntityFields[field]->entity != g_lingo->_theEntities[ptr]->entity) {
|
||||
warning("LEXER: Unsupported field '%s' for entity '%s'", field.c_str(), ptr);
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
|
||||
yylval.e[0] = g_lingo->_theEntities[ptr]->entity;
|
||||
@ -1447,12 +1448,12 @@ YY_RULE_SETUP
|
||||
|
||||
// the <field> of menuItem <expr>" of menu <expr>
|
||||
if (g_lingo->_theEntityFields[field]->entity == kTheMenuItem)
|
||||
return THEMENUITEMENTITY;
|
||||
return tTHEMENUITEMENTITY;
|
||||
|
||||
if (g_lingo->_theEntities[ptr]->hasId)
|
||||
return THEENTITYWITHID;
|
||||
return tTHEENTITYWITHID;
|
||||
else
|
||||
return THEENTITY;
|
||||
return tTHEENTITY;
|
||||
} else {
|
||||
if (g_director->getVersion() >= 400) {
|
||||
Common::String key = Common::String::format("%d%s", g_lingo->_objectEntityId, field.c_str());
|
||||
@ -1460,7 +1461,7 @@ YY_RULE_SETUP
|
||||
yylval.objectprop.obj = new Common::String(ptr);
|
||||
yylval.objectprop.prop = new Common::String(field);
|
||||
|
||||
return THEOBJECTPROP;
|
||||
return tTHEOBJECTPROP;
|
||||
} else if (g_lingo->_builtinFuncs.contains(field)) { // Let's hope they don't do it in D4+
|
||||
if (g_lingo->_builtinFuncs[field].nargs == 1 && g_lingo->_builtinFuncs[field].maxArgs == 1) {
|
||||
yylval.s = new Common::String(field);
|
||||
@ -1476,7 +1477,7 @@ YY_RULE_SETUP
|
||||
|
||||
unput(' '); unput('f'); unput('o');
|
||||
|
||||
return THEFUNC;
|
||||
return tTHEFUNC;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1486,7 +1487,7 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 51:
|
||||
YY_RULE_SETUP
|
||||
#line 303 "engines/director/lingo/lingo-lex.l"
|
||||
#line 304 "engines/director/lingo/lingo-lex.l"
|
||||
{
|
||||
count();
|
||||
|
||||
@ -1505,26 +1506,26 @@ YY_RULE_SETUP
|
||||
|
||||
if (!g_lingo->_theEntityFields.contains(field)) {
|
||||
warning("LEXER: Unhandled the field %s", ptr);
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
|
||||
if (g_lingo->_theEntityFields[field]->entity != g_lingo->_theEntities[ptr]->entity) {
|
||||
warning("LEXER: Unsupported field '%s' for entity '%s'", field.c_str(), ptr);
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
|
||||
yylval.e[0] = g_lingo->_theEntities[ptr]->entity;
|
||||
yylval.e[1] = g_lingo->_theEntityFields[field]->field;
|
||||
|
||||
if (g_lingo->_theEntities[ptr]->hasId)
|
||||
return THEENTITYWITHID;
|
||||
return tTHEENTITYWITHID;
|
||||
else
|
||||
return THEENTITY;
|
||||
return tTHEENTITY;
|
||||
}
|
||||
YY_BREAK
|
||||
case 52:
|
||||
YY_RULE_SETUP
|
||||
#line 337 "engines/director/lingo/lingo-lex.l"
|
||||
#line 338 "engines/director/lingo/lingo-lex.l"
|
||||
{
|
||||
count();
|
||||
|
||||
@ -1537,15 +1538,15 @@ YY_RULE_SETUP
|
||||
yylval.e[1] = 0; // No field
|
||||
|
||||
if (g_lingo->_theEntities[ptr]->hasId)
|
||||
return THEENTITYWITHID;
|
||||
return tTHEENTITYWITHID;
|
||||
else
|
||||
return THEENTITY;
|
||||
return tTHEENTITY;
|
||||
}
|
||||
|
||||
if (g_lingo->_builtinFuncs.contains(ptr)) {
|
||||
if (g_lingo->_builtinFuncs[ptr].nargs == 1 && g_lingo->_builtinFuncs[ptr].maxArgs == 1) {
|
||||
yylval.s = new Common::String(ptr);
|
||||
return THEFUNC;
|
||||
return tTHEFUNC;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1554,126 +1555,126 @@ YY_RULE_SETUP
|
||||
YY_BREAK
|
||||
case 53:
|
||||
YY_RULE_SETUP
|
||||
#line 363 "engines/director/lingo/lingo-lex.l"
|
||||
#line 364 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tTHEN; }
|
||||
YY_BREAK
|
||||
case 54:
|
||||
YY_RULE_SETUP
|
||||
#line 364 "engines/director/lingo/lingo-lex.l"
|
||||
#line 365 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tTO; }
|
||||
YY_BREAK
|
||||
case 55:
|
||||
YY_RULE_SETUP
|
||||
#line 365 "engines/director/lingo/lingo-lex.l"
|
||||
#line 366 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tASSERTERROR; }
|
||||
YY_BREAK
|
||||
case 56:
|
||||
YY_RULE_SETUP
|
||||
#line 366 "engines/director/lingo/lingo-lex.l"
|
||||
#line 367 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tSPRITE; }
|
||||
YY_BREAK
|
||||
case 57:
|
||||
YY_RULE_SETUP
|
||||
#line 367 "engines/director/lingo/lingo-lex.l"
|
||||
#line 368 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tWITH; }
|
||||
YY_BREAK
|
||||
case 58:
|
||||
YY_RULE_SETUP
|
||||
#line 368 "engines/director/lingo/lingo-lex.l"
|
||||
#line 369 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tWITHIN; }
|
||||
YY_BREAK
|
||||
case 59:
|
||||
YY_RULE_SETUP
|
||||
#line 369 "engines/director/lingo/lingo-lex.l"
|
||||
#line 370 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tWHEN; }
|
||||
YY_BREAK
|
||||
case 60:
|
||||
YY_RULE_SETUP
|
||||
#line 370 "engines/director/lingo/lingo-lex.l"
|
||||
#line 371 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tWHILE; }
|
||||
YY_BREAK
|
||||
case 61:
|
||||
YY_RULE_SETUP
|
||||
#line 371 "engines/director/lingo/lingo-lex.l"
|
||||
#line 372 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tWINDOW; }
|
||||
YY_BREAK
|
||||
case 62:
|
||||
YY_RULE_SETUP
|
||||
#line 372 "engines/director/lingo/lingo-lex.l"
|
||||
#line 373 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tWORD; }
|
||||
YY_BREAK
|
||||
case 63:
|
||||
YY_RULE_SETUP
|
||||
#line 374 "engines/director/lingo/lingo-lex.l"
|
||||
#line 375 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tNEQ; }
|
||||
YY_BREAK
|
||||
case 64:
|
||||
YY_RULE_SETUP
|
||||
#line 375 "engines/director/lingo/lingo-lex.l"
|
||||
#line 376 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tGE; }
|
||||
YY_BREAK
|
||||
case 65:
|
||||
YY_RULE_SETUP
|
||||
#line 376 "engines/director/lingo/lingo-lex.l"
|
||||
#line 377 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tLE; }
|
||||
YY_BREAK
|
||||
case 66:
|
||||
YY_RULE_SETUP
|
||||
#line 377 "engines/director/lingo/lingo-lex.l"
|
||||
#line 378 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tCONCAT; }
|
||||
YY_BREAK
|
||||
case 67:
|
||||
YY_RULE_SETUP
|
||||
#line 378 "engines/director/lingo/lingo-lex.l"
|
||||
#line 379 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return tEQ; }
|
||||
YY_BREAK
|
||||
case 68:
|
||||
YY_RULE_SETUP
|
||||
#line 380 "engines/director/lingo/lingo-lex.l"
|
||||
#line 381 "engines/director/lingo/lingo-lex.l"
|
||||
{
|
||||
count();
|
||||
yylval.s = new Common::String(yytext);
|
||||
|
||||
return VARID;
|
||||
return tVARID;
|
||||
}
|
||||
YY_BREAK
|
||||
case 69:
|
||||
YY_RULE_SETUP
|
||||
#line 386 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); yylval.f = atof(yytext); return FLOAT; }
|
||||
#line 387 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); yylval.f = atof(yytext); return tFLOAT; }
|
||||
YY_BREAK
|
||||
case 70:
|
||||
YY_RULE_SETUP
|
||||
#line 387 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); yylval.i = strtol(yytext, NULL, 10); return INT; }
|
||||
#line 388 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); yylval.i = strtol(yytext, NULL, 10); return tINT; }
|
||||
YY_BREAK
|
||||
case 71:
|
||||
YY_RULE_SETUP
|
||||
#line 388 "engines/director/lingo/lingo-lex.l"
|
||||
#line 389 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return *yytext; }
|
||||
YY_BREAK
|
||||
case 72:
|
||||
/* rule 72 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 389 "engines/director/lingo/lingo-lex.l"
|
||||
#line 390 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); return '\n'; }
|
||||
YY_BREAK
|
||||
case 73:
|
||||
YY_RULE_SETUP
|
||||
#line 390 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); yylval.s = cleanupString(&yytext[1]); yylval.s->deleteLastChar(); return STRING; }
|
||||
#line 391 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); yylval.s = cleanupString(&yytext[1]); yylval.s->deleteLastChar(); return tSTRING; }
|
||||
YY_BREAK
|
||||
case 74:
|
||||
YY_RULE_SETUP
|
||||
#line 391 "engines/director/lingo/lingo-lex.l"
|
||||
#line 392 "engines/director/lingo/lingo-lex.l"
|
||||
{ count(); }
|
||||
YY_BREAK
|
||||
case 75:
|
||||
YY_RULE_SETUP
|
||||
#line 393 "engines/director/lingo/lingo-lex.l"
|
||||
#line 394 "engines/director/lingo/lingo-lex.l"
|
||||
ECHO;
|
||||
YY_BREAK
|
||||
#line 1676 "engines/director/lingo/lingo-lex.cpp"
|
||||
#line 1677 "engines/director/lingo/lingo-lex.cpp"
|
||||
case YY_STATE_EOF(INITIAL):
|
||||
yyterminate();
|
||||
|
||||
@ -2682,7 +2683,7 @@ void yyfree (void * ptr )
|
||||
|
||||
#define YYTABLES_NAME "yytables"
|
||||
|
||||
#line 393 "engines/director/lingo/lingo-lex.l"
|
||||
#line 394 "engines/director/lingo/lingo-lex.l"
|
||||
|
||||
|
||||
extern int yydebug;
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
#include "director/director.h"
|
||||
#include "director/lingo/lingo.h"
|
||||
#include "director/lingo/lingo-ast.h"
|
||||
#include "director/lingo/lingo-gr.h"
|
||||
#include "director/lingo/lingo-the.h"
|
||||
|
||||
@ -134,7 +135,7 @@ end({spc}+{identifier})? {
|
||||
|
||||
yylval.s = new Common::String(ptr);
|
||||
|
||||
return ENDCLAUSE;
|
||||
return tENDCLAUSE;
|
||||
}
|
||||
^{spc}*factory { count(); return tFACTORY; }
|
||||
exit { count(); return tEXIT; }
|
||||
@ -156,7 +157,7 @@ movie { count(); return tMOVIE; }
|
||||
next { count(); return tNEXT; }
|
||||
not { count(); return tNOT; }
|
||||
of { count(); return tOF; }
|
||||
on { count(); return tON } // D3
|
||||
on { count(); return tON; } // D3
|
||||
open { count(); return tOPEN; }
|
||||
or { count(); return tOR; }
|
||||
play{spc}+frame { count(); return tPLAY; }
|
||||
@ -193,16 +194,16 @@ the{spc}+number{spc}+of{spc}+[[:alpha:]]+{spc}+(in|of){spc}+ {
|
||||
yylval.e[0] = kTheMenuItems;
|
||||
yylval.e[1] = g_lingo->_theEntityFields[key]->field;
|
||||
|
||||
return THEMENUITEMSENTITY;
|
||||
return tTHEMENUITEMSENTITY;
|
||||
}
|
||||
|
||||
yylval.s = new Common::String(Common::String::format("numberOf%s", field.c_str()));
|
||||
|
||||
if (g_lingo->_builtinFuncs.contains(*yylval.s)) {
|
||||
return THEFUNCINOF;
|
||||
return tTHEFUNCINOF;
|
||||
} else {
|
||||
warning("LEXER: Unhandled chunk expression '%s'", yylval.s->c_str());
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
}
|
||||
the{spc}+last{spc}+[[:alpha:]]+{spc}+(in|of){spc}+ {
|
||||
@ -221,10 +222,10 @@ the{spc}+last{spc}+[[:alpha:]]+{spc}+(in|of){spc}+ {
|
||||
yylval.s = new Common::String(Common::String::format("last%sOf", field.c_str()));
|
||||
|
||||
if (g_lingo->_builtinFuncs.contains(*yylval.s)) {
|
||||
return THEFUNCINOF;
|
||||
return tTHEFUNCINOF;
|
||||
} else {
|
||||
warning("LEXER: Unhandled chunk expression '%s'", yylval.s->c_str());
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
}
|
||||
the{spc}+[[:alpha:]]+{spc}+of{spc}+{identifier} {
|
||||
@ -251,12 +252,12 @@ the{spc}+[[:alpha:]]+{spc}+of{spc}+{identifier} {
|
||||
|
||||
if (!g_lingo->_theEntityFields.contains(field)) {
|
||||
warning("LEXER: Unhandled the field %s of %s", field.c_str(), ptr);
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
|
||||
if (g_lingo->_theEntityFields[field]->entity != g_lingo->_theEntities[ptr]->entity) {
|
||||
warning("LEXER: Unsupported field '%s' for entity '%s'", field.c_str(), ptr);
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
|
||||
yylval.e[0] = g_lingo->_theEntities[ptr]->entity;
|
||||
@ -264,12 +265,12 @@ the{spc}+[[:alpha:]]+{spc}+of{spc}+{identifier} {
|
||||
|
||||
// the <field> of menuItem <expr>" of menu <expr>
|
||||
if (g_lingo->_theEntityFields[field]->entity == kTheMenuItem)
|
||||
return THEMENUITEMENTITY;
|
||||
return tTHEMENUITEMENTITY;
|
||||
|
||||
if (g_lingo->_theEntities[ptr]->hasId)
|
||||
return THEENTITYWITHID;
|
||||
return tTHEENTITYWITHID;
|
||||
else
|
||||
return THEENTITY;
|
||||
return tTHEENTITY;
|
||||
} else {
|
||||
if (g_director->getVersion() >= 400) {
|
||||
Common::String key = Common::String::format("%d%s", g_lingo->_objectEntityId, field.c_str());
|
||||
@ -277,7 +278,7 @@ the{spc}+[[:alpha:]]+{spc}+of{spc}+{identifier} {
|
||||
yylval.objectprop.obj = new Common::String(ptr);
|
||||
yylval.objectprop.prop = new Common::String(field);
|
||||
|
||||
return THEOBJECTPROP;
|
||||
return tTHEOBJECTPROP;
|
||||
} else if (g_lingo->_builtinFuncs.contains(field)) { // Let's hope they don't do it in D4+
|
||||
if (g_lingo->_builtinFuncs[field].nargs == 1 && g_lingo->_builtinFuncs[field].maxArgs == 1) {
|
||||
yylval.s = new Common::String(field);
|
||||
@ -293,7 +294,7 @@ the{spc}+[[:alpha:]]+{spc}+of{spc}+{identifier} {
|
||||
|
||||
unput(' '); unput('f'); unput('o');
|
||||
|
||||
return THEFUNC;
|
||||
return tTHEFUNC;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -318,21 +319,21 @@ the{spc}+[[:alpha:]]+{spc}+(date|time) {
|
||||
|
||||
if (!g_lingo->_theEntityFields.contains(field)) {
|
||||
warning("LEXER: Unhandled the field %s", ptr);
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
|
||||
if (g_lingo->_theEntityFields[field]->entity != g_lingo->_theEntities[ptr]->entity) {
|
||||
warning("LEXER: Unsupported field '%s' for entity '%s'", field.c_str(), ptr);
|
||||
return LEXERROR;
|
||||
return tLEXERROR;
|
||||
}
|
||||
|
||||
yylval.e[0] = g_lingo->_theEntities[ptr]->entity;
|
||||
yylval.e[1] = g_lingo->_theEntityFields[field]->field;
|
||||
|
||||
if (g_lingo->_theEntities[ptr]->hasId)
|
||||
return THEENTITYWITHID;
|
||||
return tTHEENTITYWITHID;
|
||||
else
|
||||
return THEENTITY;
|
||||
return tTHEENTITY;
|
||||
}
|
||||
the{spc}+[[:alpha:]]+ {
|
||||
count();
|
||||
@ -346,15 +347,15 @@ the{spc}+[[:alpha:]]+ {
|
||||
yylval.e[1] = 0; // No field
|
||||
|
||||
if (g_lingo->_theEntities[ptr]->hasId)
|
||||
return THEENTITYWITHID;
|
||||
return tTHEENTITYWITHID;
|
||||
else
|
||||
return THEENTITY;
|
||||
return tTHEENTITY;
|
||||
}
|
||||
|
||||
if (g_lingo->_builtinFuncs.contains(ptr)) {
|
||||
if (g_lingo->_builtinFuncs[ptr].nargs == 1 && g_lingo->_builtinFuncs[ptr].maxArgs == 1) {
|
||||
yylval.s = new Common::String(ptr);
|
||||
return THEFUNC;
|
||||
return tTHEFUNC;
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,13 +382,13 @@ word { count(); return tWORD; }
|
||||
count();
|
||||
yylval.s = new Common::String(yytext);
|
||||
|
||||
return VARID;
|
||||
return tVARID;
|
||||
}
|
||||
{constfloat} { count(); yylval.f = atof(yytext); return FLOAT; }
|
||||
{constinteger} { count(); yylval.i = strtol(yytext, NULL, 10); return INT; }
|
||||
{constfloat} { count(); yylval.f = atof(yytext); return tFLOAT; }
|
||||
{constinteger} { count(); yylval.i = strtol(yytext, NULL, 10); return tINT; }
|
||||
{operator} { count(); return *yytext; }
|
||||
{newline} { count(); return '\n'; }
|
||||
{conststring} { count(); yylval.s = cleanupString(&yytext[1]); yylval.s->deleteLastChar(); return STRING; }
|
||||
{conststring} { count(); yylval.s = cleanupString(&yytext[1]); yylval.s->deleteLastChar(); return tSTRING; }
|
||||
. { count(); }
|
||||
|
||||
%%
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "director/util.h"
|
||||
|
||||
#include "director/lingo/lingo.h"
|
||||
#include "director/lingo/lingo-ast.h"
|
||||
#include "director/lingo/lingo-code.h"
|
||||
#include "director/lingo/lingo-gr.h"
|
||||
#include "director/lingo/lingo-object.h"
|
||||
@ -145,6 +146,7 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
|
||||
_currentScript = 0;
|
||||
_currentScriptContext = nullptr;
|
||||
|
||||
_assemblyAST = nullptr;
|
||||
_assemblyArchive = nullptr;
|
||||
_currentAssembly = nullptr;
|
||||
_assemblyContext = nullptr;
|
||||
@ -153,8 +155,7 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
|
||||
_globalCounter = 0;
|
||||
_pc = 0;
|
||||
_abort = false;
|
||||
_indef = kStateNone;
|
||||
_indef = kStateNone;
|
||||
_indef = false;
|
||||
_expectError = false;
|
||||
_caughtError = false;
|
||||
|
||||
@ -164,7 +165,6 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
|
||||
_hadError = false;
|
||||
|
||||
_inFactory = false;
|
||||
_inCond = false;
|
||||
|
||||
_floatPrecision = 4;
|
||||
_floatPrecisionFormat = "%.4f";
|
||||
@ -249,43 +249,6 @@ Symbol Lingo::getHandler(const Common::String &name) {
|
||||
return Symbol();
|
||||
}
|
||||
|
||||
const char *Lingo::findNextDefinition(const char *s) {
|
||||
const char *res = s;
|
||||
|
||||
while (*res) {
|
||||
while (*res && (*res == ' ' || *res == '\t' || *res == '\n'))
|
||||
res++;
|
||||
|
||||
if (!*res)
|
||||
return NULL;
|
||||
|
||||
if (!scumm_strnicmp(res, "macro ", 6)) {
|
||||
debugC(1, kDebugCompile, "findNextDefinition(): See 'macros ' construct");
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!scumm_strnicmp(res, "on ", 3)) {
|
||||
debugC(1, kDebugCompile, "findNextDefinition(): See 'on ' construct");
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!scumm_strnicmp(res, "factory ", 8)) {
|
||||
debugC(1, kDebugCompile, "findNextDefinition(): See 'factory ' construct");
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!scumm_strnicmp(res, "method ", 7)) {
|
||||
debugC(1, kDebugCompile, "findNextDefinition(): See 'method ' construct");
|
||||
return res;
|
||||
}
|
||||
|
||||
while (*res && *res != '\n')
|
||||
res++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LingoArchive::addCode(const char *code, ScriptType type, uint16 id, const char *scriptName) {
|
||||
debugC(1, kDebugCompile, "Add code for type %s(%d) with id %d in '%s%s'\n"
|
||||
"***********\n%s\n\n***********", scriptType2str(type), type, id, g_director->getCurrentPath().c_str(), cast->getMacName().c_str(), code);
|
||||
@ -319,6 +282,7 @@ ScriptContext *Lingo::compileAnonymous(const char *code) {
|
||||
|
||||
ScriptContext *Lingo::compileLingo(const char *code, LingoArchive *archive, ScriptType type, uint16 id, const Common::String &scriptName, bool anonymous) {
|
||||
_assemblyArchive = archive;
|
||||
_assemblyAST = nullptr;
|
||||
ScriptContext *mainContext = _assemblyContext = new ScriptContext(scriptName, archive, type, id);
|
||||
_currentAssembly = new ScriptData;
|
||||
|
||||
@ -326,8 +290,6 @@ ScriptContext *Lingo::compileLingo(const char *code, LingoArchive *archive, Scri
|
||||
_linenumber = _colnumber = 1;
|
||||
_hadError = false;
|
||||
|
||||
const char *begin, *end;
|
||||
|
||||
if (!strncmp(code, "menu:", 5) || scumm_strcasestr(code, "\nmenu:")) {
|
||||
debugC(1, kDebugCompile, "Parsing menu");
|
||||
parseMenu(code);
|
||||
@ -338,53 +300,15 @@ ScriptContext *Lingo::compileLingo(const char *code, LingoArchive *archive, Scri
|
||||
// Preprocess the code for ease of the parser
|
||||
Common::String codeNorm = codePreprocessor(code, archive, type, id);
|
||||
code = codeNorm.c_str();
|
||||
begin = code;
|
||||
|
||||
// macros and factories have conflicting grammar. Thus we ease life for the parser.
|
||||
if ((end = findNextDefinition(code))) {
|
||||
do {
|
||||
Common::String chunk(begin, end);
|
||||
// Parse the Lingo and build an AST
|
||||
parse(code);
|
||||
|
||||
if (chunk.hasPrefixIgnoreCase("factory")) {
|
||||
_inFactory = true;
|
||||
_assemblyContext = new ScriptContext(scriptName, archive, type, id);
|
||||
} else if (chunk.hasPrefixIgnoreCase("method")) {
|
||||
_inFactory = true;
|
||||
// remain in factory context
|
||||
} else if (chunk.hasPrefixIgnoreCase("macro") || chunk.hasPrefixIgnoreCase("on")) {
|
||||
_inFactory = false;
|
||||
_assemblyContext = mainContext;
|
||||
} else {
|
||||
_inFactory = false;
|
||||
_assemblyContext = mainContext;
|
||||
}
|
||||
|
||||
debugC(1, kDebugCompile, "Code chunk:\n#####\n%s#####", chunk.c_str());
|
||||
|
||||
parse(chunk.c_str());
|
||||
|
||||
if (debugChannelSet(3, kDebugCompile)) {
|
||||
debugC(2, kDebugCompile, "<current code>");
|
||||
uint pc = 0;
|
||||
while (pc < _currentAssembly->size()) {
|
||||
uint spc = pc;
|
||||
Common::String instr = decodeInstruction(_assemblyArchive, _currentAssembly, pc, &pc);
|
||||
debugC(2, kDebugCompile, "[%5d] %s", spc, instr.c_str());
|
||||
}
|
||||
debugC(2, kDebugCompile, "<end code>");
|
||||
}
|
||||
|
||||
begin = end;
|
||||
} while ((end = findNextDefinition(begin + 1)));
|
||||
|
||||
_inFactory = false;
|
||||
_assemblyContext = mainContext;
|
||||
|
||||
debugC(1, kDebugCompile, "Last code chunk:\n#####\n%s\n#####", begin);
|
||||
// Generate bytecode
|
||||
if (_assemblyAST) {
|
||||
_assemblyAST->compile();
|
||||
}
|
||||
|
||||
parse(begin);
|
||||
|
||||
// for D4 and above, there usually won't be any code left.
|
||||
// all scoped methods will be defined and stored by the code parser
|
||||
// however D3 and below allow scopeless functions!
|
||||
@ -451,6 +375,8 @@ ScriptContext *Lingo::compileLingo(const char *code, LingoArchive *archive, Scri
|
||||
delete _methodVars;
|
||||
_methodVars = nullptr;
|
||||
_currentAssembly = nullptr;
|
||||
delete _assemblyAST;
|
||||
_assemblyAST = nullptr;
|
||||
_assemblyContext = nullptr;
|
||||
_assemblyArchive = nullptr;
|
||||
return mainContext;
|
||||
|
@ -44,18 +44,13 @@ struct TheEntityField;
|
||||
struct LingoArchive;
|
||||
struct LingoV4Bytecode;
|
||||
struct LingoV4TheEntity;
|
||||
struct Node;
|
||||
class AbstractObject;
|
||||
class Cast;
|
||||
class ScriptContext;
|
||||
class DirectorEngine;
|
||||
class Frame;
|
||||
|
||||
enum LexerDefineState {
|
||||
kStateNone,
|
||||
kStateInDef,
|
||||
kStateInArgs
|
||||
};
|
||||
|
||||
enum VarType {
|
||||
kVarArgument,
|
||||
kVarProperty,
|
||||
@ -238,11 +233,6 @@ struct LingoArchive {
|
||||
void addNamesV4(Common::SeekableReadStreamEndian &stream);
|
||||
};
|
||||
|
||||
struct RepeatBlock {
|
||||
Common::Array<uint32> exits;
|
||||
Common::Array<uint32> nexts;
|
||||
};
|
||||
|
||||
class Lingo {
|
||||
|
||||
public:
|
||||
@ -281,10 +271,6 @@ public:
|
||||
// lingo-patcher.cpp
|
||||
Common::String patchLingoCode(Common::String &line, LingoArchive *archive, ScriptType type, uint16 id, int linenumber);
|
||||
|
||||
// lingo.cpp
|
||||
private:
|
||||
const char *findNextDefinition(const char *s);
|
||||
|
||||
// lingo-events.cpp
|
||||
private:
|
||||
void initEventHandlerTypes();
|
||||
@ -396,19 +382,19 @@ public:
|
||||
void codeLabel(int label);
|
||||
int codeString(const char *s);
|
||||
void processIf(int toplabel, int endlabel);
|
||||
void registerMethodVar(const Common::String &name, VarType type);
|
||||
void varCreate(const Common::String &name, bool global, DatumHash *localvars = nullptr);
|
||||
|
||||
LingoArchive *_assemblyArchive;
|
||||
ScriptContext *_assemblyContext;
|
||||
Node *_assemblyAST;
|
||||
ScriptData *_currentAssembly;
|
||||
LexerDefineState _indef;
|
||||
LexerDefineState _indefStore;
|
||||
bool _indef;
|
||||
uint _linenumber;
|
||||
uint _colnumber;
|
||||
uint _bytenumber;
|
||||
const char *_lines[3];
|
||||
bool _inFactory;
|
||||
Common::Array<RepeatBlock *> _repeatStack;
|
||||
|
||||
Common::Array<Common::String *> _argstack;
|
||||
Common::HashMap<Common::String, VarType, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> *_methodVars;
|
||||
@ -443,8 +429,6 @@ public:
|
||||
|
||||
bool _hadError;
|
||||
|
||||
bool _inCond;
|
||||
|
||||
private:
|
||||
int parse(const char *code);
|
||||
void parseMenu(const char *code);
|
||||
|
@ -23,6 +23,7 @@ MODULE_OBJS = \
|
||||
util.o \
|
||||
window.o \
|
||||
lingo/lingo.o \
|
||||
lingo/lingo-ast.o \
|
||||
lingo/lingo-builtins.o \
|
||||
lingo/lingo-bytecode.o \
|
||||
lingo/lingo-code.o \
|
||||
|
Loading…
Reference in New Issue
Block a user