antelope 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +25 -25
  3. data/.rspec +3 -3
  4. data/.travis.yml +10 -10
  5. data/.yardopts +7 -7
  6. data/CONTRIBUTING.md +50 -38
  7. data/GENERATORS.md +180 -124
  8. data/Gemfile +7 -7
  9. data/LICENSE.txt +22 -22
  10. data/README.md +240 -104
  11. data/Rakefile +2 -2
  12. data/TODO.md +58 -58
  13. data/antelope.gemspec +29 -28
  14. data/bin/antelope +7 -7
  15. data/examples/deterministic.ace +35 -35
  16. data/examples/example.ace +52 -51
  17. data/examples/example.ace.err +192 -192
  18. data/examples/example.ace.inf +432 -432
  19. data/examples/example.ate +70 -70
  20. data/examples/example.ate.err +192 -192
  21. data/examples/example.ate.inf +432 -432
  22. data/examples/liquidscript.ace +233 -233
  23. data/examples/simple.ace +22 -22
  24. data/lib/antelope/ace/compiler.rb +334 -334
  25. data/lib/antelope/ace/errors.rb +30 -30
  26. data/lib/antelope/ace/scanner/argument.rb +57 -57
  27. data/lib/antelope/ace/scanner/first.rb +89 -89
  28. data/lib/antelope/ace/scanner/second.rb +178 -178
  29. data/lib/antelope/ace/scanner/third.rb +27 -27
  30. data/lib/antelope/ace/scanner.rb +144 -144
  31. data/lib/antelope/ace.rb +47 -47
  32. data/lib/antelope/cli.rb +60 -60
  33. data/lib/antelope/errors.rb +25 -25
  34. data/lib/antelope/generation/constructor/first.rb +86 -86
  35. data/lib/antelope/generation/constructor/follow.rb +105 -105
  36. data/lib/antelope/generation/constructor/nullable.rb +64 -64
  37. data/lib/antelope/generation/constructor.rb +127 -127
  38. data/lib/antelope/generation/errors.rb +17 -17
  39. data/lib/antelope/generation/null.rb +13 -13
  40. data/lib/antelope/generation/recognizer/rule.rb +216 -216
  41. data/lib/antelope/generation/recognizer/state.rb +129 -129
  42. data/lib/antelope/generation/recognizer.rb +177 -177
  43. data/lib/antelope/generation/tableizer.rb +176 -176
  44. data/lib/antelope/generation.rb +15 -15
  45. data/lib/antelope/generator/base/coerce.rb +115 -0
  46. data/lib/antelope/generator/base/extra.rb +50 -0
  47. data/lib/antelope/generator/base.rb +134 -264
  48. data/lib/antelope/generator/c.rb +11 -11
  49. data/lib/antelope/generator/c_header.rb +105 -105
  50. data/lib/antelope/generator/c_source.rb +39 -39
  51. data/lib/antelope/generator/error.rb +34 -34
  52. data/lib/antelope/generator/group.rb +60 -57
  53. data/lib/antelope/generator/html.rb +51 -51
  54. data/lib/antelope/generator/info.rb +47 -47
  55. data/lib/antelope/generator/null.rb +18 -18
  56. data/lib/antelope/generator/output.rb +17 -17
  57. data/lib/antelope/generator/ruby.rb +112 -79
  58. data/lib/antelope/generator/templates/c_header.ant +36 -36
  59. data/lib/antelope/generator/templates/c_source.ant +202 -202
  60. data/lib/antelope/generator/templates/error.erb +40 -0
  61. data/lib/antelope/generator/templates/html/antelope.css +53 -1
  62. data/lib/antelope/generator/templates/html/antelope.html +82 -1
  63. data/lib/antelope/generator/templates/html/antelope.js +9 -1
  64. data/lib/antelope/generator/templates/html/css.ant +53 -53
  65. data/lib/antelope/generator/templates/html/html.ant +82 -82
  66. data/lib/antelope/generator/templates/html/js.ant +9 -9
  67. data/lib/antelope/generator/templates/info.erb +61 -0
  68. data/lib/antelope/generator/templates/{ruby.ant → ruby.erb} +171 -178
  69. data/lib/antelope/generator.rb +62 -66
  70. data/lib/antelope/grammar/generation.rb +76 -76
  71. data/lib/antelope/grammar/loading.rb +84 -84
  72. data/lib/antelope/grammar/precedence.rb +59 -59
  73. data/lib/antelope/grammar/precedences.rb +64 -64
  74. data/lib/antelope/grammar/production.rb +56 -56
  75. data/lib/antelope/grammar/productions.rb +154 -154
  76. data/lib/antelope/grammar/symbols.rb +64 -64
  77. data/lib/antelope/grammar/token/epsilon.rb +23 -23
  78. data/lib/antelope/grammar/token/error.rb +24 -24
  79. data/lib/antelope/grammar/token/nonterminal.rb +15 -15
  80. data/lib/antelope/grammar/token/terminal.rb +15 -15
  81. data/lib/antelope/grammar/token.rb +231 -231
  82. data/lib/antelope/grammar.rb +68 -68
  83. data/lib/antelope/version.rb +6 -6
  84. data/lib/antelope.rb +18 -19
  85. data/optimizations.txt +42 -42
  86. data/spec/antelope/ace/compiler_spec.rb +60 -60
  87. data/spec/antelope/ace/scanner_spec.rb +27 -27
  88. data/spec/antelope/generation/constructor_spec.rb +131 -131
  89. data/spec/fixtures/simple.ace +22 -22
  90. data/spec/spec_helper.rb +39 -39
  91. data/spec/support/benchmark_helper.rb +5 -5
  92. data/spec/support/grammar_helper.rb +14 -14
  93. data/subl/Ace (Ruby).JSON-tmLanguage +94 -94
  94. data/subl/Ace (Ruby).tmLanguage +153 -153
  95. metadata +22 -11
  96. data/lib/antelope/generator/templates/error.ant +0 -34
  97. data/lib/antelope/generator/templates/info.ant +0 -53
  98. data/lib/antelope/template/compiler.rb +0 -78
  99. data/lib/antelope/template/errors.rb +0 -9
  100. data/lib/antelope/template/scanner.rb +0 -109
  101. data/lib/antelope/template.rb +0 -64
  102. data/spec/antelope/template_spec.rb +0 -50
@@ -1,178 +1,178 @@
1
- # encoding: utf-8
2
-
3
- module Antelope
4
- module Ace
5
- class Scanner
6
-
7
- # Scans the second part of the file. The second part of the
8
- # file _only_ contains productions (or rules). Rules have a
9
- # label and a body; the label may be any lowercase alphabetical
10
- # identifier followed by a colon; the body consists of "parts",
11
- # an "or", a "prec", and/or a "block". The part may consist
12
- # of any alphabetical characters. An or is just a vertical bar
13
- # (`|`). A prec is a precedence declaraction, which is `%prec `
14
- # followed by any alphabetical characters. A block is a `{`,
15
- # followed by code, followed by a terminating `}`. Rules _may_
16
- # be terminated by a semicolon, but this is optional.
17
- module Second
18
-
19
- # Scans the second part of the file. This should be from just
20
- # before the first content boundry; if the scanner doesn't
21
- # find a content boundry, it will error. It will then check
22
- # for a rule.
23
- #
24
- # @raise [SyntaxError] if no content boundry was found, or if
25
- # the scanner encounters anything but a rule or whitespace.
26
- # @return [void]
27
- # @see #scan_second_rule
28
- # @see #scan_whitespace
29
- # @see #error!
30
- def scan_second_part
31
- scanner.scan(CONTENT_BOUNDRY) or error!
32
- tokens << [:second]
33
-
34
- until @scanner.check(CONTENT_BOUNDRY)
35
- scan_second_rule || scan_whitespace || scan_comment ||
36
- error!
37
- end
38
- end
39
-
40
- # Scans a rule. A rule consists of a label (the nonterminal
41
- # the production is for), a body, and a block; and then,
42
- # an optional semicolon.
43
- #
44
- # @return [Boolean] if it matched
45
- # @see #scan_second_rule_label
46
- # @see #scan_second_rule_body
47
- # @see #error!
48
- def scan_second_rule
49
- if @scanner.check(/(#{IDENTIFIER})(\[#{IDENTIFIER}\])?:/)
50
- scan_second_rule_label or error!
51
- scan_second_rule_body
52
- true
53
- end
54
- end
55
-
56
- # Scans the label for a rule. It should contain only lower
57
- # case letters and a colon.
58
- #
59
- # @return [Boolean] if it matched.
60
- def scan_second_rule_label
61
- if @scanner.scan(/(#{IDENTIFIER})(?:\[(#{IDENTIFIER})\])?: ?/)
62
- tokens << [:label, @scanner[1], @scanner[2]]
63
- end
64
- end
65
-
66
- # The body can contain parts, ors, precs, or blocks (or
67
- # whitespaces). Scans all of them, and then attempts to
68
- # scan a semicolon.
69
- #
70
- # @return [void]
71
- # @see #scan_second_rule_part
72
- # @see #scan_second_rule_or
73
- # @see #scan_second_rule_prec
74
- # @see #scan_second_rule_block
75
- # @see #scan_whitespace
76
- def scan_second_rule_body
77
- body = true
78
- while body
79
- scan_second_rule_prec || scan_second_rule_part ||
80
- scan_second_rule_or || scan_second_rule_block ||
81
- scan_whitespace || scan_comment || (body = false)
82
- end
83
- @scanner.scan(/;/)
84
- end
85
-
86
- # Attempts to scan a "part". A part is any series of
87
- # alphabetical characters that are not followed by a
88
- # colon.
89
- #
90
- # @return [Boolean] if it matched.
91
- def scan_second_rule_part
92
- if @scanner.scan(/(%?#{IDENTIFIER})(?:\[(#{IDENTIFIER})\])?(?!\:|[A-Za-z._])/)
93
- tokens << [:part, @scanner[1], @scanner[2]]
94
- end
95
- end
96
-
97
- # Attempts to scan an "or". It's just a vertical bar.
98
- #
99
- # @return [Boolean] if it matched.
100
- def scan_second_rule_or
101
- if @scanner.scan(/\|/)
102
- tokens << [:or]
103
- end
104
- end
105
-
106
- # Attempts to scan a precedence definition. A precedence
107
- # definition is "%prec " followed by a terminal or nonterminal.
108
- #
109
- # @return [Boolean] if it matched.
110
- def scan_second_rule_prec
111
- if @scanner.scan(/%prec (#{IDENTIFIER})/)
112
- tokens << [:prec, @scanner[1]]
113
- end
114
- end
115
-
116
- # Attempts to scan a block. This correctly balances brackets;
117
- # however, if a bracket is opened/closed within a string, it
118
- # still counts that as a bracket that needs to be balanced.
119
- # So, having extensive code within a block is not a good idea.
120
- #
121
- # @return [Boolean] if it matched.
122
- def scan_second_rule_block
123
- if @scanner.scan(/\{/)
124
- tokens << [:block, _scan_block]
125
- end
126
- end
127
-
128
- private
129
-
130
- # Scans the block; it scans until it encounters enough closing
131
- # brackets to match the opening brackets. If it encounters
132
- # an opening brackets, it increments the bracket counter by
133
- # one; if it encounters a closing bracket, it decrements by
134
- # one. It will error if it reaches the end before the
135
- # brackets are fully closed.
136
- #
137
- # @return [String] the block's body.
138
- # @raise [SyntaxError] if it reaches the end before the final
139
- # bracket is closed.
140
- def _scan_block
141
- brack = 1
142
- body = "{"
143
- scan_for = %r{
144
- (
145
- (?: " ( \\\\ | \\" | [^"] )* "? )
146
- | (?: ' ( \\\\ | \\' | [^'] )* '? )
147
- | (?: // .*? \n )
148
- | (?: \# .*? \n )
149
- | (?: /\* [\s\S]+? \*/ )
150
- | (?: \} )
151
- | (?: \{ )
152
- )
153
- }x
154
-
155
- until brack.zero?
156
- if part = @scanner.scan_until(scan_for)
157
- body << part
158
-
159
-
160
- if @scanner[1] == "}"
161
- brack -= 1
162
- elsif @scanner[1] == "{"
163
- brack += 1
164
- end
165
- else
166
- if @scanner.scan(/(.+)/m)
167
- @line += @scanner[1].count("\n")
168
- end
169
- error!
170
- end
171
- end
172
-
173
- body
174
- end
175
- end
176
- end
177
- end
178
- end
1
+ # encoding: utf-8
2
+
3
+ module Antelope
4
+ module Ace
5
+ class Scanner
6
+
7
+ # Scans the second part of the file. The second part of the
8
+ # file _only_ contains productions (or rules). Rules have a
9
+ # label and a body; the label may be any lowercase alphabetical
10
+ # identifier followed by a colon; the body consists of "parts",
11
+ # an "or", a "prec", and/or a "block". The part may consist
12
+ # of any alphabetical characters. An or is just a vertical bar
13
+ # (`|`). A prec is a precedence declaraction, which is `%prec `
14
+ # followed by any alphabetical characters. A block is a `{`,
15
+ # followed by code, followed by a terminating `}`. Rules _may_
16
+ # be terminated by a semicolon, but this is optional.
17
+ module Second
18
+
19
+ # Scans the second part of the file. This should be from just
20
+ # before the first content boundry; if the scanner doesn't
21
+ # find a content boundry, it will error. It will then check
22
+ # for a rule.
23
+ #
24
+ # @raise [SyntaxError] if no content boundry was found, or if
25
+ # the scanner encounters anything but a rule or whitespace.
26
+ # @return [void]
27
+ # @see #scan_second_rule
28
+ # @see #scan_whitespace
29
+ # @see #error!
30
+ def scan_second_part
31
+ scanner.scan(CONTENT_BOUNDRY) or error!
32
+ tokens << [:second]
33
+
34
+ until @scanner.check(CONTENT_BOUNDRY)
35
+ scan_second_rule || scan_whitespace || scan_comment ||
36
+ error!
37
+ end
38
+ end
39
+
40
+ # Scans a rule. A rule consists of a label (the nonterminal
41
+ # the production is for), a body, and a block; and then,
42
+ # an optional semicolon.
43
+ #
44
+ # @return [Boolean] if it matched
45
+ # @see #scan_second_rule_label
46
+ # @see #scan_second_rule_body
47
+ # @see #error!
48
+ def scan_second_rule
49
+ if @scanner.check(/(#{IDENTIFIER})(\[#{IDENTIFIER}\])?:/)
50
+ scan_second_rule_label or error!
51
+ scan_second_rule_body
52
+ true
53
+ end
54
+ end
55
+
56
+ # Scans the label for a rule. It should contain only lower
57
+ # case letters and a colon.
58
+ #
59
+ # @return [Boolean] if it matched.
60
+ def scan_second_rule_label
61
+ if @scanner.scan(/(#{IDENTIFIER})(?:\[(#{IDENTIFIER})\])?: ?/)
62
+ tokens << [:label, @scanner[1], @scanner[2]]
63
+ end
64
+ end
65
+
66
+ # The body can contain parts, ors, precs, or blocks (or
67
+ # whitespaces). Scans all of them, and then attempts to
68
+ # scan a semicolon.
69
+ #
70
+ # @return [void]
71
+ # @see #scan_second_rule_part
72
+ # @see #scan_second_rule_or
73
+ # @see #scan_second_rule_prec
74
+ # @see #scan_second_rule_block
75
+ # @see #scan_whitespace
76
+ def scan_second_rule_body
77
+ body = true
78
+ while body
79
+ scan_second_rule_prec || scan_second_rule_part ||
80
+ scan_second_rule_or || scan_second_rule_block ||
81
+ scan_whitespace || scan_comment || (body = false)
82
+ end
83
+ @scanner.scan(/;/)
84
+ end
85
+
86
+ # Attempts to scan a "part". A part is any series of
87
+ # alphabetical characters that are not followed by a
88
+ # colon.
89
+ #
90
+ # @return [Boolean] if it matched.
91
+ def scan_second_rule_part
92
+ if @scanner.scan(/(%?#{IDENTIFIER})(?:\[(#{IDENTIFIER})\])?(?!\:|[A-Za-z._])/)
93
+ tokens << [:part, @scanner[1], @scanner[2]]
94
+ end
95
+ end
96
+
97
+ # Attempts to scan an "or". It's just a vertical bar.
98
+ #
99
+ # @return [Boolean] if it matched.
100
+ def scan_second_rule_or
101
+ if @scanner.scan(/\|/)
102
+ tokens << [:or]
103
+ end
104
+ end
105
+
106
+ # Attempts to scan a precedence definition. A precedence
107
+ # definition is "%prec " followed by a terminal or nonterminal.
108
+ #
109
+ # @return [Boolean] if it matched.
110
+ def scan_second_rule_prec
111
+ if @scanner.scan(/%prec (#{IDENTIFIER})/)
112
+ tokens << [:prec, @scanner[1]]
113
+ end
114
+ end
115
+
116
+ # Attempts to scan a block. This correctly balances brackets;
117
+ # however, if a bracket is opened/closed within a string, it
118
+ # still counts that as a bracket that needs to be balanced.
119
+ # So, having extensive code within a block is not a good idea.
120
+ #
121
+ # @return [Boolean] if it matched.
122
+ def scan_second_rule_block
123
+ if @scanner.scan(/\{/)
124
+ tokens << [:block, _scan_block]
125
+ end
126
+ end
127
+
128
+ private
129
+
130
+ # Scans the block; it scans until it encounters enough closing
131
+ # brackets to match the opening brackets. If it encounters
132
+ # an opening brackets, it increments the bracket counter by
133
+ # one; if it encounters a closing bracket, it decrements by
134
+ # one. It will error if it reaches the end before the
135
+ # brackets are fully closed.
136
+ #
137
+ # @return [String] the block's body.
138
+ # @raise [SyntaxError] if it reaches the end before the final
139
+ # bracket is closed.
140
+ def _scan_block
141
+ brack = 1
142
+ body = "{"
143
+ scan_for = %r{
144
+ (
145
+ (?: " ( \\\\ | \\" | [^"] )* "? )
146
+ | (?: ' ( \\\\ | \\' | [^'] )* '? )
147
+ | (?: // .*? \n )
148
+ | (?: \# .*? \n )
149
+ | (?: /\* [\s\S]+? \*/ )
150
+ | (?: \} )
151
+ | (?: \{ )
152
+ )
153
+ }x
154
+
155
+ until brack.zero?
156
+ if part = @scanner.scan_until(scan_for)
157
+ body << part
158
+
159
+
160
+ if @scanner[1] == "}"
161
+ brack -= 1
162
+ elsif @scanner[1] == "{"
163
+ brack += 1
164
+ end
165
+ else
166
+ if @scanner.scan(/(.+)/m)
167
+ @line += @scanner[1].count("\n")
168
+ end
169
+ error!
170
+ end
171
+ end
172
+
173
+ body
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
@@ -1,27 +1,27 @@
1
- # encoding: utf-8
2
-
3
- module Antelope
4
- module Ace
5
- class Scanner
6
-
7
- # Scans the third part. Everything after the content
8
- # boundry is copied directly into the output.
9
- module Third
10
-
11
- # Scans the third part. It should start with a content
12
- # boundry; raises an error if it does not. It then scans
13
- # until the end of the file.
14
- #
15
- # @raise [SyntaxError] if somehow there is no content
16
- # boundry.
17
- # @return [void]
18
- def scan_third_part
19
- @scanner.scan(CONTENT_BOUNDRY) or error!
20
-
21
- tokens << [:third]
22
- tokens << [:copy, @scanner.scan(/[\s\S]+/m) || ""]
23
- end
24
- end
25
- end
26
- end
27
- end
1
+ # encoding: utf-8
2
+
3
+ module Antelope
4
+ module Ace
5
+ class Scanner
6
+
7
+ # Scans the third part. Everything after the content
8
+ # boundry is copied directly into the output.
9
+ module Third
10
+
11
+ # Scans the third part. It should start with a content
12
+ # boundry; raises an error if it does not. It then scans
13
+ # until the end of the file.
14
+ #
15
+ # @raise [SyntaxError] if somehow there is no content
16
+ # boundry.
17
+ # @return [void]
18
+ def scan_third_part
19
+ @scanner.scan(CONTENT_BOUNDRY) or error!
20
+
21
+ tokens << [:third]
22
+ tokens << [:copy, @scanner.scan(/[\s\S]+/m) || ""]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end