Я работаю над созданием интерпретатора 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
}}
Вы думали об использовании промежуточного представления? Итак, сначала проанализируйте всю целую строку в структуре данных, а затем выполните ее? После того, как все Лиспы имеют традиционный аппликативный порядок, это означает, что они сначала оценивают аргументы перед вызовом функции. Структура данных может выглядеть как строки структуры, в которой есть первая часть строки (т. Е. Начало или установка в вашем примере) и остальная часть строки для обработки в качестве второго свойства (head и rest, если хотите) , Также учтите, что деревья легче построить с помощью рекурсии, чем с помощью итерации, при этом базовый случай достигает символа «)».
Если вы заинтересованы в интерпретаторах и компиляторах Lisp, вам следует проверить Lisp в Small Pieces, что стоит своих денег.
Я бы подумал что-то вроде этого:
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++;
}
}
сделал бы работу. [Очевидно, вы, возможно, захотите сделать что-то еще там!]
Обычно разбор 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);
}