DIRECTOR: LINGO: Rewrite grammar to build AST

This commit is contained in:
djsrv 2021-06-15 02:20:31 -04:00 committed by D.J. Servilla
parent 34d8aabc4b
commit f726a6ed89
11 changed files with 1891 additions and 3227 deletions

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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(); }
%%

View File

@ -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;

View File

@ -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);

View File

@ -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 \