求助超难度问题[编译原理],分少可以加到1000分(300分)

  • 主题发起人 主题发起人 温柔的酷
  • 开始时间 开始时间

温柔的酷

Unregistered / Unconfirmed
GUEST, unregistred user!
写欲写一脚本解译器

1. 走到(X,Y)
2. 过门(X,Y)
3. 开始战斗
4. 停止战斗
5. 等待(2500)
.........
......
.......
这些函数在软件内部已经实现为
moveto(X,Y)
DOOR(X,Y)
START
STOP
SLEEP().
.........
.......
.......

还有系统中已有一些环境变量 如 $当前地图 $当前GOLD $当前版本号 &当前负重 等等
现求 IF $当前地图="比七省&quot
THEN 调用<走到战斗地图> Else <买药> 的实现的方法
*注 <> 里面的 为 子过程














附部分代码

unit Script_unit;

interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls;
const
MAX_CANX=100;

Type
Plabel=^Tlabel;
Tlabel= record
name :string
//标记名字
StarLine :word
//开始于多少行
EndLine :word
//多少行结束
end;


type
CScript =class
str:string
//一行完整的指令
M_CMD:string
//M_CMD 命令,M_CAN 临时储存参数
M_CANX: array[0..MAX_CANX] of string
//参数数组
M_CANXCount:word
//参数的个数
M_CAN,M_RIGHT:string;
M_VAR:string
//变量
M_LABEL:string;
M_value:string
//变量,如果为空,就为&quot;=&quot;右边去掉&quot;;&quot;的数据,否则为&quot;=&quot;右边脚本的返回值
M_IFO,M_IFT:string;
CanB:array[0..MAX_CANX]of word
//参数是布尔的话在这里储存
CScript_Code:Tstringlist
//源文件
Call_list:Tlist
//子程序调用时,向表内加入应返回的地址
NowLine:word
//当前指针在行

constructor Create
dynamic;
destructor Destroy
override;
private
function substr(s:string):string
//去掉注释
function Find_label:word
//查找标记,返回标记所在的行
procedure RunScript();
{ Private declarations }
public
function LoadScript(FileName:string):boolean;

end;


implementation
uses
My_Script;

constructor CScript.Create;
begin
str:='';
NowLine:=0

Call_list:=Tlist.Create;
CScript_Code:=Tstringlist.Create;
end;



destructor CScript.Destroy;
var
i:word;
begin
if Call_list.Count>0 then
for i:=0 to Call_list.Count-1 do
Dispose(Call_list.Items) ;

Call_list.Free;
CScript_Code.Free;
inherited Destroy;
end;


function CScript.Find_label:word
//查找标记,返回标记所在的行
begin
//
end;

procedure CScript.RunScript();
var
VarVa:word;
sta:word;
over:word;
LabStart:word;
LabEnd:word;
begin
VarVa:=pos('=',str);
sta:=pos('(',str);
over:=pos(')',str);
LabStart:=pos('<',str);
LabEnd:=pos('>',str);
M_LABEL:=copy(str,LabStart,LabEnd);//获取标记
M_VAR:=copy(str,0,VarVa-1);//获取变量
M_CMD:=copy(str,VarVa+1,sta-VarVa-1);//获取命令
if M_CMD='' then M_CMD:=copy(str,0,LabStart-1);//获取命令
M_CAN:=copy(str,sta+1,over-sta-1);//获取全部参数
M_RIGHT:=copy(str,VarVa+1,length(str));
Form1.Memo1.Lines.Add( format('命令 %s 变量 %s 参数 %s 标记 %s ',[M_CMD,M_VAR,M_CAN,M_LABEL]) )
end;

function CScript.substr(s:string):string;
var
TempStr:string;
begin
if s='' then
begin
Result:='';
exit;
end;
TempStr:=Trim(s);
if TempStr[1]='*' then TempStr:=''
//以 * 开头的为注释
Result:=TempStr;
end;


function CScript.LoadScript(FileName:string):boolean;
var
i:word;
begin
CScript_Code.LoadFromFile(FileName);
for i:=0 to CScript_Code.Count-1 do
begin
str:=CScript_Code.Strings;
str:=substr(str)
//去掉注释语句
CScript_Code.Strings:=str ;
end;

for i:= 0 to CScript_Code.Count-1 do
begin
str:=CScript_Code.Strings;
if str<>'' then
begin
RunScript;
end;;
end;

result:=true;
end;

end.



目标脚本




*--------------------------------*
* 洞穴二层
*--------------------------------*

*----- 回 城 -----------
*先尝试用回城卷、地牢,最后走回
*-----------------------
<回城卷>
如果当前地图名=[比奇省]
那么跳转到标记<回城结束>
如果物品[回城卷]的数量=0个
那么跳转到标记<尝试地牢>
使用[回城卷]
等待[2500]
跳转到标记<回城卷>

<尝试地牢>
如果当前地图名=[比奇省]
那么跳转到标记<回城结束>
如果物品[地牢逃脱卷]的数量=0个
那么跳转到标记<走路回城>
使用[地牢逃脱卷]
等待[2500]
跳转到标记<尝试地牢>

<走路回城>
*此处写回城的行走脚本
走到地图(比奇省,0,0)

<回城结束>
*--------卖衣服--------*
找到[安家布衣](服装店[0106],19,6)
与[安家布衣]对话
选择[卖衣服]
自动卖掉[衣服]类别物品
结束对话
*--------卖头盔--------*
找到[安家布衣](服装店[0106],19,6)
与[安家布衣]对话
选择[卖衣服,卖头盔]
自动卖掉[头盔]类别物品
结束对话
*--------卖武器--------*
找到[卫家店](商店[0103],19,18)
与[卫家店]对话
选择[卖武器]
自动卖掉[武器]类别物品
结束对话
*--------卖矿石--------*
找到[卫家店](商店[0103],19,18)
与[卫家店]对话
选择[卖武器]
自动卖掉[矿石]类别物品
结束对话
*--------卖手镯--------*
找到[手镯店老板](首饰店[0105],12,12)
与[手镯店老板]对话
选择[出售手镯]
自动卖掉[手镯]类别物品
结束对话
*--------卖戒指--------*
找到[戒指店老板](首饰店[0105],18,6)
与[戒指店老板]对话
选择[卖戒指,出售戒指]
自动卖掉[戒指]类别物品
结束对话
*--------卖项链--------*
找到[项链店老板](首饰店[0105],6,18)
与[项链店老板]对话
选择[出售项链]
自动卖掉[项链]类别物品
结束对话
*--------卖书籍--------*
找到[书店老板](比奇省[0],325,250)
与[书店老板]对话
选择[卖书]
自动卖掉[书籍]类别物品
结束对话
*--------卖药品--------*
找到[夏家店老板](比奇省[0],324,291)
与[夏家店老板]对话
选择[卖药品,卖药,卖物品]
自动卖掉[药品]类别物品
结束对话
*--------保管物品--------*
找到[仓库保管员](比奇省[0],301,257)
与[仓库保管员]对话
选择[保管东西]
自动存物
结束对话
*--------修理衣服--------*
如果物品[轻型盔甲(男)]的数量=0个
那么向下跳转到标记<修理结束>
找到[安家布衣](服装店[0106],19,6)
与[安家布衣]对话
卸下[衣服]位置的装备
选择[修复衣服,修补衣服]
修理[轻型盔甲(男)]
选择[返回]
装备[轻型盔甲(男)]到[衣服]
结束对话
<修理结束>
*--------修理武器--------*
如果物品[海魂]的数量=0个
那么向下跳转到标记<修理结束>
找到[卫家店](商店[0103],19,18)
与[卫家店]对话
卸下[武器]位置的装备
选择[修理武器]
修理[海魂]
选择[返回]
装备[海魂]到[武器]
结束对话
<修理结束>
*--------修理项链--------*
如果物品[黑檀项链]的数量=0个
那么向下跳转到标记<修理结束>
找到[项链店老板](首饰店[0105],6,18)
与[项链店老板]对话
卸下[项链]位置的装备
选择[修理项链]
修理[黑檀项链]
选择[返回]
装备[黑檀项链]到[项链]
结束对话
<修理结束>
*--------修理手镯--------*
如果物品[大手镯]的数量=0个
那么向下跳转到标记<修理结束>
找到[手镯店老板](首饰店[0105],12,12)
与[手镯店老板]对话
卸下[右手镯]位置的装备
选择[修理手镯]
修理[大手镯]
选择[返回]
装备[大手镯]到[右手镯]
结束对话
<修理结束>
*--------特修手镯--------*
如果物品[大手镯]的数量=0个
那么向下跳转到标记<修理结束>
找到[手镯店老板](首饰店[0105],12,12)
与[手镯店老板]对话
卸下[左手镯]位置的装备
选择[特殊修理]
修理[大手镯]
选择[返回]
装备[大手镯]到[左手镯]
结束对话
<修理结束>
*--------修理戒指--------*
如果物品[六角戒指]的数量=0个
那么向下跳转到标记<修理结束>
找到[戒指店老板](首饰店[0105],18,6)
与[戒指店老板]对话
卸下[右戒指]位置的装备
选择[修理戒指]
修理[六角戒指]
选择[返回]
装备[六角戒指]到[右戒指]
结束对话
<修理结束>
*--------买药品--------*
找到[夏家店老板](比奇省[0],324,291)
与[夏家店老板]对话
选择[买药品,买药,买物品]
选择购买[金创药(小)包]
买够3个金创药(小)包
选择[返回]
选择购买[魔法药(中)包]
买够8个魔法药(中)包
选择[返回]
结束对话
*--------买杂物--------*
找到[杂货铺老板](比奇省[0],378,298)
与[杂货铺老板]对话
选择[买东西,购买物品,买物品]
选择购买[地牢逃脱卷]
买够1个地牢逃脱卷
选择[返回]
选择购买[随机传送卷]
买够3个随机传送卷
选择[返回]
结束对话
*-----出发:洞穴二层------*
走到地图(石墓一层,0,0)
边打边走到(石墓二层,0,0)
等待[1000]毫秒
开始战斗
结束脚本运行
 
楼上回复太过于笼统吧~~~
 
楼主需要的问题并不能两三句话说的清楚,但仍可以概括一下。
首先,你得找出目标代码的关键词。(词法分析,觉的你这里可以直接用程序中的关键词代替文本的关键词)
然后,根据关键词来组合语句。(语法分析)
接着,当然是根据一句句的语句,逐磨这段语句的做含意。(语义分析)
目标代码生成这一部感觉你可能用不着了。
建议楼主去网上载个LR(0)的源码,一般都是C语言,好像也有pascal实现的
 
是的哦~~~不容易搞定~~~难...........麻烦~~~~~~~~~~~
 
象是传奇
 
我也在构造内存树形脚本系统。我的想法是,将文本脚本预处理成结构复杂但处理起来很
简单的内存树。变量引用、函数调用、四则运算、比较、条件转移、无条件转移等等都是这
颗树的节点。解释器的工作就是将环境信息代入,然后按照各个节点的规则来执行。具体的
系统还在构造中,在这里就不多说了。

不过我觉得,作为游戏系统,没有太大的必要自己搞一套东西,Tcl、Python、VBScript
等有现成解释器支持的语言已经很好了,如果楼主一定要用中文脚本的话,规范性(注意到
代码没有采用直观的缩进格式)和语法检查就成了很大的问题。
 
已经搞定了~~~结贴~~~~~~~~~~~
 
后退
顶部