#include <bits/stdc++.h>

#define REP(i,n) for(int i=0;i<(int)n;++i)

using namespace std;

enum ET {
  FACTOR,
  PL,
  PR,
  BL,
  BR,
  ADD,
  MUL,
  EXPR,
  TERM,
  PE,
  PT,
  PF1,
  PF2
};

int main() {
  while(1){
    int n,m,s,t;
    cin>>n>>m>>s>>t;
    --s;--t;
    if(!n)break;
    vector<vector<vector<bool>>> mat(n, vector<vector<bool>>(n, vector<bool>(13, false)));
    string chars = "a()[]+*";
    using T = tuple<int, int, ET>;
    queue<T> qe;
    vector<vector<T>> g(n);
    vector<vector<T>> rg(n);
    REP(i,m){
      int a,b;
      string s;
      cin>>a>>b>>s;
      --a;--b;
      ET et = static_cast<ET>(chars.find(s[0]));
      qe.emplace(a,b,et);
      g[a].emplace_back(a,b,et);
      rg[b].emplace_back(a,b,et);
      mat[a][b][et] = true;
    }
    while(!qe.empty()) {
      int a,b;
      ET et;
      tie(a,b,et) = qe.front(); qe.pop();
      switch(et) {
        case FACTOR:
          if (!mat[a][b][TERM]) {
            qe.emplace(a,b,TERM);
            g[a].emplace_back(a,b,TERM);
            rg[b].emplace_back(a,b,TERM);
            mat[a][b][TERM] = true;
          }
        case TERM:
          if (!mat[a][b][EXPR]) {
            qe.emplace(a,b,EXPR);
            g[a].emplace_back(a,b,EXPR);
            rg[b].emplace_back(a,b,EXPR);
            mat[a][b][EXPR] = true;
          }
          break;
      }
      for(const T &e : g[b]) {
        int na, nb;
        ET net;
        tie(na, nb, net) = e;
#define FIX(CODE) \
        if (!mat[a][nb][CODE]) {\
          qe.emplace(a,nb,CODE);\
          g[a].emplace_back(a,nb,CODE);\
          rg[nb].emplace_back(a,nb,CODE);\
          mat[a][nb][CODE] = true;\
        }
        switch(et) {
          case PL:
            if (net == EXPR) FIX(PF1)
            break;
          case BL:
            if (net == EXPR) FIX(PF2)
            break;
          case TERM:
            if (net == MUL) FIX(PT)
            break;
          case EXPR:
            if (net == ADD) FIX(PE)
            break;
          case PF1:
            if (net == PR) FIX(FACTOR)
            break;
          case PF2:
            if (net == BR) FIX(FACTOR)
            break;
          case PT:
            if (net == FACTOR) FIX(TERM)
            break;
          case PE:
            if (net == TERM) FIX(EXPR)
            break;
        }
      }
      for(const T &e : rg[a]) {
        int na, nb;
        ET net;
        tie(na, nb, net) = e;
#define FIX2(CODE) \
        if (!mat[na][b][CODE]) {\
          qe.emplace(na,b,CODE);\
          g[na].emplace_back(na,b,CODE);\
          rg[b].emplace_back(na,b,CODE);\
          mat[na][b][CODE] = true;\
        }
        switch(et) {
          case TERM:
            if (net == PE) FIX2(EXPR)
            break;
          case FACTOR:
            if (net == PT) FIX2(TERM)
            break;
          case PR:
            if (net == PF1) FIX2(FACTOR)
            break;
          case BR:
            if (net == PF2) FIX2(FACTOR)
            break;
          case EXPR:
            if (net == PL) FIX2(PF1)
            if (net == BL) FIX2(PF2)
            break;
        }
      }
    }
    if (mat[s][t][EXPR])
      cout << "Yes" << endl;
    else
      cout << "No" << endl;
  }
  return 0;
}