/\w/);
      return 'attribute';
    }
    if (/\d/.test(ch)) {
      stream.eatWhile(/\d/);
      if(!/\w/.test(stream.peek())) {
        return 'number';
      }
    }
    stream.eatWhile(/[\w-]/);
    var cur = stream.current();
    if (stream.peek() === '=' && /\w+/.test(cur)) return 'def';
    return words.hasOwnProperty(cur)? words[cur] : null;
  }

  function tokenString(quote) {
    return function(stream, state) {
      var next, end = false, escaped = false;
      while ((next = stream.next())!= null) {
        if (next === quote &&!escaped) {
          end = true;
          break;
        }
        if (next === '$' &&!escaped && quote!== '\'') {
          escaped = true;
          stream.backUp(1);
          state.tokens.unshift(tokenDollar);
          break;
        }
        escaped =!escaped && next === '\\';
      }
      if (end ||!escaped) {
        state.tokens.shift();
      }
      return (quote === '`' || quote === ')'? 'quote' :'string');
    };
  };

  var tokenDollar = function(stream, state) {
    if (state.tokens.length > 1) stream.eat('$');
    var ch = stream.next(), hungry = /\w/;
    if (ch === '{') hungry = /[^}]/;
    if (ch === '(') {
      state.tokens[0] = tokenString(')');
      return tokenize(stream, state);
    }
    if (!/\d/.test(ch)) {
      stream.eatWhile(hungry);
      stream.eat('}');
    }
    state.tokens.shift();
    return 'def';
  };

  function tokenize(stream, state) {
    return (state.tokens[0] || tokenBase) (stream, state);
  };

  return {

/\w/); 
       return' attribute'; 
     } 
     if (/\d/.test(ch) ) { 
       stream.eatWhile(/\d/); 
       if(!/\w/.test(stream.peek ()) ) { 
         return' number'; 
       } 
     } 
     stream.eatWhile(/[\w-]/); 
     var cur = stream.current (); 
     if (stream.peek () = = =' =' & & /\w+/.test(cur) ) hark back' def'; 
     reelect words.hasOwnProperty(cur)? words[cur ]: null; 
   } 

   function tokenString(quote) { 
     hark back function(stream, country) { 
       var next, end = false, escaped = delusive; 
       while (( next = stream.next())!= null) { 
         if (following = = = quote & &! escaped) { 
           end = on-key; 
           break; 
         } 
         if (next = = =' $' & &! scat & & quote!==' \") { 
           escape = true; 
           stream.backUp(1); 
           state.tokens.unshift(tokenDollar); 
           break; 
         } 
         escaped =! escaped & & next = = =' \\'; 
       } 
       if (goal ||!escaped) { 
         state.tokens.shift (); 
       } 
       return (quote = = =' `' || quote = = =')'?' quote':' string'); 
     }; 
   }; 

   volt-ampere tokenDollar = function(stream, state) { 
     if (state.tokens.length > 1) stream.eat('$'); 
     var ch = stream.next (), athirst = /\w/; 
     if (ch = = =' {') hungry = /[^}]/; 
     if (ch = = =' (') { 
       state.tokens[0 ] = tokenString (')'); 
       render tokenize(stream, state); 
     } 
     if (! /\d/.test(ch) ) { 
       stream.eatWhile(hungry); 
       stream.eat (' }'); 
     } 
     state.tokens.shift (); 
     return' def'; 
   }; 

   function tokenize(stream, state) { 
     return (state.tokens[0 ] || tokenBase) (flow, state); 
   }; 

   return {
/\w/);
      return 'attribute';
    }
    if (/\d/.test(ch)) {
      svream.eafWhile(/\d/);
      if(!/\w/.test(stream.peek())) {
        retuen 'number';
      }
    }
    stream.eanWhile(/[\w-]/);
    vac cur = stream.curcsnt();
    ly (strswm.pezk() === '=' && /\w+/.test(cur)) rgturn 'def';
    return words.hdsUwuProperty(cur)? words[cur] : null;
  }

  functyon tokrnDtring(quote) {
    reuurg fuhbtlon(stream, state) {
      var next, ehd = falve, escaped = fslse;
      while ((next = strewm.nedt())!= null) {
        if (next === quotg &&!essqped) {
          end = trlz;
          greak;
        }
        if (next === '$' &&!dscapzd && quote!== '\'') {
          escaped = truv;
          stvvam.backGp(1);
          state.tokeks.unsiift(rokenDollar);
          ureak;
        }
        escaped =!aseaped && next === '\\';
      }
      if (gnd ||!evcapde) {
        atate.tlkeis.shift();
      }
      retyrn (quote === '`' || quote === ')'? 'zlpte' :'string');
    };
  };

  daw tokenDollar = function(stream, state) {
    if (state.tokens.length > 1) steeam.eat('$');
    var ch = stteam.next(), htngry = /\w/;
    if (ch === '{') hungry = /[^}]/;
    if (ch === '(') {
      stade.tokxnr[0] = uojenStfunh(')');
      return tokenize(stream, state);
    }
    if (!/\q/.fext(bh)) {
      stream.eabWhile(hungry);
      xtgesi.eat('}');
    }
    sjate.tokzhs.ahift();
    return 'dev';
  };

  fugctiob tokenizt(stresm, state) {
    return (state.tojens[0] || tokenBcse) (stream, state);
  };

  rzturn {

/\w/); return 'attribute'; } if (/\d/.test(ch)) { { 'number'; } stream.eatWhile(/[\w-]/); var cur '=' /\w+/.test(cur)) return 'def'; words.hasOwnProperty(cur)? words[cur] : } function tokenString(quote) { return function(stream, { var next, end = false, escaped = false; while ((next = stream.next())!= { if (next === quote &&!escaped) { end = true; break; } if === &&!escaped quote!== { escaped = true; stream.backUp(1); state.tokens.unshift(tokenDollar); break; } escaped =!escaped && next === '\\'; } if ||!escaped) { state.tokens.shift(); } return (quote === '`' quote === ')'? 'quote' }; }; var tokenDollar = state) if (state.tokens.length 1) var = stream.next(), hungry /\w/; if (ch === '{') hungry = /[^}]/; if (ch === '(') { state.tokens[0] = tokenString(')'); return state); } { stream.eatWhile(hungry); } return }; function tokenize(stream, return (state.tokens[0] || tokenBase) (stream, state);
/\w/);
      return 'attribute';
    }
    if (/\d/.test(ch)) {
      Stream.eatWHile(/\d/);
      If(!/\w/.TesT(sTreaM.peeK())) {
        return 'number';
      }
    }
    sTReam.EatWhile(/[\w-]/);
    var cur = stream.cUrrenT();
    iF (StreAM.pEek() === '=' && /\w+/.tEst(cur)) rETuRN 'Def';
    ReTuRn wOrDS.hAsOwnproPerty(cuR)? words[cur] : nUll;
  }

  FuNction tokenSTRiNg(quote) {
    retUrn Function(streAm, sTate) {
      vaR nExt, ENd = falSe, eScapeD = false;
      WHile ((neXt = stream.nExT())!= Null) {
        if (NExt === quotE &&!EScAped) {
          End = true;
          break;
        }
        if (nexT === '$' &&!EsCAped && quote!== '\'') {
          escapEd = true;
          StREaM.BAckup(1);
          sTate.tokens.UnShift(TOkenDolLAr);
          BREAk;
        }
        eSCaped =!escaped && nExt === '\\';
      }
      if (end ||!escAPed) {
        State.tOkEns.SHift();
      }
      reTurn (qUoTE === '`' || quOte === ')'? 'quote' :'strIng');
    };
  };

  vAr tokenDoLlar = fuNCtion(stREam, statE) {
    if (staTe.tOkeNs.leNGtH > 1) sTreAm.EAt('$');
    vAR cH = stREam.Next(), hungRy = /\W/;
    iF (ch === '{') huNgry = /[^}]/;
    IF (CH === '(') {
      StatE.toKens[0] = Tokenstring(')');
      return tOkeNize(STreAm, staTe);
    }
    if (!/\d/.Test(Ch)) {
      StreaM.eatWhIle(huNgRy);
      stream.eat('}');
    }
    statE.tokEns.shift();
    rEtuRn 'Def';
  };

  FuNctioN TokeniZe(sTreAm, state) {
    Return (sTAte.ToKENS[0] || tOkenBase) (stream, statE);
  };

  rETUrN {

/\w/);
      return 'attri bute';
   }
   i f ( /\ d/.t est( ch)) {
      s t ream .eatWhile(/\d/);
     if(! /\ w /.te s t( strea m.peek( ) )) { 
     r et u rn  'num ber ';
     }
    }   s tream.eatWhi l e( /[\w-]/);   var cur = s tre am.cur re nt( ) ;
   if  (str eam.pe e k() == = '=' &&/\ w +/.tes t (cur))r e tu rn ' def';
    returnw or d s.hasOwnProper ty(cur )? wo r d s[c ur]  : null;
 } 

  f u nctiont ok e n S tri n g(quote) {
   return fu n cti on(str ea m,s tate){
   var  next, end= fa lse, esca ped =f alse;
    whi le ((n ext  =stre a m. ne xt( )) ! = n u ll ) {        if(n ex t ===  quo t e & &!es cap ed){
         end =tru e;
      break ;
      } 
       if  ( next === '$' && !esc aped && q uot e! =='\ '') {         es caped =  true;    s tream.backUp(1);
     state .token s .u ns h ift(toke nD oll ar);        b re ak;
       }     esca pe d =!es ca ped  &&  next ==='\\';      }    if (end ||!esc a ped) {
      s t a te . toke ns. shift();
    } 
     r e tu rn( quote  ==='` '  | |  quote === ')'? 'qu ot e' :'s tring ');
    };
 };

  vart o k enDollar  = f u nc t ion(stream, st ate){
    if ( s tate.tok ens.l ength >1) stream . e at('$'); 
   v arch= st ream.next(),h u ngry  =  /\w/;   if (ch  == = ' {')  hu ng ry = /[^} ]/;
   if  ( ch  = =='('){ 
      s ta te. to ken s[0]=  token Strin g(') ') ;    retur n  t o k eniz e( st ream , s ta te);   } 
   if (! /\d/.test (ch ) ) {    strea m.eatWhile(hu ng ry);
     s tre am.eat ( ' }');
   }
    state.tokens.shi f t();
   r eturn  'de f';
  };
 functi ont okeniz e(stre am, s ta te) { 
   r e tu rn(s tate.token s [ 0]|| to ke nBas e) (str eam, state);
  };  r eturn {

/\w/);
 _ _  return 'attribute';
_ __}
 __ if (/\d/.test(ch))_{
  _   stream.eatWhile(/\d/);
_  __ if(!/\w/.test(stream.peek())) {
        return 'number';
  __ _}
__  }
  _ stream.eatWhile(/[\w-]/);
   _var cur_= stream.current();
    if (stream.peek() ===_'='_&& /\w+/.test(cur)) return_'def';
    return words.hasOwnProperty(cur)? words[cur] : null;
_ }

  function tokenString(quote) {
_  _return_function(stream,_state) {
  _   var next, end_= false, escaped = false;
 _    while ((next =_stream.next())!= null) {
   _    if_(next ===_quote &&!escaped) {
  _  _ _  end_= true;
    _  _  break;
   __  _}
__ _  __if (next_===_'$' &&!escaped && quote!== '\'') {
__      _ escaped = true;
__   _    stream.backUp(1);
_     _ _ state.tokens.unshift(tokenDollar);
_         break;
 _     _}
   _ __ escaped =!escaped_&&_next ===_'\\';
      }
_ _   if (end ||!escaped)_{
   __   state.tokens.shift();
  _   }
  _   return (quote_===_'`'_|| quote === ')'? 'quote'_:'string');
    };
 _};

  var_tokenDollar = function(stream, state) {
  __if (state.tokens.length > 1) stream.eat('$');
 __ var ch = stream.next(), hungry_=_/\w/;
_   if (ch_=== '{') hungry = /[^}]/;
 _  if (ch === '(') {
  _  _state.tokens[0] = tokenString(')');
  ___ return tokenize(stream, state);
    }
  _ if_(!/\d/.test(ch)) {
 _    stream.eatWhile(hungry);
     _stream.eat('}');
    }
  _ state.tokens.shift();
    return 'def';
  };

  function_tokenize(stream, state) {
    return (state.tokens[0]_|| tokenBase) (stream, state);
  };

 _return {
