static NFA::CharSet parseSet(const char*& nextChar) { NFA::CharSet result; WAVM_ASSERT_THROW(*nextChar == '['); ++nextChar; bool isNegative = false; if(*nextChar == '^') { isNegative = true; ++nextChar; } while(*nextChar && *nextChar != ']') { result = result | parseCharClass<true>(nextChar); }; ++nextChar; if(isNegative) { result = ~result; result.remove(0); } return result; }
static Node* parseElementary(const char*& nextChar,Uptr groupDepth) { NFA::CharSet charSet; switch(*nextChar) { case '[': { charSet = parseSet(nextChar); break; } case '.': { charSet = ~NFA::CharSet(0); ++nextChar; break; } case '$': { charSet.add('\n'); ++nextChar; break; } default: { charSet = parseCharClass<false>(nextChar); break; } }; return new Lit(charSet); }
static NFA::CharSet parseLit(const char*& nextChar) { NFA::CharSet result; const char c = parseChar<inSet>(nextChar); if(inSet && *nextChar == '-') { ++nextChar; const char d = parseChar<inSet>(nextChar); result.addRange((U8)c,(U8)d); } else { result.add((U8)c); } return result; }
static NFA::CharSet parseCharClass(const char*& nextChar) { if(*nextChar != '\\') { return parseLit<inSet>(nextChar); } else { NFA::CharSet result; switch(nextChar[1]) { case 'd': result.addRange('0','9'); break; case 'w': result.addRange('a','z'); result.addRange('A','Z'); result.addRange('0','9'); result.add('_'); break; case 's': result.add(' '); result.add('\t'); result.add('\f'); result.add('\r'); result.add('\n'); break; default: if(!isMetachar<inSet>(nextChar[1])) { Errors::fatalf("'%c' is not a metachar in this context",nextChar[1]); } result.add(nextChar[1]); break; }; nextChar += 2; return result; } }
static NFA::StateIndex createTokenSeparatorPeekState(NFA::Builder* builder,NFA::StateIndex finalState) { NFA::CharSet tokenSeparatorCharSet; tokenSeparatorCharSet.add(U8(' ')); tokenSeparatorCharSet.add(U8('\t')); tokenSeparatorCharSet.add(U8('\r')); tokenSeparatorCharSet.add(U8('\n')); tokenSeparatorCharSet.add(U8('=')); tokenSeparatorCharSet.add(U8('(')); tokenSeparatorCharSet.add(U8(')')); tokenSeparatorCharSet.add(U8(';')); tokenSeparatorCharSet.add(0); auto separatorState = addState(builder); NFA::addEdge(builder,separatorState,tokenSeparatorCharSet,finalState | NFA::edgeDoesntConsumeInputFlag); return separatorState; }