Mpji1RdZiddddddddd d d d d dddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1Zidd2dd2d d3d d3d d3dd3dd2d4d2dd2dd2dd2dd3dd3dd3dd3d d3d5d3d3d3d3d3d3d3d3d6d3d6d2d3d2d7 Zd8Zd9Zed:k(reey;y;) '}}' start: {start} // Parse
document: {document} // A group consists of text and control words or control symbols enclosed in braces ({{}}). // The opening brace ({{ ) indicates the start of the group and the closing brace ( }}) indicates the end of the group. group: {group} // ====== CONTROL WORD(s) ====== // A control word is defined by: \ // A control word’s name cannot be longer than 32 letters. CONTROLWORD: {CONTROLWORD} // === Delimiter == DELIMITER: {DELIMITER} // The can be one of the following: // 1. A numeric digit or an ASCII minus sign (-), which indicates that a numeric parameter is associated with the control word. NUMERICALDEL: {NUMERICALDEL} // 2. A space: When a space is used as a the delimiter, it is discarded. This means that it’s not included in subsequent processing. So, we are using a discarded terminal (by putting a underscore in front of the name) to ensure it is tossed. // See: "_SPACE_DELETE" under SIMPLE GRAMMAR OBJECTS // 3. Any character other than a letter or a digit. In this case, the delimiting character terminates the control word and is not part of the control word. So, it's not included in the grammar here. // ====== CONTROL SYMBOLS(s) ====== // A control symbol consists of a backslash followed by a single, nonalphabetic character. // For example, \~ represents a nonbreaking space. // The STAR_ESCAPE special construct means that if the program understands the \command, it takes this to mean {\command ...}, but if it doesn’t understand \command, the program ignores not just \command (as it would anyway) but everything in this group. STAR_ESCAPE: {STAR_ESCAPE} NONBREAKING_HYPHEN: {NONBREAKING_HYPHEN} OPTIONAL_HYPHEN: {OPTIONAL_HYPHEN} NONBREAKING_SPACE: {NONBREAKING_SPACE} FORMULA_CHARACTER: {FORMULA_CHARACTER} INDEX_SUBENTRY: {INDEX_SUBENTRY} // Control symbols take no delimiters. control_symbol: {control_symbol} // ====== SPECIAL CONTROL WORD(s) ====== // ====== HEADER OBJECTS ====== // The FROMHTML control word specifies that the RTF document contains encapsulated HTML text. // This control word MUST be \fromhtml1. Any other form, such as \fromhtml or \fromhtml0, will not be considered encapsulated // FROMTEXT: {FROMTEXT} //The FROMHTML control word specifies that the RTF document contains encapsulated HTML text. // This control word MUST be \fromhtml1. Any other form, such as \fromhtml or \fromhtml0, will not be considered encapsulated. //FROMHTML : {FROMHTML} // ====== SPECIFIC CONTROL WORD OBJECTS ====== // HTMLRTF Toggle Control Word // The HTMLRTF control word identifies fragments of RTF that were not in the original HTML content // If the flag is "\htmlrtf" or "\htmlrtf1" then do not process anything else until you encounter "\htmlrtf0" which will toggle this off again. // A de-encapsulating RTF reader MUST support the HTMLRTF control word within nested groups. The state of the HTMLRTF control word MUST transfer when entering groups and be restored when exiting groups. // This means that you can only turn this off on it's own level (turning it off in an object nested within it does nothing). And, if the object it's in ends then it doesn't transfer up the tree to objects that contain it. So, if you don't find a closing "\htmlrtf0" you can delete from the opening "\htmlrtf" all the way until the end of the current object, but not above. HTMLRTF : {HTMLRTF} // The HTMLTAG destination group encapsulates HTML fragments that cannot be directly represented in RTF htmltag_group: {htmltag_group} // The "DIGIT~0..3" in the following definition is the HTMLTagParameter from the spec. // A space MUST be used to separate the CONTENT HTML fragment from the HTMLTagParameter HTML fragment if the text starts with a DIGIT, or if the HTMLTagParameter HTML fragment is omitted. As such, we throw away this space by using _SPACE_DELETE if we encounter one. HTMLTAG: {HTMLTAG} content : {content} // \*\mhtmltag[HTMLTagParameter] [CONTENT] // The values and format of the numeric parameter are identical to the numeric parameter in the HTMLTAG destination group. // This RTF control word SHOULD be skipped on de-encapsulation and SHOULD NOT be written when encapsulating. # TODO: https://datatracker.ietf.org/doc/html/draft-ietf-mhtml-cid-00#section-1 // NOTE: mhtmltag's contain original URL which has been replaced in the corresponding htmltag with the CID of an object. As such, it contains possibly useful URI data that, while not useful for the direct output, should be saved. MHTMLTAG : {MHTMLTAG} mhtmltag_group: {mhtmltag_group} // TODO: Check if really neeeded // Increased priority of escape chars to make unescaping easier // Multiple char acceptance is important here because if you just catch one escape at a time you mess up multi-byte values. _QUESTION_MARK: {_QUESTION_MARK} // TODO Define these objects // RTFESCAPE no longer used // RTFESCAPE : {RTFESCAPE} // UNICODE unicode chars UNICODE : {UNICODE} // Hex chars [HEXENCODED] are stored in an array [hexarray] // We often need to parse hex chars as a set so this is the easiest way HEXENCODED : {HEXENCODED} hexarray : {hexarray} )r'r()r)s r,make_literate_grammarr1s4 ggN OgNOgGP Nr.__main__N)HTMLRTF_GRAMMARr(r%r-r1__name__printr0r.r,r6s`" 9  9  $9 v9 v9 9  (9 #9 * 0+9 B?C9 D7E9 F9G9 HAI9 J%K9 LVM9 N&O9 P/Q9 RJS9 TC#*'))&H%,/7q9 J t t$ d     T dtTd4$ D!"4#$=Bnb z  !r.