将子字符串传递给函数

时间:2013-08-20 18:44:18

标签: c++ parsing lisp

我正在建立LISP解释器。我遇到的问题是,当我遇到“(”)时,我需要将整个子字符串发送到函数。 例如,如果我有,

( begin  ( set x  2 ) (set y 3 ) )

然后我需要传递

begin  ( set x  2 ) (set y 3 ) )

当我遇到“(”再次  我需要通过

set x  2 ) (set y 3 ) )

然后

set y 3 ) )

我尝试使用substr计算长度,但这并不是很有效。如果有人可以提供帮助,那就太棒了。

请求的代码

int a=0;
listnode *makelist(string t) //t is the substring 
{
     //some code
     istringstream iss(t); 
     string word;
     while(iss>>word){
         if(word=="(")//I used strcmp here. Just for the sake for time saving I wrote this
         //some operations
             int x=word.size();
     a=a+x;
     word=word.substr(a);
     p->down=makelist(word);//function called again and word here should be the substring
}}

3 个答案:

答案 0 :(得分:1)

您是否考虑过使用中间代表?那么首先将整个字符串解析为数据结构然后执行它?毕竟Lisps有传统的应用顺序,这意味着他们在调用函数之前首先评估参数。数据结构可能看起来像一个结构的行,该结构具有字符串的第一部分(即在您的示例中开始或设置),而字符串的其余部分作为第二个属性处理(如果需要,可以处理头部和休息) 。还要考虑树通过递归比通过迭代更容易构造,这里的基本情况是达到')'字符。

如果您对Lisp口译员和编译器感兴趣,您应该在小件中检查Lisp,这非常值得。

答案 1 :(得分:0)

我会想到这样的事情:

string str = "( begin  ( set x  2 ) (set y 3 ) )";

func(str);

...

void func(string s)
{
    int i = 0;
    while(s.size() > i)
    {
        if (s[i] == '(')
        {
           func(s.substr(i)); 
        }

        i++;
    }
}

会做这个工作。 [显然,你也许也想在那里做点什么!]

答案 2 :(得分:0)

通常,lisp解析是通过递归调用读取器并让读者“消耗”尽可能多的数据来完成的。如果你在字符串上执行此操作,通过引用传递相同的字符串可能很方便,并返回“这是我读过的”元组和“这是我读完的地方”。

所以这样的事情(很明显,在实际的代码中,你可能想要将指针传递给offset而不是有一对结构并需要处理内存管理,我省略了使代码更具可读性) :

struct readthing {
  Node *data;
  int offset
}

struct readthing *read (char *str, int offset) {
  if (str[offset] == '(')
    return read_delimited(str, offset+1, ')'); /* Read a list, consumer the start */
  ...
}

struct readthing *read_delimited (char *str, int offset, char terminator) {
  Node *list  = NULL;
  offset = skip_to_next_token(str, offset);
  while (str[offset] != terminator) {
    struct readthing *foo = read(str, offset);
    offset = foo->offset;
    list = do_cons(foo->data, list);
  }
  return make_readthing(do_reverse(list), offset+1);
}