#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using Pi = pair<int, int>;
using Pl = pair<ll, ll>;
using vint = vector<int>;
using vvint = vector<vint>;
using vvvint = vector<vvint>;
using vll = vector<ll>;
using uint = unsigned int;
using ull = unsigned long long;

template<typename T> using uset = unordered_set<T>;
template<typename T1, typename T2> using umap = unordered_map<T1, T2>;

constexpr int INF = (1 << 30) - 1;
constexpr ll LLINF = 1LL << 60;
constexpr int dy[] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dx[] = {0, 1, 0, -1, 1, 1, -1, -1};
constexpr char el = '\n';
constexpr int mod = 1000000007;

template<typename T> T gcd(T a, T b) { return (b ? gcd(b, a % b) : a); }
template<typename T> T lcm(T a, T b) { return (a / gcd(a, b) * b); }
template<typename T1, typename T2> inline void chmin(T1 &a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> inline void chmax(T1 &a, T2 b) { if (a < b) a = b; }

template<typename T>
ostream& operator <<(ostream &os, vector<T> &v) {
	for (auto &u : v) os << u << el;
	return (os);
}

template<typename T>
istream& operator >>(istream &is, vector<T> &v) {
	for (auto &u : v) is >> u;
	return (is);
}

template<typename T1, typename T2>
istream& operator >>(istream &is, pair<T1, T2> &p) {
	return (is >> p.first >> p.second);
}

vector<vector<vector<bool>>> dat;
vvvint dp;
int N, M, s, t;

//p = 0 -> どっちもfactor
//p = 1 -> op factor
//p = 2 -> ( factor
//p = 3 -> ( op
//p = 4 -> [ factor
//p = 5 -> ( op
//p = 6 -> factor op(臨時追加)
//ちなみに()になるとこれ自体がfactorになるのでよい


bool solve() {
	queue<tuple<int, int, int>> que;
	cin >> N >> M >> s >> t; --s, --t;
	if (N == 0 && M == 0) return (false);
	dat = vector<vector<vector<bool>>>(N, vector<vector<bool>>(N, vector<bool>(8, false)));
	dp = vvvint(N, vvint(N, vint(7, 0)));
	for (int i = 0; i < M; i++) {
		int a, b; cin >> a >> b; --a, --b;
		char c; cin >> c;
		if (c == 'a') { dat[a][b][0] = dp[a][b][0] = true; que.emplace(a, b, 0); }
		if (c == '+' || c == '*') dat[a][b][1] = true;
		if (c == '(') dat[a][b][2] = true;
		if (c == ')') dat[a][b][3] = true;
		if (c == '[') dat[a][b][4] = true;
		if (c == ']') dat[a][b][5] = true;
	}
	
	while (!que.empty()) {
		int u, v, p;
		tie(u, v, p) = que.front(); que.pop();
		if (p == 0) {
			for (int i = 0; i < N; i++) {
				int ar[] = {1, 2, 4};
				int ar2[] = {1, 2, 4};
				for (int j = 0; j < 3; j++) {
					if (dat[i][u][ar[j]] && !dp[i][v][ar2[j]]) {
						dp[i][v][ar2[j]] = true;
						que.emplace(i, v, ar2[j]);
					}
				}
			}
			for (int i = 0; i < N; i++) {
				if (dat[v][i][1] && !dp[u][i][6]) {
					dp[u][i][6] = true;
					que.emplace(u, i, 6);
				}
			}
		}
		if (p == 1) {
			for (int i = 0; i < N; i++) {
				if (dat[i][u][0] && !dp[i][v][0]) {
					dp[i][v][0] = true;
					que.emplace(i, v, 0);
				}
			}
			for (int i = 0; i < N; i++) {
				if (dp[i][u][0] && !dp[i][v][0]) {
					dp[i][v][0] = true;
					que.emplace(i, v, 0);
				}
			}
		}
		if (p == 2) {
			for (int i = 0; i < N; i++) {
				int ar[] = {1, 3};
				int ar2[] = {3, 0};
				for (int j = 0; j < 2; j++) {
					if (dat[v][i][ar[j]] && !dp[u][i][ar2[j]]) {
						dp[u][i][ar2[j]] = true;
						que.emplace(u, i, ar2[j]);
					}
				}
			}
		}
		if (p == 3) {
			for (int i = 0; i < N; i++) {
				if (dat[v][i][0] && !dp[u][i][2]) {
					dp[u][i][2] = true;
					que.emplace(u, i, 2);
				}
			}
		}
		if (p == 4) {
			for (int i = 0; i < N; i++) {
				int ar[] = {1, 5};
				int ar2[] = {5, 0};
				for (int j = 0; j < 2; j++) {
					if (dat[v][i][ar[j]] && !dp[u][i][ar2[j]]) {
						dp[u][i][ar2[j]] = true;
						que.emplace(u, i, ar2[j]);
					}
				}
			}
		}
		if (p == 5) {
			for (int i = 0; i < N; i++) {
				if (dat[v][i][0] && !dp[u][i][4]) {
					dp[u][i][4] = true;
					que.emplace(u, i, 4);
				}
			}
		}
		if (p == 6) {
			for (int i = 0; i < N; i++) {
				if (dat[v][i][0] && !dp[u][i][0]) {
					dp[u][i][0] = true;
					que.emplace(u, i, 0);
				}
			}
			for (int i = 0; i < N; i++) {
				if (dp[v][i][0] && !dp[u][i][0]) {
					dp[u][i][0] = true;
					que.emplace(u, i, 0);
				}
			}
		}
	}
	cout << (dp[s][t][0] ? "Yes" : "No") << endl;
	return (true);
}
int main() {
	while (solve());		
	return (0);
}



Measured memory_bytes: 11740