#include <vector>
#include <list>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <utility>
#include <functional>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <climits>
#include <cassert>
#include <memory>
#include <time.h>
using namespace std;
inline int toInt(string s) {int v; istringstream sin(s);sin>>v;return v;}
template<class T> inline string toString(T x) {ostringstream sout;sout<<x;return sout.str();}
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define EXIST2(s,e) (find(ALL(s),(e))!=(s).end())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
const double EPS = 1e-9;
const double PI = acos(-1.0);


void read(int i,vi &ans,vi &done,bool &has_read){
	ans.push_back(i);
	done[i]=1;
	has_read=true;
}

pair<string,int> get_type_and_num(vs &marks,int i){
	string type;
	int num;
	REP(j,marks[i].size()){
		if(isdigit(marks[i][j])){
			type=marks[i].substr(0,j);
			num=toInt(marks[i].substr(j));
			break;
		}
	}
	return make_pair(type,num);
}

int main(){
	int n;
	while(cin>>n,n){
		vs marks(n);
		map<string,map<int,vi > > pos;
		REP(i,n){
			cin>>marks[i];
			if(marks[i]!="v"&&marks[i]!="-"){
				pair<string,int> p=get_type_and_num(marks,i);
				pos[p.first][p.second].push_back(i);
			}
		}
		int cur=0;
		int last=0;
		bool has_read=false;
		vi done(n);
		vi ans;
		int i=0;
		while(i<n){
			if(!has_read&&done[i]){
				//6. No letter may be read twice or more. Once a letter is read, the letter must be skipped in the subsequent steps. 
				i++;
				continue;
			}
			if(has_read&&i>0&&marks[i-1][marks[i-1].size()-1]=='v'){
				//5. When the i-th letter is read and (i - 1)-th letter has a 'Re' mark, then (i - 1)-th letter must be read next.
				read(i-1,ans,done,has_read);
				i--;
				continue;
			}
			if(!has_read&&marks[i][marks[i].size()-1]=='v'){
				//4. A letter with a 'Re' mark must be skipped.
				i++;
				has_read=false;
				continue;
			}
			if(marks[i]!="-"){
				pair<string,int> p=get_type_and_num(marks,i);
				string type=p.first;
				int num=p.second;
				if(has_read){
					//3. When the i-th letter with a jump mark of type t, number n is read, and when there exists an unread letter L at position less than i that has a jump mark of type t, number n + 1, then L must be read next. If there is no such letter L, the (k + 1)-th letter is read, where k is the index of the most recently read letter with a jump mark of type t, number 1.
					vi &v=pos[type][num+1];
					vi::iterator it=lower_bound(ALL(v),i);
					if(it==v.begin()){
						i=last+1;
						has_read=false;
						continue;
					}else{
						i=*(it-1);
						read(i,ans,done,has_read);
						continue;
					}
				}else{
					//2. Each jump mark has a type (represented with a string consisting of lower-case letters) and a number (represented with a positive integer). A letter with a jump mark whose number is 2 or larger must be skipped. 
					if(num==1){
						last=i;
						read(i,ans,done,has_read);
						continue;
					}else{
						i++;
						has_read=false;
						continue;
					}
				}
			}
			if(marks[i]=="-"){
				//1. Basically letters are read downwards from top to bottom, i.e. the first letter should be read (or skipped) first, and after the i-th letter is read or skipped, (i + 1)-th letter is read next. 
				if(has_read){
					i++;
					has_read=false;
					continue;
				}else{
					read(i,ans,done,has_read);
					continue;
				}
			}
		}
		REP(i,ans.size()){
			cout<<ans[i]+1<<endl;
		}
	}
}

Measured memory_bytes: 4284