Class: Ntxt::Parser
- Inherits:
-
Object
- Object
- Ntxt::Parser
- Defined in:
- lib/ntxt/parser.rb
Overview
The parser for Ntxt. Most of this a typical user will not find useful with the exception of Parser.parse.
Defined Under Namespace
Classes: State
Class Method Summary collapse
-
.extractTags(block, line) ⇒ Object
Extract all the tags from the given line.
-
.hlevel(line) ⇒ Object
Return an array in which the first element is the indent length and the second element is the contained text.
Instance Method Summary collapse
-
#parse(ntxtObj) ⇒ Object
Parse the given Ntxt ‘s Ntxt#text.
-
#parseHlevel(level, title) ⇒ Object
Take the state off the top of the #stack and attempt to parse an Hlevel block.
-
#parseIndent(indentLevel, text) ⇒ Object
Parse blocks of text that are indented at the given level or greater.
-
#parseLines ⇒ Object
This is the root of the parser’s call tree after #parse sets up the parse.
Class Method Details
.extractTags(block, line) ⇒ Object
Extract all the tags from the given line.
- block
-
The block to which all tags will be added with Block#addTag. All parent blocks recieve copies of the child block’s tag.
- line
-
The line to extract all tags from. Tags are square-bracket-enclosed strings found in sequence at the beginning of a line. If the sequence is broken, extraction stops.
Some tag examples:
[a tag] [another tag]
[a tag] [another tag] Not a tag. [not a tag]
No tag on this line.
No tag on this line either. [not a tag]
157 158 159 160 161 162 163 |
# File 'lib/ntxt/parser.rb', line 157 def self.extractTags(block, line) while line =~ /^\s*\[([^\[]+)\]/m block.addTag($~[1]) matchLength = $~[0].length line = line[matchLength,line.length - matchLength] end end |
.hlevel(line) ⇒ Object
Return an array in which the first element is the indent length and the second element is the contained text. Nil otherwise.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/ntxt/parser.rb', line 127 def self.hlevel(line) case line when /^\s*=([^=].*)=\s*$/ [ 1, $~[1] ] when /^\s*==([^=].*)==\s*$/ [ 2, $~[1] ] when /^\s*===([^=].*)===\s*$/ [ 3, $~[1] ] when /^\s*====([^=].*)====\s*$/ [ 4, $~[1] ] when /^\s*=====([^=].*)=====\s*$/ [ 5, $~[1] ] when /^\s*======([^=].*)======\s*$/ [ 6, $~[1] ] else nil end end |
Instance Method Details
#parse(ntxtObj) ⇒ Object
Parse the given Ntxt ‘s Ntxt#text.
- ntxtObj
-
If this is an Ntxt object, Ntxt#text is parsed. If
ntxtObj
is not an Ntxt object, it is assumed to be a valid argument for Ntxt.new and a new Ntxt is constructed.
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/ntxt/parser.rb', line 169 def parse(ntxtObj) # If ntxtObj isn't an Ntxt, create it as one. ( ntxtObj = Ntxt.new(ntxtObj) ) unless ntxtObj.is_a?( Ntxt ) lines = ntxtObj.text.split("\n") rootBlock = Block.new(ntxtObj) @stack = [ State.new( lines, rootBlock, 0, 0, lines.length ) ] parseLines() if @stack.length == 1 # parse success! rootBlock else # parse failure. nil end end |
#parseHlevel(level, title) ⇒ Object
Take the state off the top of the #stack and attempt to parse an Hlevel block. An HLevel block is a wiki-like header block of text. For example:
= Header 1 =
== Header 2 ==
- level
-
an integer from 1 to 6.
- title
-
a string of the text found between the equal signs.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/ntxt/parser.rb', line 198 def parseHlevel(level, title) state = @stack[-1] # If in parseHlevel, don't get the current line. That is contained # in the title argument. Instead, get the next line and proceed. line = state.nextLine while line # Check if we have discovered another block in the form of an hlevel. hl = Parser::hlevel(line) if hl && hl[0].to_i <= level break end line = state.nextLine end block = Block.new( state.block.ntxt, state.block, state.start, state.offset) subState = State.new( state.lines, block, state.lineStart+1, state.start + state.lines[state.lineStart].length + 1, state.line) @stack.push subState parseLines @stack.pop state.consume end |
#parseIndent(indentLevel, text) ⇒ Object
Parse blocks of text that are indented at the given level or greater.
- indentLevel
-
an integer denoteing the number of characters this line is indented at.
- text
-
the content of the line that was indented.
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/ntxt/parser.rb', line 239 def parseIndent(indentLevel, text) state = @stack[-1] line = state.currLine # Build the block. Update the offset. block = Block.new(state.block.ntxt, state.block, state.start, state.offset) # Position state at the ed of the block. # Blocks are ended by empty lines or lines with the = starting them. while line break if Parser::hlevel(line) break unless line =~ /^(\s*)(..*)$/ nextIndentLevel = $~[1].length nextLine = $~[2] break if nextIndentLevel < indentLevel if nextIndentLevel > indentLevel # Advance to the next line after parsing a subblock. subState = State.new( state.lines, block, state.line, state.start + state.offset, state.lineEnd) @stack.push subState parseIndent(nextIndentLevel, nextLine) @stack.pop state.seek subState line = state.currLine else Parser::extractTags(block, line) line = state.nextLine end # if nextIndentLevel > indentLevel end # while line block.offset = state.offset state.consume end |
#parseLines ⇒ Object
This is the root of the parser’s call tree after #parse sets up the parse. This plucks the State off the Parser.stack, obtains the State.currLine.
When an indented line is found, #parseIndent is called. When a header line is found, #parseHlevel is caled. Otherwise, we move to the next line.
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/ntxt/parser.rb', line 292 def parseLines state = @stack[-1] line = state.currLine while line tmp = Parser::hlevel(line) if tmp state.consume parseHlevel(tmp[0].to_i, tmp[1]) line = state.currLine elsif line =~ /^(\s*)(\S.*)$/ state.consume parseIndent($~[1].length, $~[2]) line = state.currLine else line = state.nextLine end # if tmp end # while line end |