Module: Antelope::Ace::Scanner::Second
- Included in:
- Antelope::Ace::Scanner
- Defined in:
- lib/antelope/ace/scanner/second.rb
Overview
Scans the second part of the file. The second part of the
file only contains productions (or rules). Rules have a
label and a body; the label may be any lowercase alphabetical
identifier followed by a colon; the body consists of "parts",
an "or", a "prec", and/or a "block". The part may consist
of any alphabetical characters. An or is just a vertical bar
(|
). A prec is a precedence declaraction, which is %prec
followed by any alphabetical characters. A block is a {
,
followed by code, followed by a terminating }
. Rules may
be terminated by a semicolon, but this is optional.
Instance Method Summary collapse
-
#_scan_block ⇒ String
private
Scans the block; it scans until it encounters enough closing brackets to match the opening brackets.
-
#scan_second_part ⇒ void
Scans the second part of the file.
-
#scan_second_rule ⇒ Boolean
Scans a rule.
-
#scan_second_rule_block ⇒ Boolean
Attempts to scan a block.
-
#scan_second_rule_body ⇒ void
The body can contain parts, ors, precs, or blocks (or whitespaces).
-
#scan_second_rule_label ⇒ Boolean
Scans the label for a rule.
-
#scan_second_rule_or ⇒ Boolean
Attempts to scan an "or".
-
#scan_second_rule_part ⇒ Boolean
Attempts to scan a "part".
-
#scan_second_rule_prec ⇒ Boolean
Attempts to scan a precedence definition.
Instance Method Details
#_scan_block ⇒ String (private)
Scans the block; it scans until it encounters enough closing brackets to match the opening brackets. If it encounters an opening brackets, it increments the bracket counter by one; if it encounters a closing bracket, it decrements by one. It will error if it reaches the end before the brackets are fully closed.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/antelope/ace/scanner/second.rb', line 140 def _scan_block brack = 1 body = "{" scan_for = %r{ ( (?: " ( \\\\ | \\" | [^"] )* "? ) | (?: ' ( \\\\ | \\' | [^'] )* '? ) | (?: // .*? \n ) | (?: \# .*? \n ) | (?: /\* [\s\S]+? \*/ ) | (?: \} ) | (?: \{ ) ) }x until brack.zero? if part = @scanner.scan_until(scan_for) body << part if @scanner[1] == "}" brack -= 1 elsif @scanner[1] == "{" brack += 1 end else if @scanner.scan(/(.+)/m) @line += @scanner[1].count("\n") end error! end end body end |
#scan_second_part ⇒ void
This method returns an undefined value.
Scans the second part of the file. This should be from just before the first content boundry; if the scanner doesn't find a content boundry, it will error. It will then check for a rule.
30 31 32 33 34 35 36 37 38 |
# File 'lib/antelope/ace/scanner/second.rb', line 30 def scan_second_part scanner.scan(CONTENT_BOUNDRY) or error! tokens << [:second] until @scanner.check(CONTENT_BOUNDRY) scan_second_rule || scan_whitespace || scan_comment || error! end end |
#scan_second_rule ⇒ Boolean
Scans a rule. A rule consists of a label (the nonterminal the production is for), a body, and a block; and then, an optional semicolon.
48 49 50 51 52 53 54 |
# File 'lib/antelope/ace/scanner/second.rb', line 48 def scan_second_rule if @scanner.check(/(#{IDENTIFIER})(\[#{IDENTIFIER}\])?:/) scan_second_rule_label or error! scan_second_rule_body true end end |
#scan_second_rule_block ⇒ Boolean
Attempts to scan a block. This correctly balances brackets; however, if a bracket is opened/closed within a string, it still counts that as a bracket that needs to be balanced. So, having extensive code within a block is not a good idea.
122 123 124 125 126 |
# File 'lib/antelope/ace/scanner/second.rb', line 122 def scan_second_rule_block if @scanner.scan(/\{/) tokens << [:block, _scan_block] end end |
#scan_second_rule_body ⇒ void
This method returns an undefined value.
The body can contain parts, ors, precs, or blocks (or whitespaces). Scans all of them, and then attempts to scan a semicolon.
76 77 78 79 80 81 82 83 84 |
# File 'lib/antelope/ace/scanner/second.rb', line 76 def scan_second_rule_body body = true while body scan_second_rule_prec || scan_second_rule_part || scan_second_rule_or || scan_second_rule_block || scan_whitespace || scan_comment || (body = false) end @scanner.scan(/;/) end |
#scan_second_rule_label ⇒ Boolean
Scans the label for a rule. It should contain only lower case letters and a colon.
60 61 62 63 64 |
# File 'lib/antelope/ace/scanner/second.rb', line 60 def scan_second_rule_label if @scanner.scan(/(#{IDENTIFIER})(?:\[(#{IDENTIFIER})\])?: ?/) tokens << [:label, @scanner[1], @scanner[2]] end end |
#scan_second_rule_or ⇒ Boolean
Attempts to scan an "or". It's just a vertical bar.
100 101 102 103 104 |
# File 'lib/antelope/ace/scanner/second.rb', line 100 def scan_second_rule_or if @scanner.scan(/\|/) tokens << [:or] end end |
#scan_second_rule_part ⇒ Boolean
Attempts to scan a "part". A part is any series of alphabetical characters that are not followed by a colon.
91 92 93 94 95 |
# File 'lib/antelope/ace/scanner/second.rb', line 91 def scan_second_rule_part if @scanner.scan(/(%?#{IDENTIFIER})(?:\[(#{IDENTIFIER})\])?(?!\:|[A-Za-z._])/) tokens << [:part, @scanner[1], @scanner[2]] end end |
#scan_second_rule_prec ⇒ Boolean
Attempts to scan a precedence definition. A precedence definition is "%prec " followed by a terminal or nonterminal.
110 111 112 113 114 |
# File 'lib/antelope/ace/scanner/second.rb', line 110 def scan_second_rule_prec if @scanner.scan(/%prec (#{IDENTIFIER})/) tokens << [:prec, @scanner[1]] end end |