//.............................................................................. // // This file is part of the Jancy toolkit. // // Jancy is distributed under the MIT license. // For details see accompanying license.txt file, // the public copy of which is also available at: // http://tibbo.com/downloads/archive/jancy/license.txt // //.............................................................................. // Jancy features 'reswitch' statement as a built-in support for creating // protocol analyzers, programming language lexers and other recognizers. // If you ever used tools like Lex, Flex, Ragel etc then you are already // familiar with the idea. If not, then it is pretty simple, actually. First, // you define a list of recognized lexemes in form of regular expressions. Then // you specify which actions to execute when these lexemes are found in the // input stream. Jancy compiler will then automatically build a DFA to // recognize your language. //.............................................................................. bool errorcode fooBar ( jnc.RegexState* state, const char* p, size_t length = -1 ) { if (length == -1) length = strlen (p); const char* end = p + length; // post-condition loop allows passing 'null' as eof do { reswitch (state, p, end - p) { case "foo": printf ("lexeme found: foo\n"); break; case "bar": printf ("lexeme found: bar\n"); break; case r"\d+": // you can access matched lexeme via jnc.RegexState.m_match field printf ("lexeme found: dec '%s'\n", state.m_match.m_text); break; case r"\s+": // ignore whitespace break; default: // we can get here for two reasons only: // 1) mismatch // 2) incremental recognition if (!state.m_consumedLength) return false; assert (state.m_isIncremental && state.m_consumedLength == end - p); } p += state.m_consumedLength; // advance to the next lexeme } while (p < end) return true; } //.............................................................................. // entry point int main () { printf ("main ()\n"); // you need a jnc.RegexState object to store the state of DFA jnc.RegexState state; char const* p = " foo bar 100 baz"; bool result = try fooBar (state, p); if (!result) printf ("recognition error at: %s\n", p + state.m_currentOffset); // It's OK to perform recognition incrementally, chunk by chunk. // This is cructial when analyzing protocols operating over stream // transports like TCP or Serial, where it is not guaranteed that a message // will be delivered as a whole and not as multiple segments. state.reset (); state.m_isIncremental = true; // turn on incremental matching try { fooBar (state, " ba"); fooBar (state, "r f"); fooBar (state, "oo "); fooBar (state, "100"); fooBar (state, "000"); // Incremental recognizer must be notified about eof -- this // can trigger actions or errors. fooBar (state, null); catch: printf ("recognition error\n"); } return 0; } //..............................................................................