写一个简单的游戏口译员

时间:2011-01-23 09:38:21

标签: interpreter

我在本网站和黑客新闻上阅读了很多关于翻译和编译器构建的条目。

所有主题都谈到大翻译语言,我希望写一个过于简化的语言。

语言

  1. 该语言基于Herbert [Imagine Cup]
  2. 我希望创建一个在线版本,用户可以在表格中提交并看到它在网页窗口中运行。
  3. 我只能使用php,python,ruby或任何网络语言。
  4. 这是我的语言

    基本教学

    1. s - 直接
    2. l - left
    3. r - 右
    4. 你可以在这里有功能    f:ssrl [它们支持递归f:ssrlf参数f(A):Assrl,f(A):ssrlf(A-1)(A在这里是整数)
    5. 您可以在程序中互相调用多个函数。 F:ssrlgf
    6. 我想尽快实现这一点,这将是我完成这项工作的最佳选择。 [我知道php,没有python或ruby的经验但愿意为这个项目学习它们]

2 个答案:

答案 0 :(得分:2)

你必须写一个tokenizer-(链)。

类令牌{     static Token Parse(字符串程序);     void Execute(CurrentProgramState state); }

首先有一个程序令牌试图解析整个文本,方法是将多个较小的令牌传递给它,从而创建令牌。传递的每个成功令牌都会消耗一点字符串,因此最后字符串为空。 (最后程序令牌有一个有序的令牌列表)。

然后当调用Program.Execute()时,它会跟踪CurrentProgramState并将该状态传递给它自己的令牌,这些令牌根据其参数修改游戏状态。

一个小例子。

假设我们的语言只有两种类型的令牌

s(直) 号码(多远)

class StraightToken
{
    public StraightToken(NumberToken howFar)
    {
        this.howFar = howFar;
    }
    private NumberToken howFar;
    static Token Parse(string program)
    {
        if(program.StartsWith("s ")
        {
            NumberToken number = NumberToken.Parse(program.substring(2));
            if(howFar != null)
            {                
                return new StraightToken(number);
            }
        }
        return null;
    }

    public void Execute(ProgramState state)
    {
        state.Position += this.howFar.value;
    }
}

class NumberToken
{
    public int value;
    public NumberToken(int value;)
    {
        this.value = value;
    }

    static Token Parse(string program)
    {
        if(IsDigit(program[0]))
        {
            program = program.SubString(1);
            return new NumberToken((int)program[0])
        }
    }
}

答案 1 :(得分:0)

很抱歉在旧帖子上发帖但是, 这是一个有趣的问题,因为它没有解决,我个人会使用javascript,并且不会为编写一个翻译而烦恼

所以假设输入全部是一行,你就是这样:[警告:可能包含错别字,我在手机上发帖]

var input = "lllssrb",
      horizontal = 0, vertical = 0;
//now we'll just loop through the input
input.split("").forEach(function(char){
    switch(char){
         case "l":
              horizontal --;
              break;
         case "r"
              horizontal ++;
              break;
         case "s":
              vertical ++;
              break;
          case "b":
              vertical --;
              break;
    }
});

//now do something with our results
//function advance(horizontal, vertical)
advance(horizontal, vertical);