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

Instance Method Details

#_scan_blockString (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.

Returns:

  • (String)

    the block's body.

Raises:

  • (SyntaxError)

    if it reaches the end before the final bracket is closed.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/antelope/ace/scanner/second.rb', line 137

def _scan_block
  brack = 1
  body = "{"

  until brack.zero?
    if part = @scanner.scan_until(/(\}|\{)/)
      body << part

      if @scanner[1] == "}"
        brack -= 1
      else
        brack += 1
      end
    else
      error!
    end
  end

  body
end

#scan_second_partvoid

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.

Raises:

  • (SyntaxError)

    if no content boundry was found, or if the scanner encounters anything but a rule or whitespace.

See Also:



28
29
30
31
32
33
34
35
# File 'lib/antelope/ace/scanner/second.rb', line 28

def scan_second_part
  scanner.scan(CONTENT_BOUNDRY) or error!
  tokens << [:second]

  until @scanner.check(CONTENT_BOUNDRY)
    scan_second_rule || scan_whitespace || error!
  end
end

#scan_second_ruleBoolean

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.

Returns:

  • (Boolean)

    if it matched

See Also:



45
46
47
48
49
50
51
# File 'lib/antelope/ace/scanner/second.rb', line 45

def scan_second_rule
  if @scanner.check(/([a-z]+):/)
    scan_second_rule_label or error!
    scan_second_rule_body
    true
  end
end

#scan_second_rule_blockBoolean

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.

Returns:

  • (Boolean)

    if it matched.



119
120
121
122
123
# File 'lib/antelope/ace/scanner/second.rb', line 119

def scan_second_rule_block
  if @scanner.scan(/\{/)
    tokens << [:block, _scan_block]
  end
end

#scan_second_rule_bodyvoid

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.



73
74
75
76
77
78
79
80
81
# File 'lib/antelope/ace/scanner/second.rb', line 73

def scan_second_rule_body
  body = true
  while body
    scan_second_rule_part || scan_second_rule_or ||
    scan_second_rule_prec || scan_second_rule_block ||
    scan_whitespace || (body = false)
  end
  @scanner.scan(/;/)
end

#scan_second_rule_labelBoolean

Scans the label for a rule. It should contain only lower case letters and a colon.

Returns:

  • (Boolean)

    if it matched.



57
58
59
60
61
# File 'lib/antelope/ace/scanner/second.rb', line 57

def scan_second_rule_label
  if @scanner.scan(/([a-z]+): ?/)
    tokens << [:label, @scanner[1]]
  end
end

#scan_second_rule_orBoolean

Attempts to scan an "or". It's just a vertical bar.

Returns:

  • (Boolean)

    if it matched.



97
98
99
100
101
# File 'lib/antelope/ace/scanner/second.rb', line 97

def scan_second_rule_or
  if @scanner.scan(/\|/)
    tokens << [:or]
  end
end

#scan_second_rule_partBoolean

Attempts to scan a "part". A part is any series of alphabetical characters that are not followed by a colon.

Returns:

  • (Boolean)

    if it matched.



88
89
90
91
92
# File 'lib/antelope/ace/scanner/second.rb', line 88

def scan_second_rule_part
  if @scanner.scan(/([A-Za-z]+)(?!\:)/)
    tokens << [:part, @scanner[1]]
  end
end

#scan_second_rule_precBoolean

Attempts to scan a precedence definition. A precedence definition is "%prec " followed by a terminal or nonterminal.

Returns:

  • (Boolean)

    if it matched.



107
108
109
110
111
# File 'lib/antelope/ace/scanner/second.rb', line 107

def scan_second_rule_prec
  if @scanner.scan(/%prec ([A-Za-z]+)/)
    tokens << [:prec, @scanner[1]]
  end
end