передача подстроки в функцию

Я работаю над созданием интерпретатора 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

Решение

Вы думали об использовании промежуточного представления? Итак, сначала проанализируйте всю целую строку в структуре данных, а затем выполните ее? После того, как все Лиспы имеют традиционный аппликативный порядок, это означает, что они сначала оценивают аргументы перед вызовом функции. Структура данных может выглядеть как строки структуры, в которой есть первая часть строки (т. Е. Начало или установка в вашем примере) и остальная часть строки для обработки в качестве второго свойства (head и rest, если хотите) , Также учтите, что деревья легче построить с помощью рекурсии, чем с помощью итерации, при этом базовый случай достигает символа «)».

Если вы заинтересованы в интерпретаторах и компиляторах Lisp, вам следует проверить Lisp в Small Pieces, что стоит своих денег.

1

Другие решения

Я бы подумал что-то вроде этого:

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++;
}
}

сделал бы работу. [Очевидно, вы, возможно, захотите сделать что-то еще там!]

0

Обычно разбор lisp выполняется путем рекурсивного вызова считывателя и позволяет ему «потреблять» столько данных, сколько необходимо. Если вы делаете это со строками, может быть удобно передать одну и ту же строку по ссылке и вернуть кортеж «это то, что я прочитал» и «это то, где я закончил читать».

Итак, что-то вроде этого (очевидно, в реальном коде вы, возможно, захотите передавать указатели на смещение, а не иметь парную структуру, и мне нужно иметь дело с управлением памятью, я исключил это, чтобы сделать код более читабельным):

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);
}
0
По вопросам рекламы [email protected]