Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1350 lines (1095 sloc) 52.13 kb
%{
/**********************************************************************
markdown_parser.leg - markdown parser in C using a PEG grammar.
(c) 2008 John MacFarlane (jgm at berkeley dot edu).
portions Copyright (c) 2010-2011 Fletcher T. Penney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License or the MIT
license. See LICENSE for details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
***********************************************************************/
#include <stdbool.h>
#include <assert.h>
#include "markdown_peg.h"
#include "utility_functions.h"
/**********************************************************************
Definitions for leg parser generator.
YY_INPUT is the function the parser calls to get new input.
We take all new input from (static) charbuf.
***********************************************************************/
# define YYSTYPE element *
#ifdef __DEBUG__
# define YY_DEBUG 1
#endif
#define YY_INPUT(buf, result, max_size) \
{ \
int yyc; \
if (charbuf && *charbuf != '\0') { \
yyc= *charbuf++; \
} else { \
yyc= EOF; \
} \
result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \
}
#define YY_RULE(T) T
#define YY_DEBUG_OFF
/**********************************************************************
PEG grammar and parser actions for markdown syntax.
***********************************************************************/
%}
Doc = BOM? a:StartList ( Block { a = cons($$, a); } )*
{ parse_result = reverse(a); }
DocWithMetaData = BOM? a:StartList b:StartList
( &{ !extension(EXT_COMPATIBILITY) }
&( MetaDataKey Sp ':' Sp (!Newline)) MetaData
{ a = cons($$, a); b = mk_element(FOOTER);})?
( Block { a = cons($$, a); } )*
{ if (b != NULL) a = cons(b, a);
parse_result = reverse(a);
}
MetaData = a:StartList !([A-Za-z]+ "://")
(MetaDataKeyValue { a = cons($$, a); })+
{ $$ = mk_list(LIST, a);
$$->key = METADATA;
}
MetaDataOnly = BOM? a:StartList
( MetaData { a = cons($$, a); } )?
# SkipBlock*
.*
{ parse_result = reverse(a); }
MetaDataOnly2 = BOM? a:StartList
( MetaData { a = cons($$, a); } )?
# SkipBlock*
.*
{ parse_result = mk_list(LIST,a); }
MetaDataKeyValue = a:MetaDataKey
Sp ':' Sp b:MetaDataValue
{ $$ = a;
$$->children = b;
}
MetaDataKey = < !([A-Za-z]+ "://") AlphanumericAscii ( Sp ( AlphanumericAscii | '_' | ' ' | '-')+)* >
{
char *label = label_from_string(yytext,0);
$$ = mk_str(label);
free(label);
$$->key = METAKEY;
}
SingleLineMetaKeyValue = MetaDataKey Sp ':' Sp (!Newline .)*
MetaDataValue = a:StartList
((< (!Newline .)* > { a = cons(mk_str(yytext), a); })
((Newline &(!BlankLine !SingleLineMetaKeyValue Sp RawLine))
{ a = cons(mk_str("\n"), a);} | Newline)
(!BlankLine !SingleLineMetaKeyValue Sp RawLine
{ a = cons(mk_str(yytext), a);} )* )
{ $$ = mk_str_from_list(a,false);
trim_trailing_whitespace($$->contents.str);
$$->key = METAVALUE;
}
Block = BlankLine*
( BlockQuote
| Verbatim
| &{ !extension(EXT_COMPATIBILITY) } DefinitionList
| &{ !extension(EXT_COMPATIBILITY) } Glossary
| Note
| Reference
| HorizontalRule
| HeadingSection
| OrderedList
| BulletList
| HtmlBlock
| MarkdownHtmlBlock
| StyleBlock
| &{ !extension(EXT_COMPATIBILITY) } Table
| &{ !extension(EXT_COMPATIBILITY) } ImageBlock
| !(Sp? HtmlBlockOpenDiv) Para
| Plain )
HeadingSectionBlock =
BlankLine*
!Heading
( BlockQuote
| Verbatim
| &{ !extension(EXT_COMPATIBILITY) } DefinitionList
| &{ !extension(EXT_COMPATIBILITY) } Glossary
| Note
| Reference
| HorizontalRule
| OrderedList
| BulletList
| HtmlBlock
| MarkdownHtmlBlock
| StyleBlock
| &{ !extension(EXT_COMPATIBILITY) } Table
| &{ !extension(EXT_COMPATIBILITY) } ImageBlock
| !(Sp? HtmlBlockOpenDiv) Para
| Plain )
Para = NonindentSpace a:Inlines BlankLine+
{ $$ = a; $$->key = PARA; }
Plain = a:Inlines
{ $$ = a; $$->key = PLAIN; }
AtxInline = !Newline !( &{ !extension(EXT_COMPATIBILITY) } Sp AutoLabel Sp? '#'* Sp Newline) !(Sp? '#'* Sp Newline) Inline
AtxStart = < ( "######" | "#####" | "####" | "###" | "##" | "#" ) >
{ $$ = mk_element(H1 + (strlen(yytext) - 1)); }
AtxHeading = s:AtxStart Sp? a:StartList ( AtxInline { a = cons($$, a); } )+ ( Sp? b:AutoLabel { append_list(b,a);})? (Sp? '#'* Sp)? Newline
{ $$ = mk_list(s->key,a);
free(s); }
SetextHeading = SetextHeading1 | SetextHeading2
SetextBottom1 = '='+ Newline
SetextBottom2 = '-'+ Newline
SetextHeading1 = &(RawLine SetextBottom1)
a:StartList ( !Endline !( &{ !extension(EXT_COMPATIBILITY) } Sp AutoLabel ) Inline { a = cons($$, a); } )+ ( Sp b:AutoLabel { append_list(b,a);} Sp? )? Sp? Newline
SetextBottom1 { $$ = mk_list(H1, a); }
SetextHeading2 = &(RawLine SetextBottom2)
a:StartList ( !Endline !( &{ !extension(EXT_COMPATIBILITY) } Sp AutoLabel ) Inline { a = cons($$, a); } )+ ( Sp b:AutoLabel { append_list(b,a)} Sp? )? Sp? Newline
SetextBottom2 { $$ = mk_list(H2, a); }
Heading = SetextHeading | AtxHeading
HeadingSection = a:StartList Heading { a = cons($$, a); }
(HeadingSectionBlock {a = cons($$, a); })*
{ $$ = mk_list(HEADINGSECTION, a);}
BlockQuote = a:BlockQuoteRaw
{ $$ = mk_element(BLOCKQUOTE);
$$->children = a;
}
BlockQuoteRaw = a:StartList
(( '>' ' '? Line { a = cons($$, a); } )
( !'>' !BlankLine Line { a = cons($$, a); } )*
( BlankLine { a = cons(mk_str("\n"), a); } )*
)+
{ $$ = mk_str_from_list(a, true);
$$->key = RAW;
}
NonblankIndentedLine = !BlankLine IndentedLine
VerbatimChunk = a:StartList
( BlankLine { a = cons(mk_str("\n"), a); } )*
( NonblankIndentedLine { a = cons($$, a); } )+
{ $$ = mk_str_from_list(a, false); }
Verbatim = a:StartList ( VerbatimChunk { a = cons($$, a); } )+ BlankLine*
{ $$ = mk_str_from_list(a, false);
$$->key = VERBATIM; }
HorizontalRule = NonindentSpace
( '*' Sp '*' Sp '*' (Sp '*')*
| '-' Sp '-' Sp '-' (Sp '-')*
| '_' Sp '_' Sp '_' (Sp '_')*)
Sp Newline BlankLine+
{ $$ = mk_element(HRULE); }
Bullet = !HorizontalRule NonindentSpace ('+' | '*' | '-') Spacechar+
BulletList = &Bullet (ListTight | ListLoose)
{ $$->key = BULLETLIST; }
ListTight = a:StartList
( ListItemTight { a = cons($$, a); } )+
BlankLine* !(Bullet | Enumerator)
{ $$ = mk_list(LIST, a); }
ListLoose = a:StartList
( b:ListItem BlankLine*
{ element *li;
li = b->children;
li->contents.str = realloc(li->contents.str, strlen(li->contents.str) + 3);
strcat(li->contents.str, "\n\n"); /* In loose list, \n\n added to end of each element */
a = cons(b, a);
} )+
{ $$ = mk_list(LIST, a); }
ListItem = ( Bullet | Enumerator )
a:StartList
ListBlock { a = cons($$, a); }
( ListContinuationBlock { a = cons($$, a); } )*
{ element *raw;
raw = mk_str_from_list(a, false);
raw->key = RAW;
$$ = mk_element(LISTITEM);
$$->children = raw;
}
ListItemTight =
( Bullet | Enumerator )
a:StartList
ListBlock { a = cons($$, a); }
( !BlankLine
ListContinuationBlock { a = cons($$, a); } )*
!ListContinuationBlock
{ element *raw;
raw = mk_str_from_list(a, false);
raw->key = RAW;
$$ = mk_element(LISTITEM);
$$->children = raw;
}
ListBlock = a:StartList
!BlankLine Line { a = cons($$, a); }
( ListBlockLine { a = cons($$, a); } )*
{ $$ = mk_str_from_list(a, false); }
ListContinuationBlock = a:StartList
( < BlankLine* >
{ if (strlen(yytext) == 0)
a = cons(mk_str("\001"), a); /* block separator */
else
a = cons(mk_str(yytext), a); } )
( Indent ListBlock { a = cons($$, a); } )+
{ $$ = mk_str_from_list(a, false); }
Enumerator = NonindentSpace [0-9]+ '.' Spacechar+
OrderedList = &Enumerator (ListTight | ListLoose)
{ $$->key = ORDEREDLIST; }
ListBlockLine = !BlankLine
!( Indent? (Bullet | Enumerator) )
!HorizontalRule
OptionallyIndentedLine
# Parsers for different kinds of block-level HTML content.
# This is repetitive due to constraints of PEG grammar.
HtmlBlockOpenAddress = '<' Spnl ("address" | "ADDRESS") Spnl HtmlAttribute* '>'
HtmlBlockCloseAddress = '<' Spnl '/' ("address" | "ADDRESS") Spnl '>'
HtmlBlockAddress = HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress
HtmlBlockOpenArticle = '<' Spnl ("article" | "ARTICLE") Spnl HtmlAttribute* '>'
HtmlBlockCloseArticle = '<' Spnl '/' ("article" | "ARTICLE") Spnl '>'
HtmlBlockArticle = HtmlBlockOpenArticle (HtmlBlockArticle | !HtmlBlockCloseArticle .)* HtmlBlockCloseArticle
HtmlBlockOpenAside = '<' Spnl ("aside" | "ASIDE") Spnl HtmlAttribute* '>'
HtmlBlockCloseAside = '<' Spnl '/' ("aside" | "ASIDE") Spnl '>'
HtmlBlockAside = HtmlBlockOpenAside (HtmlBlockAside | !HtmlBlockCloseAside .)* HtmlBlockCloseAside
HtmlBlockOpenBlockquote = '<' Spnl ("blockquote" | "BLOCKQUOTE") Spnl HtmlAttribute* '>'
HtmlBlockCloseBlockquote = '<' Spnl '/' ("blockquote" | "BLOCKQUOTE") Spnl '>'
HtmlBlockBlockquote = HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote
HtmlBlockOpenCanvas = '<' Spnl ("canvas" | "CANVAS") Spnl HtmlAttribute* '>'
HtmlBlockCloseCanvas = '<' Spnl '/' ("canvas" | "CANVAS") Spnl '>'
HtmlBlockCanvas = HtmlBlockOpenCanvas (HtmlBlockCanvas | !HtmlBlockCloseCanvas .)* HtmlBlockCloseCanvas
HtmlBlockOpenCenter = '<' Spnl ("center" | "CENTER") Spnl HtmlAttribute* '>'
HtmlBlockCloseCenter = '<' Spnl '/' ("center" | "CENTER") Spnl '>'
HtmlBlockCenter = HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter
HtmlBlockOpenDir = '<' Spnl ("dir" | "DIR") Spnl HtmlAttribute* '>'
HtmlBlockCloseDir = '<' Spnl '/' ("dir" | "DIR") Spnl '>'
HtmlBlockDir = HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir
HtmlBlockOpenDiv = '<' Spnl ("div" | "DIV") Spnl HtmlAttribute* '>'
HtmlBlockCloseDiv = '<' Spnl '/' ("div" | "DIV") Spnl '>'
HtmlBlockDiv = HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv
HtmlBlockOpenDl = '<' Spnl ("dl" | "DL") Spnl HtmlAttribute* '>'
HtmlBlockCloseDl = '<' Spnl '/' ("dl" | "DL") Spnl '>'
HtmlBlockDl = HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl
HtmlBlockOpenFieldset = '<' Spnl ("fieldset" | "FIELDSET") Spnl HtmlAttribute* '>'
HtmlBlockCloseFieldset = '<' Spnl '/' ("fieldset" | "FIELDSET") Spnl '>'
HtmlBlockFieldset = HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset
HtmlBlockOpenFigure = '<' Spnl ("figure" | "FIGURE") Spnl HtmlAttribute* '>'
HtmlBlockCloseFigure = '<' Spnl '/' ("figure" | "FIGURE") Spnl '>'
HtmlBlockFigure = HtmlBlockOpenFigure (HtmlBlockFigure | !HtmlBlockCloseFigure .)* HtmlBlockCloseFigure
HtmlBlockOpenFooter = '<' Spnl ("footer" | "FOOTER") Spnl HtmlAttribute* '>'
HtmlBlockCloseFooter = '<' Spnl '/' ("footer" | "FOOTER") Spnl '>'
HtmlBlockFooter = HtmlBlockOpenFooter (HtmlBlockFooter | !HtmlBlockCloseFooter .)* HtmlBlockCloseFooter
HtmlBlockOpenForm = '<' Spnl ("form" | "FORM") Spnl HtmlAttribute* '>'
HtmlBlockCloseForm = '<' Spnl '/' ("form" | "FORM") Spnl '>'
HtmlBlockForm = HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm
HtmlBlockOpenHeader = '<' Spnl ("header" | "HEADER") Spnl HtmlAttribute* '>'
HtmlBlockCloseHeader = '<' Spnl '/' ("header" | "HEADER") Spnl '>'
HtmlBlockHeader = HtmlBlockOpenHeader (HtmlBlockHeader | !HtmlBlockCloseHeader .)* HtmlBlockCloseHeader
HtmlBlockOpenHgroup = '<' Spnl ("hgroup" | "HGROUP") Spnl HtmlAttribute* '>'
HtmlBlockCloseHgroup = '<' Spnl '/' ("hgroup" | "HGROUP") Spnl '>'
HtmlBlockHgroup = HtmlBlockOpenHgroup (HtmlBlockHgroup | !HtmlBlockCloseHgroup .)* HtmlBlockCloseHgroup
HtmlBlockOpenH1 = '<' Spnl ("h1" | "H1") Spnl HtmlAttribute* '>'
HtmlBlockCloseH1 = '<' Spnl '/' ("h1" | "H1") Spnl '>'
HtmlBlockH1 = HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1
HtmlBlockOpenH2 = '<' Spnl ("h2" | "H2") Spnl HtmlAttribute* '>'
HtmlBlockCloseH2 = '<' Spnl '/' ("h2" | "H2") Spnl '>'
HtmlBlockH2 = HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2
HtmlBlockOpenH3 = '<' Spnl ("h3" | "H3") Spnl HtmlAttribute* '>'
HtmlBlockCloseH3 = '<' Spnl '/' ("h3" | "H3") Spnl '>'
HtmlBlockH3 = HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3
HtmlBlockOpenH4 = '<' Spnl ("h4" | "H4") Spnl HtmlAttribute* '>'
HtmlBlockCloseH4 = '<' Spnl '/' ("h4" | "H4") Spnl '>'
HtmlBlockH4 = HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4
HtmlBlockOpenH5 = '<' Spnl ("h5" | "H5") Spnl HtmlAttribute* '>'
HtmlBlockCloseH5 = '<' Spnl '/' ("h5" | "H5") Spnl '>'
HtmlBlockH5 = HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5
HtmlBlockOpenH6 = '<' Spnl ("h6" | "H6") Spnl HtmlAttribute* '>'
HtmlBlockCloseH6 = '<' Spnl '/' ("h6" | "H6") Spnl '>'
HtmlBlockH6 = HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6
HtmlBlockOpenMenu = '<' Spnl ("menu" | "MENU") Spnl HtmlAttribute* '>'
HtmlBlockCloseMenu = '<' Spnl '/' ("menu" | "MENU") Spnl '>'
HtmlBlockMenu = HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu
HtmlBlockOpenNoframes = '<' Spnl ("noframes" | "NOFRAMES") Spnl HtmlAttribute* '>'
HtmlBlockCloseNoframes = '<' Spnl '/' ("noframes" | "NOFRAMES") Spnl '>'
HtmlBlockNoframes = HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes
HtmlBlockOpenNoscript = '<' Spnl ("noscript" | "NOSCRIPT") Spnl HtmlAttribute* '>'
HtmlBlockCloseNoscript = '<' Spnl '/' ("noscript" | "NOSCRIPT") Spnl '>'
HtmlBlockNoscript = HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript
HtmlBlockOpenOl = '<' Spnl ("ol" | "OL") Spnl HtmlAttribute* '>'
HtmlBlockCloseOl = '<' Spnl '/' ("ol" | "OL") Spnl '>'
HtmlBlockOl = HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl
HtmlBlockOpenP = '<' Spnl ("p" | "P") Spnl HtmlAttribute* '>'
HtmlBlockCloseP = '<' Spnl '/' ("p" | "P") Spnl '>'
HtmlBlockP = HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP
HtmlBlockOpenPre = '<' Spnl ("pre" | "PRE") Spnl HtmlAttribute* '>'
HtmlBlockClosePre = '<' Spnl '/' ("pre" | "PRE") Spnl '>'
HtmlBlockPre = HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre
HtmlBlockOpenProgress = '<' Spnl ("progress" | "PROGRESS") Spnl HtmlAttribute* '>'
HtmlBlockCloseProgress = '<' Spnl '/' ("progress" | "PROGRESS") Spnl '>'
HtmlBlockProgress = HtmlBlockOpenProgress (HtmlBlockProgress | !HtmlBlockCloseProgress .)* HtmlBlockCloseProgress
HtmlBlockOpenSection = '<' Spnl ("section" | "SECTION") Spnl HtmlAttribute* '>'
HtmlBlockCloseSection = '<' Spnl '/' ("section" | "SECTION") Spnl '>'
HtmlBlockSection = HtmlBlockOpenSection (HtmlBlockSection | !HtmlBlockCloseSection .)* HtmlBlockCloseSection
HtmlBlockOpenTable = '<' Spnl ("table" | "TABLE") Spnl HtmlAttribute* '>'
HtmlBlockCloseTable = '<' Spnl '/' ("table" | "TABLE") Spnl '>'
HtmlBlockTable = HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable
HtmlBlockOpenUl = '<' Spnl ("ul" | "UL") Spnl HtmlAttribute* '>'
HtmlBlockCloseUl = '<' Spnl '/' ("ul" | "UL") Spnl '>'
HtmlBlockUl = HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl
HtmlBlockOpenVideo = '<' Spnl ("video" | "VIDEO") Spnl HtmlAttribute* '>'
HtmlBlockCloseVideo = '<' Spnl '/' ("video" | "VIDEO") Spnl '>'
HtmlBlockVideo = HtmlBlockOpenVideo (HtmlBlockVideo | !HtmlBlockCloseVideo .)* HtmlBlockCloseVideo
HtmlBlockOpenDd = '<' Spnl ("dd" | "DD") Spnl HtmlAttribute* '>'
HtmlBlockCloseDd = '<' Spnl '/' ("dd" | "DD") Spnl '>'
HtmlBlockDd = HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd
HtmlBlockOpenDt = '<' Spnl ("dt" | "DT") Spnl HtmlAttribute* '>'
HtmlBlockCloseDt = '<' Spnl '/' ("dt" | "DT") Spnl '>'
HtmlBlockDt = HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt
HtmlBlockOpenFrameset = '<' Spnl ("frameset" | "FRAMESET") Spnl HtmlAttribute* '>'
HtmlBlockCloseFrameset = '<' Spnl '/' ("frameset" | "FRAMESET") Spnl '>'
HtmlBlockFrameset = HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset
HtmlBlockOpenLi = '<' Spnl ("li" | "LI") Spnl HtmlAttribute* '>'
HtmlBlockCloseLi = '<' Spnl '/' ("li" | "LI") Spnl '>'
HtmlBlockLi = HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi
HtmlBlockOpenTbody = '<' Spnl ("tbody" | "TBODY") Spnl HtmlAttribute* '>'
HtmlBlockCloseTbody = '<' Spnl '/' ("tbody" | "TBODY") Spnl '>'
HtmlBlockTbody = HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody
HtmlBlockOpenTd = '<' Spnl ("td" | "TD") Spnl HtmlAttribute* '>'
HtmlBlockCloseTd = '<' Spnl '/' ("td" | "TD") Spnl '>'
HtmlBlockTd = HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd
HtmlBlockOpenTfoot = '<' Spnl ("tfoot" | "TFOOT") Spnl HtmlAttribute* '>'
HtmlBlockCloseTfoot = '<' Spnl '/' ("tfoot" | "TFOOT") Spnl '>'
HtmlBlockTfoot = HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot
HtmlBlockOpenTh = '<' Spnl ("th" | "TH") Spnl HtmlAttribute* '>'
HtmlBlockCloseTh = '<' Spnl '/' ("th" | "TH") Spnl '>'
HtmlBlockTh = HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh
HtmlBlockOpenThead = '<' Spnl ("thead" | "THEAD") Spnl HtmlAttribute* '>'
HtmlBlockCloseThead = '<' Spnl '/' ("thead" | "THEAD") Spnl '>'
HtmlBlockThead = HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead
HtmlBlockOpenTr = '<' Spnl ("tr" | "TR") Spnl HtmlAttribute* '>'
HtmlBlockCloseTr = '<' Spnl '/' ("tr" | "TR") Spnl '>'
HtmlBlockTr = HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr
HtmlBlockOpenScript = '<' Spnl ("script" | "SCRIPT") Spnl HtmlAttribute* '>'
HtmlBlockCloseScript = '<' Spnl '/' ("script" | "SCRIPT") Spnl '>'
HtmlBlockScript = HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript
HtmlBlockInTags = HtmlBlockAddress
| HtmlBlockArticle
| HtmlBlockAside
| HtmlBlockCanvas
| HtmlBlockBlockquote
| HtmlBlockCenter
| HtmlBlockDir
| HtmlBlockDiv
| HtmlBlockDl
| HtmlBlockFieldset
| HtmlBlockFigure
| HtmlBlockFooter
| HtmlBlockForm
| HtmlBlockHeader
| HtmlBlockHgroup
| HtmlBlockH1
| HtmlBlockH2
| HtmlBlockH3
| HtmlBlockH4
| HtmlBlockH5
| HtmlBlockH6
| HtmlBlockMenu
| HtmlBlockNoframes
| HtmlBlockNoscript
| HtmlBlockOl
| HtmlBlockP
| HtmlBlockPre
| HtmlBlockProgress
| HtmlBlockSection
| HtmlBlockTable
| HtmlBlockUl
| HtmlBlockVideo
| HtmlBlockDd
| HtmlBlockDt
| HtmlBlockFrameset
| HtmlBlockLi
| HtmlBlockTbody
| HtmlBlockTd
| HtmlBlockTfoot
| HtmlBlockTh
| HtmlBlockThead
| HtmlBlockTr
| HtmlBlockScript
HtmlBlock = !MarkdownHtmlTagOpen < ( HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing ) >
BlankLine+
{ if (extension(EXT_FILTER_HTML)) {
$$ = mk_list(LIST, NULL);
} else {
$$ = mk_str(yytext);
if ( extension(EXT_PROCESS_HTML)) $$->key = RAW;
else $$->key = HTMLBLOCK;
}
}
MarkdownHtmlBlock = &MarkdownHtmlTagOpen < ( HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing) >
BlankLine+
{ $$ = mk_str(yytext);
$$->key = RAW;
}
HtmlBlockSelfClosing = '<' Spnl HtmlBlockType Spnl HtmlAttribute* '/' Spnl '>'
HtmlBlockType = "address" | "blockquote" | "center" | "dir" | "div" | "dl" | "fieldset" | "form" | "h1" | "h2" | "h3" |
"h4" | "h5" | "h6" | "hr" | "isindex" | "menu" | "noframes" | "noscript" | "ol" | "p" | "pre" | "table" |
"ul" | "dd" | "dt" | "frameset" | "li" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "script" |
"ADDRESS" | "BLOCKQUOTE" | "CENTER" | "DIR" | "DIV" | "DL" | "FIELDSET" | "FORM" | "H1" | "H2" | "H3" |
"H4" | "H5" | "H6" | "HR" | "ISINDEX" | "MENU" | "NOFRAMES" | "NOSCRIPT" | "OL" | "P" | "PRE" | "TABLE" |
"UL" | "DD" | "DT" | "FRAMESET" | "LI" | "TBODY" | "TD" | "TFOOT" | "TH" | "THEAD" | "TR" | "SCRIPT"
StyleOpen = '<' Spnl ("style" | "STYLE") Spnl HtmlAttribute* '>'
StyleClose = '<' Spnl '/' ("style" | "STYLE") Spnl '>'
InStyleTags = StyleOpen (!StyleClose .)* StyleClose
StyleBlock = < InStyleTags >
BlankLine*
{ if (extension(EXT_FILTER_STYLES)) {
$$ = mk_list(LIST, NULL);
} else {
$$ = mk_str(yytext);
$$->key = HTMLBLOCK;
}
}
Inlines = a:StartList ( !Endline Inline { a = cons($$, a); }
| c:Endline &Inline { a = cons(c, a); } )+ Endline?
{ $$ = mk_list(LIST, a); }
Inline = &{ check_timeout() }
Str
| &{ !extension(EXT_COMPATIBILITY) } MathSpan
| Endline
| UlOrStarLine
| Space
| Strong
| Emph
| &{ !extension(EXT_COMPATIBILITY) } CitationReference
| Image
| Link
| NoteReference
# | InlineNote # Not used in Markdown/MultiMarkdown
| Code
| MarkdownHtmlTagOpen
| RawHtml
| Entity
| EscapedChar
| Smart
| Symbol
Space = Spacechar+
{ $$ = mk_str(" ");
$$->key = SPACE; }
Str = a:StartList < NormalChar+ > { a = cons(mk_str(yytext), a); }
( StrChunk { a = cons($$, a); } )*
{ if (a->next == NULL) { $$ = a; } else { $$ = mk_list(LIST, a); } }
StrChunk = < (NormalChar | '_'+ &Alphanumeric)+ > { $$ = mk_str(yytext); } |
AposChunk
AposChunk = &{ extension(EXT_SMART) } '\'' &Alphanumeric
{ $$ = mk_element(APOSTROPHE); }
EscapedChar = '\\' !Newline < [-\\`|*_{}[\]()#+.!><] >
{ $$ = mk_str(yytext); }
Entity = ( HexEntity | DecEntity | CharEntity )
{ $$ = mk_str(yytext); $$->key = HTML; }
Endline = LineBreak | TerminalEndline | NormalEndline
NormalEndline = Sp Newline !BlankLine !'>' !AtxStart
!(Line ('='+ | '-'+) Newline)
{ $$ = mk_str("\n");
$$->key = SPACE; }
TerminalEndline = Sp Newline Eof
{ $$ = NULL; }
LineBreak = " " NormalEndline
{ $$ = mk_element(LINEBREAK); }
Symbol = < SpecialChar >
{ $$ = mk_str(yytext); }
# This keeps the parser from getting bogged down on long strings of '*' or '_',
# or strings of '*' or '_' with space on each side:
UlOrStarLine = (UlLine | StarLine) { $$ = mk_str(yytext); }
StarLine = < "****" '*'* > | < Spacechar '*'+ &Spacechar >
UlLine = < "____" '_'* > | < Spacechar '_'+ &Spacechar >
Emph = EmphStar | EmphUl
Whitespace = Spacechar | Newline
EmphStar = '*' !Whitespace
a:StartList
( !'*' b:Inline { a = cons(b, a); }
| b:StrongStar { a = cons(b, a); }
)+
'*'
{ $$ = mk_list(EMPH, a); }
EmphUl = '_' !Whitespace
a:StartList
( !'_' b:Inline { a = cons(b, a); }
| b:StrongUl { a = cons(b, a); }
)+
'_'
{ $$ = mk_list(EMPH, a); }
Strong = StrongStar | StrongUl
StrongStar = "**" !Whitespace
a:StartList
( !"**" b:Inline { a = cons(b, a); })+
"**"
{ $$ = mk_list(STRONG, a); }
StrongUl = "__" !Whitespace
a:StartList
( !"__" b:Inline { a = cons(b, a); })+
"__"
{ $$ = mk_list(STRONG, a); }
ImageBlock = Image Sp Newline BlankLine+
{ if ($$->key == IMAGE) $$->key = IMAGEBLOCK; }
Image = '!' ( ExplicitLink | ReferenceLink )
{ if ($$->key == LINK) {
$$->key = IMAGE;
} else {
element *result;
result = $$;
$$->children = cons(mk_str("!"), result->children);
} }
Link = ExplicitLink | ReferenceLink | AutoLink
ReferenceLink = ReferenceLinkDouble | ReferenceLinkSingle
ReferenceLinkDouble = a:Label < Spnl > !"[]" b:Label
{ link match;
if (find_reference(&match, b->children)) {
$$ = mk_link(a->children, match.url, match.title, match.attr, match.identifier);
free(a);
free_element_list(b);
} else if ( !extension(EXT_COMPATIBILITY) &&
find_label(&match, b->children)) {
GString *text = g_string_new("");
print_raw_element_list(text, b->children);
char *lab = label_from_string(text->str,0);
GString *label = g_string_new(lab);
g_string_prepend(label,"#");
$$ = mk_link(a->children, label->str, "", NULL, lab);
free(lab);
g_string_free(text, TRUE);
g_string_free(label, TRUE);
free(a);
free_element_list(b);
} else {
element *result;
result = mk_element(LIST);
result->children = cons(mk_str("["), cons(a, cons(mk_str("]"), cons(mk_str("["), cons(b, mk_str("]"))))));
$$ = result;
}
}
ReferenceLinkSingle = a:Label < (Spnl "[]")? >
{ link match;
if (find_reference(&match, a->children)) {
$$ = mk_link(a->children, match.url, match.title, match.attr, match.identifier);
free(a);
} else if ( !extension(EXT_COMPATIBILITY) &&
find_label(&match, a->children)) {
GString *text = g_string_new("");
print_raw_element_list(text, a->children);
char *lab = label_from_string(text->str,0);
GString *label = g_string_new(lab);
g_string_prepend(label,"#");
$$ = mk_link(a->children, label->str, "", NULL, lab);
g_string_free(text, TRUE);
g_string_free(label, TRUE);
free(lab);
free(a);
} else {
element *result;
result = mk_element(LIST);
result->children = cons(mk_str("["), cons(a, cons(mk_str("]"), mk_str(yytext))));
$$ = result;
}
}
ExplicitLink = l:Label '(' Sp s:Source Spnl t:Title Sp ')'
{
$$ = mk_link(l->children, s->contents.str, t->contents.str, NULL, "");
free_element(s);
free_element(t);
free(l);
}
Source = ( '<' < SourceContents > '>' | < SourceContents > )
{ $$ = mk_str(yytext); }
SourceContents = ( ( !'(' !')' !'>' Nonspacechar )+ | '(' SourceContents ')')*
Title = ( TitleSingle | TitleDouble | < "" > )
{ $$ = mk_str(yytext); }
TitleSingle = '\'' < ( !( '\'' Sp ( ')' | Newline ) ) . )* > '\''
TitleDouble = '"' < ( !( '"' Sp ( ')' | Newline ) ) . )* > '"'
AutoLink = AutoLinkUrl | AutoLinkEmail
AutoLinkUrl = '<' < [A-Za-z]+ "://" ( !Newline !'>' . )+ > '>'
{ $$ = mk_link(mk_str(yytext), yytext, "", NULL, ""); }
AutoLinkEmail = '<' ( "mailto:" )? < [-A-Za-z0-9+_./!%~$]+ '@' ( !Newline !'>' . )+ > '>'
{ char *mailto = malloc(strlen(yytext) + 8);
sprintf(mailto, "mailto:%s", yytext);
$$ = mk_link(mk_str(yytext), mailto, "", NULL, "");
free(mailto);
}
Reference = a:StartList NonindentSpace !"[]" l:Label ':' Spnl s:RefSrc
t:RefTitle
( &{ !extension(EXT_COMPATIBILITY) }
(Attributes { a = cons($$,a);})? )?
BlankLine+
{
char *label;
GString *text = g_string_new("");
print_raw_element_list(text, l->children);
label = label_from_string(text->str,0);
if (a == NULL) {
$$ = mk_link(l->children, s->contents.str,
t->contents.str, a, label);
} else {
$$ = mk_link(l->children, s->contents.str,
t->contents.str, a->children, label);
}
free_element(s);
free_element(t);
free(l);
free(label);
g_string_free(text, TRUE);
$$->key = REFERENCE;
}
Attributes = a:StartList (Attribute { a =cons($$,a);})+
{ $$ = mk_list(LIST,a); }
Attribute = Spnl a:AttrKey '=' b:AttrValue
{
$$ = a;
$$->children = b;
}
AttrKey = < AlphanumericAscii+ >
{
char *lab;
lab = label_from_string(yytext,0);
$$ = mk_str(lab);
$$->key = ATTRKEY;
free(lab);
}
AttrValue = (QuotedValue | UnQuotedValue)
{ $$ = mk_str(yytext);
$$->key = ATTRVALUE;
}
QuotedValue = '"' < (!'"' .)* > '"'
UnQuotedValue = < (AlphanumericAscii | '.')+ >
Label = '[' !'[' ( !'^' !'#' &{ extension(EXT_NOTES) } | &. &{ !extension(EXT_NOTES) } )
a:StartList
( !']' Inline { a = cons($$, a); } )*
']'
{ $$ = mk_list(LIST, a); }
RefSrc = < Nonspacechar+ >
{ $$ = mk_str(yytext);
$$->key = HTML; }
RefTitle = ( RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle )
{ $$ = mk_str(yytext);
$$->key = RAW;}
EmptyTitle = < "" >
RefTitleSingle = Spnl '\'' < ( !( '\'' Sp Newline | Newline |
&{ !extension(EXT_COMPATIBILITY) } '\'' Sp AlphanumericAscii+ '=' ) . )* > '\''
RefTitleDouble = Spnl '"' < ( !('"' Sp Newline | Newline |
&{ !extension(EXT_COMPATIBILITY) } '"' Sp AlphanumericAscii+ '=' ) . )* > '"'
RefTitleParens = Spnl '(' < ( !(')' Sp Newline | Newline |
&{ !extension(EXT_COMPATIBILITY) } ')' Sp AlphanumericAscii+ '=' ) . )* > ')'
References = a:StartList
( b:Reference { a = cons(b, a); } | SkipBlock )*
{ references = reverse(a); }
Ticks1 = "`" !'`'
Ticks2 = "``" !'`'
Ticks3 = "```" !'`'
Ticks4 = "````" !'`'
Ticks5 = "`````" !'`'
Code = ( Ticks1 Sp < ( ( !'`' Nonspacechar )+ | !Ticks1 '`'+ | !( Sp Ticks1 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks1
| Ticks2 Sp < ( ( !'`' Nonspacechar )+ | !Ticks2 '`'+ | !( Sp Ticks2 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks2
| Ticks3 Sp < ( ( !'`' Nonspacechar )+ | !Ticks3 '`'+ | !( Sp Ticks3 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks3
| Ticks4 Sp < ( ( !'`' Nonspacechar )+ | !Ticks4 '`'+ | !( Sp Ticks4 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks4
| Ticks5 Sp < ( ( !'`' Nonspacechar )+ | !Ticks5 '`'+ | !( Sp Ticks5 ) ( Spacechar | Newline !BlankLine ) )+ > Sp Ticks5
)
{ $$ = mk_str(yytext); $$->key = CODE; }
RawHtml = < (HtmlComment | HtmlBlockScript | HtmlTag) >
{ if (extension(EXT_FILTER_HTML)) {
$$ = mk_list(LIST, NULL);
} else {
$$ = mk_str(yytext);
$$->key = HTML;
}
}
BlankLine = Sp Newline
Quoted = '"' (!'"' .)* '"' | '\'' (!'\'' .)* '\''
HtmlAttribute = (AlphanumericAscii | '-')+ Spnl ('=' Spnl (Quoted | (!'>' Nonspacechar)+))? Spnl
HtmlComment = "<!--" (!"-->" .)* "-->"
HtmlTag = '<' Spnl '/'? AlphanumericAscii+ Spnl HtmlAttribute* '/'? Spnl '>'
Eof = !.
Spacechar = ' ' | '\t'
Nonspacechar = !Spacechar !Newline .
Newline = '\n' | '\r' '\n'?
Sp = Spacechar*
Spnl = Sp (Newline Sp)?
SpecialChar = '*' | '_' | '`' | '&' | '[' | ']' | '(' | ')' | '<' | '!' | '#' | '\\' | '\'' | '"' | ExtendedSpecialChar
NormalChar = !( SpecialChar | Spacechar | Newline ) .
Alphanumeric = [0-9A-Za-z] | '\200' | '\201' | '\202' | '\203' | '\204' | '\205' | '\206' | '\207' | '\210' | '\211' | '\212' | '\213' | '\214' | '\215' | '\216' | '\217' | '\220' | '\221' | '\222' | '\223' | '\224' | '\225' | '\226' | '\227' | '\230' | '\231' | '\232' | '\233' | '\234' | '\235' | '\236' | '\237' | '\240' | '\241' | '\242' | '\243' | '\244' | '\245' | '\246' | '\247' | '\250' | '\251' | '\252' | '\253' | '\254' | '\255' | '\256' | '\257' | '\260' | '\261' | '\262' | '\263' | '\264' | '\265' | '\266' | '\267' | '\270' | '\271' | '\272' | '\273' | '\274' | '\275' | '\276' | '\277' | '\300' | '\301' | '\302' | '\303' | '\304' | '\305' | '\306' | '\307' | '\310' | '\311' | '\312' | '\313' | '\314' | '\315' | '\316' | '\317' | '\320' | '\321' | '\322' | '\323' | '\324' | '\325' | '\326' | '\327' | '\330' | '\331' | '\332' | '\333' | '\334' | '\335' | '\336' | '\337' | '\340' | '\341' | '\342' | '\343' | '\344' | '\345' | '\346' | '\347' | '\350' | '\351' | '\352' | '\353' | '\354' | '\355' | '\356' | '\357' | '\360' | '\361' | '\362' | '\363' | '\364' | '\365' | '\366' | '\367' | '\370' | '\371' | '\372' | '\373' | '\374' | '\375' | '\376' | '\377'
AlphanumericAscii = [A-Za-z0-9]
Digit = [0-9]
BOM = "\357\273\277"
HexEntity = < '&' '#' [Xx] [0-9a-fA-F]+ ';' >
DecEntity = < '&' '#' [0-9]+ > ';' >
CharEntity = < '&' [A-Za-z0-9]+ ';' >
NonindentSpace = " " | " " | " " | ""
Indent = "\t" | " "
IndentedLine = Indent Line
OptionallyIndentedLine = Indent? Line
# StartList starts a list data structure that can be added to with cons:
StartList = &.
{ $$ = NULL; }
Line = RawLine
{ $$ = mk_str(yytext); }
RawLine = ( < (!'\r' !'\n' .)* Newline > | < .+ > Eof )
SkipBlock = HtmlBlock
| ( !'#' !SetextBottom1 !SetextBottom2 !BlankLine RawLine )+ BlankLine*
| BlankLine+
| RawLine
# Syntax extensions
ExtendedSpecialChar = &{ extension(EXT_SMART) } ('.' | '-' | '\'' | '"')
| &{ extension(EXT_NOTES) } ( '^' )
Smart = &{ extension(EXT_SMART) }
( Ellipsis | Dash | SingleQuoted | DoubleQuoted | Apostrophe )
Apostrophe = '\''
{ $$ = mk_element(APOSTROPHE); }
Ellipsis = ("..." | ". . .")
{ $$ = mk_element(ELLIPSIS); }
Dash = EmDash | EnDash
EnDash = < ( "--" | '-' &Digit) >
{ $$ = mk_element(ENDASH);
$$->contents.str = strdup(yytext);
}
EmDash = ( <"---"> )
{ $$ = mk_element(EMDASH);
$$->contents.str = strdup(yytext);
}
SingleQuoteStart = '\'' !(Spacechar | Newline)
SingleQuoteEnd = '\'' !Alphanumeric
SingleQuoted = SingleQuoteStart
a:StartList
( !SingleQuoteEnd b:Inline { a = cons(b, a); } )+
SingleQuoteEnd
{ $$ = mk_list(SINGLEQUOTED, a); }
DoubleQuoteStart = '"'
DoubleQuoteEnd = '"'
DoubleQuoted = DoubleQuoteStart
a:StartList
( !DoubleQuoteEnd b:Inline { a = cons(b, a); } )+
DoubleQuoteEnd
{ $$ = mk_list(DOUBLEQUOTED, a); }
NoteReference = &{ extension(EXT_NOTES) }
ref:RawNoteReference
{ element *match;
if (find_note(&match, ref->contents.str)) {
$$ = mk_element(NOTE);
assert(match->children != NULL);
$$->children = match->children;
$$->contents.str = 0;
} else {
char *s;
s = malloc(strlen(ref->contents.str) + 4);
sprintf(s, "[^%s]", ref->contents.str);
$$ = mk_str(s);
free(s);
}
}
RawNoteReference = ( "[^" | "[#" ) < ( !Newline !']' . )+ > ']'
{ $$ = mk_str(yytext); }
Glossary = &{ extension(EXT_NOTES) }
a:StartList
NonindentSpace ref:RawNoteReference ':' Sp
"glossary:" Sp (GlossaryTerm { a = cons($$, a); })
(GlossarySortKey { a = cons($$, a); })?
Newline
( RawNoteBlock { a = cons($$, a); } )
( &Indent RawNoteBlock { a = cons($$, a); } )*
{ $$ = mk_list(GLOSSARY, a);
$$->contents.str = strdup(ref->contents.str);
}
GlossaryTerm = < (!Newline !'(' .)+ >
{
$$ = mk_list(LIST, NULL);
$$->contents.str = 0;
$$->children = mk_str(yytext);
$$->key = GLOSSARYTERM;
}
GlossarySortKey = '(' < (!')' !Newline .)* > ')'
{ $$ = mk_str(yytext);
$$->key = GLOSSARYSORTKEY; }
Note = &{ extension(EXT_NOTES) }
NonindentSpace ref:RawNoteReference ':' Sp
a:StartList
( RawNoteBlock { a = cons($$, a); } )
( &Indent RawNoteBlock { a = cons($$, a); } )*
{ element *label;
label = mk_str(ref->contents.str);
label->key = NOTELABEL;
a = cons(label,a);
$$ = mk_list(NOTE, a);
$$->contents.str = strdup(ref->contents.str);
}
InlineNote = &{ extension(EXT_NOTES) }
"^["
a:StartList
( !']' Inline { a = cons($$, a); } )+
']'
{ $$ = mk_list(NOTE, a);
$$->contents.str = 0; }
Notes = a:StartList
( (b:Glossary | b:Note) { a = cons(b, a); } | SkipBlock )*
{ notes = reverse(a); }
RawNoteBlock = a:StartList
( !BlankLine OptionallyIndentedLine { a = cons($$, a); } )+
( < BlankLine* > { a = cons(mk_str(yytext), a); } )
{ $$ = mk_str_from_list(a, true);
$$->key = RAW;
}
# MultiMarkdown Citations
CitationReference = CitationReferenceDouble | CitationReferenceSingle
CitationReferenceDouble = !"[]" b:Label < Spnl > !"[]" ref:RawCitationReference
{ element *match;
if (find_note(&match, ref->contents.str)) {
/* This citation is specified within the document */
$$ = mk_element(CITATION);
assert(match->children != NULL);
b->next = match->children;
b->key = LOCATOR;
$$->children = b;
$$->contents.str = strdup(ref->contents.str);
} else {
/* Citation not specified - likely bibtex citation */
/* TODO: fix this - need to print label as well */
char *s;
s = malloc(strlen(ref->contents.str) + 4);
sprintf(s, "[#%s]", ref->contents.str);
$$ = mk_str(s);
$$->key = CITATION;
b->key = LOCATOR;
$$->children = b;
free(s);
}
GString *label = g_string_new("");
char *lab;
print_raw_element_list(label, b->children);
lab = label_from_string(label->str,0);
if (strcmp(lab,"notcited") == 0 ) {
$$->key = NOCITATION;
}
g_string_free(label, true);
free(lab);
}
CitationReferenceSingle = (( "[]" Spnl ref:RawCitationReference )
| ( ref:RawCitationReference < (Spnl "[]")? > ))
{ element *match;
if (find_note(&match, ref->contents.str)) {
$$ = mk_element(CITATION);
assert(match->children != NULL);
$$->children = match->children;
$$->contents.str = strdup(ref->contents.str);
} else {
char *s;
s = malloc(strlen(ref->contents.str) + 4);
sprintf(s, "[#%s]", ref->contents.str);
$$ = mk_str(s);
$$->key = CITATION;
free(s);
}
}
RawCitationReference = "[#" < ( !Newline !']' . )+ > ']'
{ $$ = mk_str(yytext); }
AutoLabels = ( &{ !extension(EXT_COMPATIBILITY) && !extension(EXT_NO_LABELS)}
a:StartList ( b:Heading
{
GString *label = g_string_new("");
char *lab;
print_raw_element_list(label, b->children);
if (b->children->key == AUTOLABEL) {
lab = label_from_string(b->children->contents.str,0);
} else {
lab = label_from_string(label->str,0);
}
a = cons(mk_str(lab), a);
free(lab);
g_string_free(label,true);
/* TODO: this causes segfault when trying to use a footnote in the header */
/* I would like to fix it at some point */
/* free_element_list(b); */
} | c:TableCaption {
GString *label = g_string_new("");
char *lab;
if (c->children->key == TABLELABEL) {
print_raw_element_list(label, c->children->children);
} else {
print_raw_element_list(label, c->children);
}
lab = label_from_string(label->str,0);
a = cons(mk_str(lab), a);
free(lab);
g_string_free(label,true);
free_element_list(c);} TableBody
| (TableBody|SeparatorLine)+ c:TableCaption {
GString *label = g_string_new("");
char *lab;
if (c->children->key == TABLELABEL) {
print_raw_element_list(label, c->children->children);
} else {
print_raw_element_list(label, c->children);
}
lab = label_from_string(label->str,0);
a = cons(mk_str(lab), a);
free(lab);
g_string_free(label,true);
free_element_list(c);}
| SkipBlock )*
{ labels = a; })
DefinitionList = a:StartList &(TermLine+ Newline? NonindentSpace ':')
(
(Term { a = cons($$, a); } )+
BlankLine?
(Definition { a = cons($$, a);})+
BlankLine*
)+
{ $$ = mk_list(LIST, a);
$$->key = DEFLIST;
}
TermLine = !':' !BlankLine (!Newline .)* Newline
Term = a:StartList !BlankLine !':'
(!Newline !Endline Inline {a = cons($$, a);} )+ Newline
{
$$ = mk_list(TERM,a);
}
Definition = (a:StartList b:StartList
(BlankLine { b = cons(mk_str("\n"),b); } )?
( NonindentSpace ':' Sp RawLine { a = cons(mk_str(yytext), a);})
( !':' !BlankLine RawLine { a = cons(mk_str(yytext), a);})*
( BlankLine {a = cons(mk_str("\n"),a);}
(IndentedLine { a = cons(mk_str(yytext),a);})+
{ a = cons(mk_str("\n"),a);}
)*
)
{ if (b != NULL) { a = cons(b,a);}
element *raw = mk_str_from_list(a, false);
raw->key = RAW;
$$ = mk_list(DEFINITION,raw);
}
Table = a:StartList b:StartList (TableCaption { b = cons($$, b);})?
TableBody { $$->key = TABLEHEAD; a = cons($$, a); }
(SeparatorLine { append_list($$,a); } )
(TableBody { a = cons($$, a);} )
(BlankLine !TableCaption TableBody { a = cons($$, a); }
&(TableCaption | BlankLine) )*
( (TableCaption { b = cons($$, b);} &BlankLine) | &BlankLine)
# Requires blank line to end table "block"
{
if (b != NULL) { append_list(b,a); };
$$ = mk_list(TABLE, a);
}
TableBody = a:StartList (TableRow {a = cons($$, a);})+
{ $$ = mk_list(TABLEBODY, a);}
TableRow = a:StartList
(!SeparatorLine &(TableLine)
CellDivider?
(TableCell { a = cons($$, a); })+ ) Sp Newline
{ $$ = mk_list(TABLEROW, a); }
TableLine = (!Newline !CellDivider .)* CellDivider
TableCell = ExtendedCell | EmptyCell | FullCell
ExtendedCell = (EmptyCell | FullCell) <CellDivider+>
{
element *span;
span = mk_str(yytext);
span->key = CELLSPAN;
span->next = $$->children;
$$->children = span;
}
CellStr = < (!CellDivider NormalChar) (!CellDivider NormalChar | '_'+ &Alphanumeric)* >
{ $$ = mk_str(yytext); }
FullCell = Sp a:StartList ((!CellDivider CellStr | !Newline !Endline !CellDivider !Str !(Sp &CellDivider) Inline ) { a = cons($$,a)})+
Sp ( CellDivider )?
{ $$ = mk_list(TABLECELL,a); }
EmptyCell = Sp CellDivider
{ $$ = mk_element(TABLECELL);}
SeparatorLine = a:StartList
&(TableLine)
CellDivider?
( AlignmentCell { a = cons($$, a);})+ Sp Newline
{
$$ = mk_str_from_list(a,false);
$$->key = TABLESEPARATOR;
}
AlignmentCell = Sp (!CellDivider ( LeftAlignWrap | CenterAlignWrap | RightAlignWrap | LeftAlign | CenterAlign | RightAlign))
Sp ( CellDivider )?
LeftAlignWrap = ':'? '-'+ '+' &(!'-' !':')
{ $$ = mk_str("L");}
LeftAlign = ':'? '-'+ &(!'-' !':')
{ $$ = mk_str("l");}
CenterAlignWrap = ':' '-'* '+' ':' &(!'-' !':')
{ $$ = mk_str("C");}
CenterAlign = ':' '-'* ':' &(!'-' !':')
{ $$ = mk_str("c");}
RightAlignWrap = '-'+ ':' '+' &(!'-' !':')
{ $$ = mk_str("R");}
RightAlign = '-'+ ':' &(!'-' !':')
{ $$ = mk_str("r");}
CellDivider = '|'
TableCaption = b:StartList a:Label
( c:Label { b = c; b->key = TABLELABEL;})? Sp Newline
{
$$ = a;
$$->key = TABLECAPTION;
if ( (b != NULL) && (b->key == TABLELABEL) ) {
b->next = $$->children;
$$->children = b;
}
}
AutoLabel = '[' < (!Newline !'^' !'#' . )( !Newline !']' . )+ > ']' &(!(Sp? ('(' | '[')))
{
char *label = label_from_string(yytext,0);
$$ = mk_str(label);
$$->key = AUTOLABEL;
free(label);
}
MathSpan = '\\' < (
('\\[' (!'\\\\]' .)* '\\\\]') |
('\\(' (!'\\\\)' .)* '\\\\)') ) >
{
/* Basically, these delimiters indicate math in LaTeX syntax, and the
delimiters are compatible with MathJax and LaTeX
ASCIIMathML is *not* supported */
$$ = mk_str(yytext);
$$->key = MATHSPAN;
}
DocForOPML = BOM? a:StartList
( &{ !extension(EXT_COMPATIBILITY) }
&( MetaDataKey Sp ':' Sp (!Newline)) MetaData
{ a = cons($$, a); })?
( OPMLBlock { a = cons($$, a); } )*
{ parse_result = reverse(a);
}
OPMLBlock = BlankLine*
( OPMLHeadingSection
| OPMLPlain )
OPMLHeadingSection = a:StartList OPMLHeading { a = cons($$, a); }
(OPMLSectionBlock {a = cons($$, a); })*
{ $$ = mk_list(HEADINGSECTION, a);}
OPMLHeading = OPMLAtxHeading | OPMLSetextHeading
OPMLAtxHeading = &(Heading) s:AtxStart Sp?
< (!Newline !(Sp? '#'* Sp Newline) .)* >
(Sp? '#'+)? Sp? Newline
{
$$ = mk_str(yytext);
$$->key = s->key;
free(s);
}
OPMLSetextHeading = OPMLSetextHeading1 | OPMLSetextHeading2
OPMLSetextHeading1 = < (!'\r' !'\n' .)* > Newline SetextBottom1
{
$$ = mk_str(yytext);
$$->key = H1;
}
OPMLSetextHeading2 = < (!'\r' !'\n' .)* > Newline SetextBottom2
{
$$ = mk_str(yytext);
$$->key = H2;
}
OPMLSectionBlock =
BlankLine*
!OPMLHeading
OPMLPlain
OPMLPlain = a:StartList (!BlankLine !Heading Line { a = cons($$,a); })+
{ $$ = mk_list(PLAIN, a); }
MarkdownHtmlAttribute = ("markdown" | "MARKDOWN")
Spnl '=' Spnl ('"' Spnl)? "1" (Spnl '"')? Spnl
MarkdownHtmlTagOpen = a:StartList '<' {a = cons(mk_str("<"),a);}
Spnl <HtmlBlockType> {a = cons(mk_str(yytext),a);} Spnl
(!MarkdownHtmlAttribute
<HtmlAttribute> {a = cons(mk_str(" "),a);
a = cons(mk_str(yytext),a);})*
MarkdownHtmlAttribute
(<HtmlAttribute> {a = cons(mk_str(" "),a);
a = cons(mk_str(yytext),a);})*
'>' { a = cons(mk_str(">"),a);}
{
$$ = mk_str_from_list(a,false);
$$->key = HTML;
}
%%
Jump to Line
Something went wrong with that request. Please try again.