%{ #include #include #include #include "stb_sb.h" #include "hmmlib.h" const struct HMML_Version hmml_version = { 0, 4, 0 }; typedef struct { int line; HMML_Annotation* annos; HMML_VideoMetaData meta; HMML_Annotation an; HMML_Reference ref; HMML_Error error; void* attr; int mnext; bool first; } HMML_ParseState; #define HMML_ERR(fmt, ...) \ do { \ asprintf(&yyextra->error.message, fmt, ##__VA_ARGS__);\ yyextra->error.line = yyextra->line;\ return 1;\ } while(0) #define CHECKESCAPE(x) do { if(!strchr("[]:@~\\\"", x)) HMML_ERR("Unknown backslash escape code '%c'", x); } while(0) #define V_(x) &yyextra->meta.x #define R_(x) &yyextra->ref.x #define M_(x, state) do { HMML_Marker m = { HMML_ ## x }; sb_push(yyextra->an.markers, m); yyextra->mnext = state; } while(0) #define M_ADD(t, n) \ do { \ char* c = UNQUOTE(strndup(t, n));\ sb_last(yyextra->an.markers).marker = c;\ sb_last(yyextra->an.markers).offset = sb_count(yyextra->an.text);\ if(yyextra->mnext == TEXT){\ memcpy(sb_add(yyextra->an.text, n), c, n);\ }\ } while(0) #define MX_ADD(c) \ do { \ sb_push(sb_last(yyextra->an.markers).parameter, c);\ if(c) sb_push(yyextra->an.text, c);\ } while(0) #define NEWANNO() \ do { \ if(!yyextra->first) sb_push(yyextra->annos, yyextra->an); \ memset(&yyextra->an, 0, sizeof(yyextra->an));\ yyextra->an.line = yyextra->line;\ yyextra->first = false;\ } while(0) #define UNQUOTE_LEN(_attr, _len) ({ \ typeof(_attr) attr = (_attr); \ typeof(_len) len = (_len); \ for(char* c = attr; c < attr+len; ++c){\ if(*c == '\\'){ \ CHECKESCAPE(c[1]); \ memmove(c, c+1, len-(c-attr)); \ --len; \ } \ } \ attr; \ }) #define UNQUOTE(_attr) UNQUOTE_LEN(_attr, strlen(attr)) %} %option reentrant %option extra-type="HMML_ParseState*" %option noyywrap S [\t \r]* ATTR_SIMPLE [^\" \]\t\r\n][^ \]\t\r\n]* ATTR_ALNUM [0-9a-zA-Z][0-9a-zA-Z_]* ATTR_QUOTED \"([^\"\\]|\\.)*\" TAG_VIDEO_OPEN \[video TIMECODE \[[0-9]{1,2}(:[0-5][0-9]){1,2}\] BAD_TIMECODE \[[0-9]{1,2}(:[6-9][0-9]){1,2}\] TEXT_BREAK [^\\:@~\[\]\r\n\t ] LB \[ RB \] %s VIDEO %s V_ATTR %s V2_ATTR %s V3_ATTR %s ANNOTATION %s TEXT_START %s TEXT %s MARKER %s MARKER_XTRA %s REF %s R_ATTR %s AFTERTEXT %s AUTHOR %s CATEGORIES %s QUOTES %% <> { HMML_ERR("Unexpected EOF, video close tag not found."); } \r\n|\n { yyextra->line++; } {TAG_VIDEO_OPEN} { BEGIN(VIDEO); } . { HMML_ERR("Missing video tag."); }