在设计 pirates ho! 时,我们需要一种简便的方法向玩家描述界面和对话框选项。我们需要简单、一致且灵活的语言来进行描述,因此我们寻找可以帮助我们构建脚本语言的工具。
谁想要另一段 bison?
我还在学校时,就已经对 "yacc" 这个词充满恐惧。它让我想到那些头发凌乱、面色苍白的学生低声念叨着编译器和符号表。所以我非常小心,尽量避免使用编译器类。但在开发游戏时,我鼓起勇气使用 yacc,希望它可以使编写脚本变得容易些。最后,yacc 不仅使编写脚本变得更容易,还使这个过程很有趣。
从基础开始
yacc 实际上非常易于使用。只要提供给它一组描述语法的规则,它就可以分析标记,并根据所见到的采取操作。对于我们使用的脚本语言,我们希望由浅入深,最初只是指定一些数字及其逻辑运算:
eval.y
%{
/* this first section contains c code which will be included in the output
file.
*/
#include
#include
/* since we are using c++, we need to specify the prototypes for some
internal yacc functions so that they can be found at link time.
*/
extern int yylex(void);
extern void yyerror(char *msg);
%}
/* this is a union of the different types of values that a token can
take on. in our case we'll just handle "numbers", which are of
c int type.
*/
%union {
int number;
}
/* these are untyped tokens which are recognized as part of the grammar */
%token and or equals
/* here we are, any number token is stored in the number member of the
union above.
*/
%token number
/* these rules all return a numeric value */
%type expression
%type logical_expression and or equals
%%
/* our language consists either of a single statement or of a list of statements.
notice the recursivity of the rule, this allows us to have any
number of statements in a statement list.
*/
statement_list: statement | statement_list statement
;
/* a statement is simply an expression. when the parser sees an expression
we print out its value for debugging purposes. later on we'll
have more than just expressions in our statements.
*/
statement: expression
{ printf("expression = %d\n", $1); }
;
/* an expression can be a number or a logical expression. */
expression: number
| logical_expression
;
/* we have a few different types of logical expressions */
logical_expression: and
| or
| equals
;
/* when the parser sees two expressions surrounded by parenthesis and
connected by the and token, it will actually perform a c logical
expression and store the result into
this statement.
*/
and: '(' expression and expression ')'
{ if ( $2 && $4 ) { $$ = 1; } else { $$ = 0; } }
;
or: '(' expression or expression ')'
{ if ( $2 || $4 ) { $$ = 1; } else { $$ = 0; } }
;
equals: '(' expression equals expression ')'
{ if ( $2 == $4 ) { $$ = 1; } else { $$ = 0; } }
;
%%
/* this is a sample main() function that just parses standard input
using our yacc grammar. it allows us to feed sample scripts in
and see if they are parsed correctly.
*/
int main(int argc, char *argv[">)
{ yyparse();
}
/* this is an error function used by yacc, and must be defined */-
void yyerror(char *message)
{
fprintf(stderr, "%s\n", message);
}
如果喜欢sdl 用法,第 4 部分: lex 和 yacc请收藏或告诉您的好朋友.
阅读(201) | 评论(0) | 转发(0) |