%% name = ArtiMark::Parser # literals eof = !. space = ' ' | '\t' eof_comment = lh space* "#" (!eof .)* comment = lh space* "#" (!nl .)* nl empty_line* - = ( space | comment )* empty_line = lh - nl nl = /\r?\n/ lh = /^/ le = nl | eof word = < /[\w0-9]/ ( '-' | /[\w0-9]/ )* > { text } num = < [0-9]+ > { text.to_i } #common syntax classname = '.' word:classname { classname } classnames = (classname)*:classnames { classnames } idname = '#' word:idname { idname } idnames = (idname)*:idnames { idnames } commandname = word:name idnames?:idnames classnames?:classes { {:name => name, :ids => idnames, :classes => classes} } parameter = < ( /[^,)]/* | '"' /[^"]/* '"' | "'" /[^']/* "'" ) > { text } parameters = < parameter (',' parameter)* > { text } command = commandname:cn ('(' - parameters:arg - ')')? { arg ||= ''; cn.merge({ :args => arg.split(',') }) } # paragraph implicit_paragraph = < (!paragraph_delimiter - documentline:p -) > { create_item(:paragraph, nil, p, raw: text) } paragraph = explicit_paragraph | implicit_paragraph # paragraph_group paragraph_group = < paragraph+:p empty_line* > { create_item(:paragraph_group, nil, p, raw: text) } # explicit block blockhead = lh - command:command - '{' - nl empty_line* { command } blockend = lh - '}' - le empty_line* blockbody = (!blockend block)+:body { body } explicit_block = < blockhead:head - blockbody:body - blockend > { create_item(:block, head, body, raw: text) } # inline command inline = img_inline | common_inline common_inline = < '[' command:c '{' documentcontent_except('}'):content '}' ']' > { create_item(:inline, c, content, raw: text) } img_command = command:c &{ c[:name] == 'img' && c[:args].size == 2} img_inline = < '[' img_command:c ']' > { create_item(:inline, c, nil, raw: text) } # special line commands # explicit paragraph explicit_paragraph_command = command:c &{ c[:name] == 'p' } explicit_paragraph = < lh - explicit_paragraph_command:c ':' documentcontent?:content le empty_line*> { create_item(:paragraph, c, content, raw:text) } # unordered list unordered_list = < unordered_item+:items > { create_item(:ul, nil, items, raw: text) } unordered_item = < lh '*:' documentcontent:content le > { create_item(:li, nil, content, raw: text) } # ordered list ordered_list = < ordered_item+:items > { create_item(:ol, nil, items, raw: text) } ordered_item = < lh num ':' documentcontent:content le > { create_item(:li, nil, content, raw: text) } # definition list definition_list = < definition_item+:items > { create_item(:dl, nil, items, raw: text) } definition_item = < lh ';:' - documentcontent_except(':'):term ':' - documentcontent:definition le > { create_item(:dtdd, {:args => [term, definition]}, nil, raw: text) } items_list = unordered_list | ordered_list | definition_list # generic line command line_command = < lh - !explicit_paragraph_command command:c ':' documentcontent?:content - le empty_line* > { create_item(:line_command, c, content, raw: text) } # blocks line_block = items_list | line_command block = (line_block | explicit_block | paragraph_group):block empty_line* {block} block_delimiter = blockhead | blockend paragraph_delimiter = block_delimiter | line_block #header stylesheets = < lh - 'stylesheets:' !le charstring:s nl > { create_item(:stylesheets, {:stylesheets => s.split(',').map(&:strip)}, nil, raw:text) } title = < lh - 'title:' !le charstring:t nl > { create_item(:title, {:title => t }, nil, raw:text) } lang = < lh - 'lang:' !le charstring:l nl > { create_item(:lang, {:lang => l }, nil, raw:text) } header = (stylesheets | title | lang) empty_line* # texts char = < /[[:print:]]/ > { text } charstring = < char* > { text } char_except(e) = char:c &{ c != e } charstring_except(e) = < char_except(e)* > { text } documentcontent_except(e) = (inline | !inline char_except(e))+:content ~parse_text(content) documentcontent = (inline | !inline char)+:content ~parse_text(content) documentline = lh documentcontent:content le { content } #root root = header*:headers - block*:blocks - eof_comment? eof { headers.concat blocks.select{ |x| !x.nil?} }