当玩家书写一个脚本时,如果写错了脚本,那么肯定运行不了。现在就来分析怎么样确保脚本是正确的问题,如果不正确就需要显示出来那里不正确。脚本是否正确,其实是根据脚本的语法来判断的。那么又怎么样来构造语法分析的程序呢?在第二人生里是通过使用程序
bison.exe
来创建的。
下面先来看看
bison.exe
是做什么东西的:
Yacc
代表
Yet Another Compiler Compiler
。
Yacc
的
GNU
版叫做
Bison
。它是一种工具,将任何一种编程语言的所有语法翻译成针对此种语言的
Yacc
语 法解析器。它用巴科斯范式
(BNF, Backus Naur Form)
来书写。按照惯例,
Yacc
文件有
.y
后缀。编译行如下调用
Yacc
编译器:
$ yacc <options>
<filename ending with .y>
我们看到
Lex
从输入序列中识别标记。如果你在查看标记序列,你可能想在这一序列出现时执行某一动作。这种情况下有效序列的规范称为语法。
Yacc
语法文件包括这一语法规范。它还包含了序列匹配时你想要做的事。
bison
的语法文件,也是定义、规则和辅助代码部份。第二人生里的定义语法文件如下:
#001
%{
#002
#include "linden_common.h"
#003
#include "lscript_tree.h"
#004
#005
#ifdef __cplusplus
#006
extern "C" {
#007
#endif
#008
#009
int yylex(void);
#010
int yyparse( void );
#011
int yyerror(const char *fmt, ...);
#012
#013
#if LL_LINUX
#014
// broken yacc codegen...
--ryan.
#015
#define getenv getenv_workaround
#016
#endif
#017
#018
#ifdef LL_WINDOWS
#019
#pragma warning (disable : 4702) // warning C4702: unreachable code
#020
#pragma warning( disable : 4065 )
// warning: switch statement contains 'default' but no 'case' labels
#021
#endif
#022
#023
#ifdef __cplusplus
#024
}
#025
#endif
#026
%}
#027
#028
%union
#029
{
#030
S32
ival;
#
#032
char
*sval;
#033
class LLScriptType
*type;
#034
class LLScriptConstant
*constant;
#035
class LLScriptIdentifier
*identifier;
#036
class LLScriptSimpleAssignable
*assignable;
#037
class LLScriptGlobalVariable
*global;
#038
class LLScriptEvent
*event;
#039
class LLScriptEventHandler
*handler;
#040
class LLScriptExpression
*expression;
#041
class LLScriptStatement
*statement;
#042
class LLScriptGlobalFunctions
*global_funcs;
#043
class LLScriptFunctionDec
*global_decl;
#044
class LLScriptState
*state;
#045
class LLScritpGlobalStorage
*global_store;
#046
class LLScriptScript
*script;
#047
};