Class: Coradoc::Markdown::Parser::BlockParser
- Inherits:
-
Parslet::Parser
- Object
- Parslet::Parser
- Coradoc::Markdown::Parser::BlockParser
- Defined in:
- lib/coradoc/markdown/parser/block_parser.rb
Class Method Summary collapse
- .parse(filename) ⇒ Object
-
.parse_with_processing(content) ⇒ Object
Parse with AST post-processing (escape sequences, etc.).
Instance Method Summary collapse
-
#block_quote_cont ⇒ Object
This implements laziness, which is context-sensitive: “only applies to lines that would have been continuations of paragraphs had they been prepended with block quote markers” means we actually must be inside of a continueable paragraph.
- #code_fence_info ⇒ Object
- #consume_fenced_indent ⇒ Object
-
#continuation ⇒ Object
Block nesting is the tricky part, but Parslet’s ‘dynamic` and `scope` make it possible to be aware of what blocks we’re already in, and implement a check for whether we’re still inside of those blocks on the beginning of every line.
-
#debug(msg) ⇒ Object
NOTE: Debug method for parser development.
- #open_block(kind, cont_rule) ⇒ Object
- #thematic_break_char(c) ⇒ Object
Class Method Details
.parse(filename) ⇒ Object
727 728 729 730 731 732 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 727 def self.parse(filename) content = File.read(filename) new.parse(content) rescue Parslet::ParseFailed => e puts e.parse_failure_cause.ascii_tree end |
.parse_with_processing(content) ⇒ Object
Parse with AST post-processing (escape sequences, etc.)
735 736 737 738 739 740 741 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 735 def self.parse_with_processing(content) ast = new.parse(content) AstProcessor.process(ast) rescue Parslet::ParseFailed => e puts e.parse_failure_cause.ascii_tree nil end |
Instance Method Details
#block_quote_cont ⇒ Object
This implements laziness, which is context-sensitive: “only applies to lines that would have been continuations of paragraphs had they been prepended with block quote markers” means we actually must be inside of a continueable paragraph.
Cannot be a ‘rule` as usual with `dynamic`.
189 190 191 192 193 194 195 196 197 198 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 189 def block_quote_cont dynamic do |_src, ctx| # puts "BQDYN in #{ctx.captures[:block]}" block_quote_marker | if ctx.captures[:block] == :paragraph paragraph_interrupt.absent? >> paragraph_continued_line.present? else any.absent? >> any.present? # never match end end end |
#code_fence_info ⇒ Object
129 130 131 132 133 134 135 136 137 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 129 def code_fence_info # NOTE: Uses dynamic block for context-dependent fence character detection # This handles both backtick (`) and tilde (~) fenced code blocks dynamic do |_src, ctx| char = line_char char = str('`').absent? >> char if ctx.captures[:fence].to_s.chr == '`' char.repeat(1).as(:info).maybe end end |
#consume_fenced_indent ⇒ Object
153 154 155 156 157 158 159 160 161 162 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 153 def consume_fenced_indent dynamic do |_src, ctx| indent = ctx.captures[:fence_indent].to_s.length if indent.positive? str(' ').repeat(0, indent) else any.present? end end end |
#continuation ⇒ Object
Block nesting is the tricky part, but Parslet’s ‘dynamic` and `scope` make it possible to be aware of what blocks we’re already in, and implement a check for whether we’re still inside of those blocks on the beginning of every line. The rules that match the line run inside of the innermost parser expression, but this way they are aware of where they’re nested at runtime.
‘continuation` MUST NOT be a `rule`, otherwise gets cached in a failure state and prevents nested alternatives from working
43 44 45 46 47 48 49 50 51 52 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 43 def continuation dynamic do |_src, ctx| # puts "parsing continuation at #{src.line_and_column} (#{src.bytepos}) with #{ctx.captures[:cont]}" if ctx.captures.key?(:cont) ctx.captures[:cont].ignore else any.present? end end end |
#debug(msg) ⇒ Object
NOTE: Debug method for parser development. Outputs current parse position and capture context. Only called during parser debugging sessions.
13 14 15 16 17 18 19 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 13 def debug(msg) dynamic do |src, ctx| puts "#{msg} @ #{src.line_and_column}:" pp ctx.captures any.present? | any.absent? end end |
#open_block(kind, cont_rule) ⇒ Object
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 54 def open_block(kind, cont_rule) dynamic do |_src, ctx| parent_scope = ctx.captures.current.parent ctx.captures[:cont] = cont_rule ctx.captures[:cont] = parent_scope[:cont] >> cont_rule if parent_scope.key?(:cont) ctx.captures[:block] = kind # puts "starting block #{kind} at #{src.line_and_column} (#{src.bytepos}): #{ctx.captures[:cont]}" any.present? | any.absent? end end |
#thematic_break_char(c) ⇒ Object
95 96 97 |
# File 'lib/coradoc/markdown/parser/block_parser.rb', line 95 def thematic_break_char(c) (str(c) >> whitespace.repeat).repeat(3) end |