antelope 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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