Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / ai_service / script_compiler.h
blob00a0ed2afc0a03814e71cd0ca6f0c4ad341cc62f
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef __SCRIPT_COMPILER__
18 #define __SCRIPT_COMPILER__
20 #include "script_vm.h"
23 static std::string scriptHex_decode(std::string str)
25 std::string output;
26 for (size_t i=0; i<(str.length()-1); i+=2)
28 char c1 = str[i], c2 = str[i+1];
29 char buffer[3] = { c1, c2, '\0' };
30 char c = (char)strtol(buffer, NULL, 16);
31 output.push_back(c);
33 return output;
36 // Forward declarations
37 class CStateInstance;
39 namespace AICOMP
42 /****************************************************************************/
43 /* Compiler classes */
44 /****************************************************************************/
45 //////////////////////////////////////////////////////////////////////////////
46 // Helper classes //
47 //////////////////////////////////////////////////////////////////////////////
49 struct EScriptError : public NLMISC::Exception
51 EScriptError(const std::string &text, size_t index);
52 size_t getIndex() const;
53 size_t _Index;
56 //////////////////////////////////////////////////////////////////////////////
57 // Native functions access //
58 //////////////////////////////////////////////////////////////////////////////
60 typedef void (*FScrptNativeFunc)(CStateInstance* si, AIVM::CScriptStack& stack);
62 class CScriptNativeFuncParams : public NLMISC::CRefCount
64 public:
65 CScriptNativeFuncParams(const std::string &str, FScrptNativeFunc func);
66 virtual ~CScriptNativeFuncParams() { }
67 size_t _nbInParams;
68 size_t _nbOutParams;
69 bool _va;
70 FScrptNativeFunc _func;
73 //////////////////////////////////////////////////////////////////////////////
74 // Node classes //
75 //////////////////////////////////////////////////////////////////////////////
77 class CCodeNode : public NLMISC::CRefCount
79 public:
80 CCodeNode(const std::string &type, const std::string &name, NLMISC::CSmartPtr<CCodeNode> firstChildNode=NULL);
82 virtual void dump(size_t indent=0);
83 virtual std::string getFullName() const;
85 virtual ~CCodeNode() { }
86 std::string _Type;
87 std::string _Name;
88 NLMISC::CSmartPtr<CCodeNode> _NextNode;
89 NLMISC::CSmartPtr<CCodeNode> _FirstChildNode;
92 //////////////////////////////////////////////////////////////////////////////
94 class CCodeTokenNode : public CCodeNode
96 public:
97 CCodeTokenNode(const std::string &type, const std::string &name, NLMISC::CSmartPtr<CCodeNode> firstChildNode);
98 virtual ~CCodeTokenNode() { }
100 void dump(size_t indent=0);
101 virtual std::string getFullName() const;
104 //////////////////////////////////////////////////////////////////////////////
105 // Token classes //
106 //////////////////////////////////////////////////////////////////////////////
108 class CTokenTestResult
110 public:
111 enum TBasicTokenTestRes
113 BRULE_INVALID = 0,
114 BRULE_VALID,
117 CTokenTestResult();
118 CTokenTestResult(const NLMISC::CSmartPtr<CCodeNode> &codeNode);
119 CTokenTestResult(const NLMISC::CSmartPtr<CCodeNode> &codeNode, TBasicTokenTestRes res);
120 virtual ~CTokenTestResult();
121 bool isValid() const;
122 CCodeNode *getCode () const;
123 private:
124 TBasicTokenTestRes _res;
125 NLMISC::CSmartPtr<CCodeNode> _codeNode;
128 //////////////////////////////////////////////////////////////////////////////
130 class CBasicToken : public NLMISC::CRefCount
132 public:
133 typedef std::map<char,NLMISC::CSmartPtr<CBasicToken> > TBasicTokenList;
134 public:
135 virtual ~CBasicToken() { }
137 typedef std::vector<NLMISC::CSmartPtr<CBasicToken> > TTokenList;
139 virtual size_t init (TTokenList &tokenList, const std::string &str, size_t firstIndex, size_t lastIndex) = 0;
140 virtual CBasicToken *createNew () const = 0;
141 virtual void dump(size_t indent) const = 0;
142 virtual CTokenTestResult buildNode(const std::string &code, size_t &index) const = 0;
144 static size_t initTokens(TTokenList &tokenList, const std::string &str, size_t firstIndex, size_t lastIndex);
146 static NLMISC::CSmartPtr<CBasicToken> getNewToken(char c);
147 static void insertBasicToken(char id, NLMISC::CSmartPtr<CBasicToken> token);
148 static TBasicTokenList _BasicTokens;
151 //////////////////////////////////////////////////////////////////////////////
153 class CToken : public NLMISC::CRefCount
155 public:
156 CToken(const std::string &tokenName, const std::string &tokenDesc);
158 typedef std::vector<NLMISC::CSmartPtr<CBasicToken> > TTokenContainer;
160 void dump() const;
162 virtual ~CToken() { }
164 CTokenTestResult buildTree(const std::string &code, size_t &index);
166 const std::string &getName() const;
168 std::string _tokenName;
169 std::string _tokenDesc;
170 std::vector<NLMISC::CSmartPtr<CBasicToken> > _Tokens;
173 //////////////////////////////////////////////////////////////////////////////
174 // Rule classes //
175 //////////////////////////////////////////////////////////////////////////////
177 class CSubRule;
179 typedef std::vector<NLMISC::CSmartPtr<CSubRule> > TSubRuleList;
181 class CRule : public NLMISC::CRefCount
183 public:
184 CRule(const std::string &name, const std::string &decl);
185 virtual ~CRule() { }
187 void setDesc(const std::string &decl);
189 TSubRuleList _subRules;
190 std::string _Name;
193 //////////////////////////////////////////////////////////////////////////////
195 class CSubRule : public NLMISC::CRefCount
197 public:
198 CSubRule(CRule *parent, const std::string &decl);
200 std::vector<std::string> _tokens;
201 NLMISC::CSmartPtr<CRule> _Parent;
203 std::vector<std::string> _ExecOpCodes;
206 //////////////////////////////////////////////////////////////////////////////
208 class CSubRuleTracer;
209 typedef std::vector<NLMISC::CSmartPtr<CSubRuleTracer> > TSubRuleTracerList;
211 class CSubRuleTracer : public NLMISC::CRefCount, public NLMISC::CDbgRefCount<CSubRuleTracer>
213 public:
214 CSubRuleTracer(size_t tokenStartIndex, size_t currentTokenIndex, const std::string &name, const std::string &textValue);
215 CSubRuleTracer(NLMISC::CSmartPtr<CSubRule> subRule, size_t tokenStartIndex, size_t currentTokenIndex, const std::string &name, const std::string &textValue);
216 CSubRuleTracer(const CSubRuleTracer &otherSRT);
218 virtual ~CSubRuleTracer();
220 NLMISC::CSmartPtr<CSubRuleTracer> getValidTracer() const;
222 void updatePreviousNext();
224 void checkRule(CSubRule *rule, size_t index, size_t currentToken, TSubRuleTracerList &childTracers);
225 void checkRules(size_t currentToken);
227 NLMISC::CSmartPtr<CSubRuleTracer> codifyTree();
229 void generateCode(NLMISC::CSmartPtr<AIVM::CByteCode> &cByteCode) const;
231 /// Returns a chain specifying the params this way: ffsf for (float, float, string, float)
232 const CSubRuleTracer *getChildForName(const std::string &name) const;
233 void getSignature(std::string &signature, bool inOtherWiseOut) const;
234 size_t getNbChildNamed(const std::string &name) const;
236 CSubRuleTracer *getHigherParent ();
237 CSubRuleTracer *getNextLower() const;
239 void removePrevious(CSubRuleTracer *tracer);
240 void removeNext (CSubRuleTracer *tracer);
241 void removeParent (CSubRuleTracer *tracer);
242 void removeChild (CSubRuleTracer *tracer);
244 void detachFromEveryBody();
246 void iterateToMarkValidTracer();
247 void removeInvalidTracers();
249 void flushErrors();
251 void dump(size_t indent) const;
254 std::string _Name;
255 std::string _TextValue;
257 size_t _index; ///< Index in the subrule.
259 size_t _tokenStartIndex;
260 size_t _tokenIndex;
262 bool _Valid;
264 //////////////////////////////////////////////////////////////////////////////
265 // All Links are Directs.
267 NLMISC::CSmartPtr<CSubRule> _subRule;
269 typedef std::set<NLMISC::CSmartPtr<CSubRuleTracer> > TTracersSet;
270 typedef std::map<size_t, TTracersSet> TOrderedTracers;
272 static TOrderedTracers _PreviousTracers;
273 static TOrderedTracers _NextTracers;
275 TSubRuleTracerList _parentTracers;
276 TSubRuleTracerList _childTracers;
279 //////////////////////////////////////////////////////////////////////////////
281 class CCompiler
283 public:
284 typedef std::map<NLMISC::TStringId, NLMISC::CSmartPtr<CScriptNativeFuncParams> > TNativeFuncMap;
285 typedef std::vector<NLMISC::CSmartPtr<CRule> > TRuleList;
286 typedef std::map<std::string, AIVM::CScriptVM::EOpcode> TOpcodeMap;
287 public:
288 CCompiler();
289 virtual ~CCompiler() { }
291 NLMISC::CSmartPtr<AIVM::CByteCode const> compileCode(std::string const& sourceCode, std::string const& fullName) const;
292 NLMISC::CSmartPtr<AIVM::CByteCode const> compileCode(std::vector<std::string> const& sourceCodeLines, std::string const& fullName) const;
294 // New compiler using lex & yacc
295 NLMISC::CSmartPtr<AIVM::CByteCode const> compileCodeYacc(std::string const& sourceCode, std::string const& fullName, bool dump, bool win32report) const;
297 // Old compiler
298 NLMISC::CSmartPtr<AIVM::CByteCode const> compileCodeOld(std::string const& sourceCode, std::string const& fullName, bool dump) const;
300 // Dump the source and the bytecode for debugging
301 void dumpByteCode(std::string const& sourceCode, std::string const& fullName, NLMISC::CSmartPtr<AIVM::CByteCode const> &byteCode, std::string const& directory) const;
303 NLMISC::CSmartPtr<CSubRuleTracer> buildCodeTree(const std::string &code) const;
305 static void registerNativeFunc ();
307 static void addToken(std::string const& tokenName, std::string const& tokenDesc);
308 static void addRule(std::string const& ruleName, std::string const& ruleDesc);
309 static void addOpcode(std::string const& str, AIVM::CScriptVM::EOpcode const& op);
310 static void addNativeFunc(std::string const& signature, FScrptNativeFunc const& foo);
311 static void addDeprecatedNativeFunc(std::string const& signature);
313 static CToken* getToken (std::string const& tokenName);
314 static NLMISC::CSmartPtr<CRule> getRule (std::string const& ruleName);
315 static bool getNextToken (std::string const& text, size_t& index, std::string& tokenName, std::string& textValue);
316 static std::string const& getOpcodeName (AIVM::CScriptVM::EOpcode const& op);
317 static AIVM::CScriptVM::EOpcode getOpcodeAndValue (std::string const& str, std::string& value);
318 static CScriptNativeFuncParams* getNativeFunc (std::string const& funcName, std::string const& inparams, std::string const& outparams);
320 static CCompiler& getInstance()
322 if (!_Instance)
323 _Instance = new CCompiler();
324 return *_Instance;
326 static TNativeFuncMap const& getFunctionList() { return _NativeFunctions; }
328 typedef std::vector<NLMISC::CSmartPtr<CToken> > TTokenList;
330 static TRuleList _Rules;
331 static TOpcodeMap _Opcodes;
332 private:
333 static TNativeFuncMap _NativeFunctions;
334 static TTokenList _Tokens;
335 static CCompiler* _Instance;
338 /****************************************************************************/
339 /* Inlined functions */
340 /****************************************************************************/
342 inline
343 EScriptError::EScriptError(const std::string &text, size_t index)
344 : NLMISC::Exception(text)
345 , _Index(index)
348 inline
349 size_t EScriptError::getIndex() const
351 return _Index;
354 inline
355 CTokenTestResult::CTokenTestResult()
356 : _res(BRULE_VALID)
359 inline
360 CTokenTestResult::CTokenTestResult(const NLMISC::CSmartPtr<CCodeNode> &codeNode)
361 : _res(BRULE_VALID)
362 , _codeNode(codeNode)
365 inline
366 CTokenTestResult::CTokenTestResult(const NLMISC::CSmartPtr<CCodeNode> &codeNode, TBasicTokenTestRes res)
367 : _res(BRULE_VALID)
368 , _codeNode(codeNode)
371 inline
372 CTokenTestResult::~CTokenTestResult()
375 inline
376 bool CTokenTestResult::isValid() const
378 return _res==BRULE_VALID;
380 inline
381 CCodeNode *CTokenTestResult::getCode () const
383 return _codeNode;
386 /****************************************************************************/
387 /* For LEX & YACC */
388 /****************************************************************************/
390 #define AICOMP_MAX_SIGNATURE 32
392 // Yacc base node
393 struct CBaseYacc
395 char Signature[AICOMP_MAX_SIGNATURE];
396 bool isFloat () const { return strcmp (Signature, "f") == 0; }
397 bool isString () const { return strcmp (Signature, "s") == 0; }
398 bool isBool () const { return strcmp (Signature, "b") == 0; }
399 const char *getType () const { return isFloat ()?"float":isBool ()?"bool":isString ()?"string":"void"; }
402 // Yacc node for current byte code
403 struct CByteCodeYacc : public CBaseYacc
405 std::vector<size_t> *ByteCode;
408 // Yacc node for a single opcode
409 struct COpcodeYacc : public CBaseYacc
411 int Line;
412 size_t Opcode;
415 // Yacc node for operators
416 struct COperatorYacc : public COpcodeYacc
418 const char *Operator;
421 // Yacc node for byte code tree node, keeping the tree structure
422 struct CByteCodeListYacc : public CBaseYacc
424 std::list<std::vector<size_t> * > *ByteCodeList;
427 // Case structure
428 struct CCase : public CBaseYacc
430 int Line;
431 size_t Case;
432 std::vector<size_t> *ByteCode;
435 // Yacc node for case
436 struct CCaseYacc : public CBaseYacc
438 CCase *Case;
441 // Yacc node for switch
442 struct CSwitchYacc : public CBaseYacc
444 std::map<size_t, CCase *> *Cases;
447 }; // namespace
449 // From Lex&Yacc
450 extern bool aiCompile (std::vector<size_t> &dest, const char *script, const char *scriptName, bool win32report);
452 #endif