我正在建立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
}}
答案 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);
}