antelope 0.2.0 → 0.2.2

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +25 -23
  3. data/.rspec +3 -3
  4. data/.travis.yml +10 -9
  5. data/.yardopts +7 -7
  6. data/CONTRIBUTING.md +38 -38
  7. data/GENERATORS.md +124 -124
  8. data/Gemfile +7 -7
  9. data/LICENSE.txt +22 -22
  10. data/README.md +104 -104
  11. data/Rakefile +2 -2
  12. data/TODO.md +58 -58
  13. data/antelope.gemspec +28 -28
  14. data/bin/antelope +7 -7
  15. data/examples/deterministic.ace +35 -35
  16. data/examples/example.ace +51 -50
  17. data/examples/example.err +192 -0
  18. data/examples/{example.output → example.inf} +384 -385
  19. data/examples/liquidscript.ace +233 -162
  20. data/examples/simple.ace +22 -22
  21. data/lib/antelope/ace/compiler.rb +334 -334
  22. data/lib/antelope/ace/errors.rb +48 -48
  23. data/lib/antelope/ace/grammar/generation.rb +80 -80
  24. data/lib/antelope/ace/grammar/loading.rb +53 -53
  25. data/lib/antelope/ace/grammar/precedences.rb +68 -65
  26. data/lib/antelope/ace/grammar/productions.rb +156 -150
  27. data/lib/antelope/ace/grammar/symbols.rb +66 -66
  28. data/lib/antelope/ace/grammar.rb +69 -69
  29. data/lib/antelope/ace/precedence.rb +61 -61
  30. data/lib/antelope/ace/production.rb +57 -57
  31. data/lib/antelope/ace/scanner/argument.rb +57 -57
  32. data/lib/antelope/ace/scanner/first.rb +89 -89
  33. data/lib/antelope/ace/scanner/second.rb +177 -177
  34. data/lib/antelope/ace/scanner/third.rb +27 -27
  35. data/lib/antelope/ace/scanner.rb +134 -134
  36. data/lib/antelope/ace/token/epsilon.rb +24 -24
  37. data/lib/antelope/ace/token/error.rb +26 -26
  38. data/lib/antelope/ace/token/nonterminal.rb +17 -17
  39. data/lib/antelope/ace/token/terminal.rb +17 -17
  40. data/lib/antelope/ace/token.rb +238 -238
  41. data/lib/antelope/ace.rb +53 -53
  42. data/lib/antelope/cli.rb +55 -55
  43. data/lib/antelope/errors.rb +8 -8
  44. data/lib/antelope/generation/constructor/first.rb +88 -88
  45. data/lib/antelope/generation/constructor/follow.rb +103 -103
  46. data/lib/antelope/generation/constructor/nullable.rb +64 -64
  47. data/lib/antelope/generation/constructor.rb +126 -126
  48. data/lib/antelope/generation/errors.rb +17 -17
  49. data/lib/antelope/generation/null.rb +13 -13
  50. data/lib/antelope/generation/recognizer/rule.rb +216 -216
  51. data/lib/antelope/generation/recognizer/state.rb +130 -130
  52. data/lib/antelope/generation/recognizer.rb +180 -180
  53. data/lib/antelope/generation/tableizer.rb +175 -154
  54. data/lib/antelope/generation.rb +15 -15
  55. data/lib/antelope/generator/base.rb +264 -264
  56. data/lib/antelope/generator/c.rb +11 -11
  57. data/lib/antelope/generator/c_header.rb +105 -105
  58. data/lib/antelope/generator/c_source.rb +39 -39
  59. data/lib/antelope/generator/error.rb +34 -0
  60. data/lib/antelope/generator/group.rb +57 -57
  61. data/lib/antelope/generator/html.rb +51 -0
  62. data/lib/antelope/generator/info.rb +47 -0
  63. data/lib/antelope/generator/null.rb +18 -18
  64. data/lib/antelope/generator/output.rb +17 -49
  65. data/lib/antelope/generator/ruby.rb +79 -79
  66. data/lib/antelope/generator/templates/c_header.ant +36 -36
  67. data/lib/antelope/generator/templates/c_source.ant +202 -202
  68. data/lib/antelope/generator/templates/error.ant +33 -0
  69. data/lib/antelope/generator/templates/html/antelope.css +1 -0
  70. data/lib/antelope/generator/templates/html/antelope.html +1 -0
  71. data/lib/antelope/generator/templates/html/antelope.js +1 -0
  72. data/lib/antelope/generator/templates/html/css.ant +53 -0
  73. data/lib/antelope/generator/templates/html/html.ant +82 -0
  74. data/lib/antelope/generator/templates/html/js.ant +9 -0
  75. data/lib/antelope/generator/templates/info.ant +53 -0
  76. data/lib/antelope/generator/templates/ruby.ant +178 -146
  77. data/lib/antelope/generator.rb +66 -63
  78. data/lib/antelope/template/compiler.rb +78 -78
  79. data/lib/antelope/template/errors.rb +9 -9
  80. data/lib/antelope/template/scanner.rb +109 -109
  81. data/lib/antelope/template.rb +65 -60
  82. data/lib/antelope/version.rb +6 -6
  83. data/lib/antelope.rb +13 -13
  84. data/optimizations.txt +42 -0
  85. data/spec/antelope/ace/compiler_spec.rb +60 -60
  86. data/spec/antelope/ace/scanner_spec.rb +27 -27
  87. data/spec/antelope/constructor_spec.rb +133 -136
  88. data/spec/antelope/template_spec.rb +50 -49
  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 +15 -15
  93. data/subl/Ace (Ruby).JSON-tmLanguage +94 -94
  94. data/subl/Ace (Ruby).tmLanguage +153 -153
  95. metadata +17 -6
  96. data/lib/antelope/generator/templates/output.ant +0 -68
@@ -1,61 +1,61 @@
1
- # encoding: utf-8
2
-
3
- module Antelope
4
- module Ace
5
-
6
- # Defines a precedence. A precedence has a type, tokens, and a
7
- # level.
8
- class Precedence < Struct.new(:type, :tokens, :level)
9
-
10
- # @!attribute [rw] type
11
- # The type of precedence level. This should be one of
12
- # `:left`, `:right`, or `:nonassoc`.
13
- #
14
- # @return [Symbol] the type.
15
- # @!attribute [rw] tokens
16
- # An set of tokens that are on this specific precedence
17
- # level. The tokens are identified as symbols. The special
18
- # symbol, `:_`, represents any token.
19
- #
20
- # @return [Set<Symbol>] the tokens on this level.
21
- # @!attribute [rw] level
22
- # The level we're on. The higher the level, the higher the
23
- # precedence.
24
-
25
- include Comparable
26
-
27
- # Compares the other object to this object. If the other object
28
- # isn't a {Precedence}, it returns nil. If the other
29
- # precedence isn't on the same level as this one, then the
30
- # levels are compared and the result of that is returned. If
31
- # it is, however, the type is checked; if this precedence is
32
- # left associative, then it returns 1 (it is greater than the
33
- # other); if this precedence is right associative, then it
34
- # returns -1 (it is less than the other); if this precedence is
35
- # nonassociative, it returns 0 (it is equal to the other).
36
- #
37
- # @param other [Object] the object to compare to this one.
38
- # @return [Numeric?]
39
- def <=>(other)
40
- return nil unless other.is_a? Precedence
41
- if level != other.level
42
- level <=> other.level
43
- elsif type == :left
44
- 1
45
- elsif type == :right
46
- -1
47
- else
48
- 0
49
- end
50
- end
51
-
52
- # Converts the precedence into a representative string, denoting
53
- # the type and the level.
54
- #
55
- # @return [String]
56
- def to_s
57
- "#{type.to_s[0]}#{level}"
58
- end
59
- end
60
- end
61
- end
1
+ # encoding: utf-8
2
+
3
+ module Antelope
4
+ module Ace
5
+
6
+ # Defines a precedence. A precedence has a type, tokens, and a
7
+ # level.
8
+ class Precedence < Struct.new(:type, :tokens, :level)
9
+
10
+ # @!attribute [rw] type
11
+ # The type of precedence level. This should be one of
12
+ # `:left`, `:right`, or `:nonassoc`.
13
+ #
14
+ # @return [Symbol] the type.
15
+ # @!attribute [rw] tokens
16
+ # An set of tokens that are on this specific precedence
17
+ # level. The tokens are identified as symbols. The special
18
+ # symbol, `:_`, represents any token.
19
+ #
20
+ # @return [Set<Symbol>] the tokens on this level.
21
+ # @!attribute [rw] level
22
+ # The level we're on. The higher the level, the higher the
23
+ # precedence.
24
+
25
+ include Comparable
26
+
27
+ # Compares the other object to this object. If the other object
28
+ # isn't a {Precedence}, it returns nil. If the other
29
+ # precedence isn't on the same level as this one, then the
30
+ # levels are compared and the result of that is returned. If
31
+ # it is, however, the type is checked; if this precedence is
32
+ # left associative, then it returns 1 (it is greater than the
33
+ # other); if this precedence is right associative, then it
34
+ # returns -1 (it is less than the other); if this precedence is
35
+ # nonassociative, it returns 0 (it is equal to the other).
36
+ #
37
+ # @param other [Object] the object to compare to this one.
38
+ # @return [Numeric?]
39
+ def <=>(other)
40
+ return nil unless other.is_a? Precedence
41
+ if level != other.level
42
+ level <=> other.level
43
+ elsif type == :left
44
+ 1
45
+ elsif type == :right
46
+ -1
47
+ else
48
+ 0
49
+ end
50
+ end
51
+
52
+ # Converts the precedence into a representative string, denoting
53
+ # the type and the level.
54
+ #
55
+ # @return [String]
56
+ def to_s
57
+ "#{type.to_s[0]}#{level}"
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,57 +1,57 @@
1
- # encoding: utf-8
2
-
3
- module Antelope
4
- module Ace
5
-
6
- # Defines a production.
7
- class Production < Struct.new(:label, :items, :block, :prec, :id)
8
- # @!attribute [rw] label
9
- # The label (or left-hand side) of the production. This
10
- # should be a nonterminal.
11
- #
12
- # @return [Symbol]
13
- # @!attribute [rw] items
14
- # The body (or right-hand side) of the production. This can
15
- # be array of terminals and nonterminals.
16
- #
17
- # @return [Array<Token>]
18
- # @!attribute [rw] block
19
- # The block of code to be executed when the production's right
20
- # hand side is reduced.
21
- #
22
- # @return [String]
23
- # @!attribute [rw] prec
24
- # The precedence declaration for the production.
25
- #
26
- # @return [Ace::Precedence]
27
- # @!attribute [rw] id
28
- # The ID of the production. The starting production always
29
- # has an ID of 0.
30
- #
31
- # @return [Numeric]
32
-
33
- # Creates a new production from a hash. The hash's keys
34
- # correspond to the attributes on this class.
35
- #
36
- # @param hash [Hash<(Symbol, Object)>]
37
- def self.from_hash(hash)
38
- new(hash[:label] || hash["label"],
39
- hash[:items] || hash["items"],
40
- hash[:block] || hash["block"],
41
- hash[:prec] || hash["prec"],
42
- hash[:id] || hash["id"])
43
- end
44
-
45
- # Create a new version of the production with duplicated values.
46
- #
47
- # @return [Production]
48
- def clone
49
- Production.new(label.dup,
50
- items.map(&:dup),
51
- block.dup,
52
- prec.dup,
53
- id)
54
- end
55
- end
56
- end
57
- end
1
+ # encoding: utf-8
2
+
3
+ module Antelope
4
+ module Ace
5
+
6
+ # Defines a production.
7
+ class Production < Struct.new(:label, :items, :block, :prec, :id)
8
+ # @!attribute [rw] label
9
+ # The label (or left-hand side) of the production. This
10
+ # should be a nonterminal.
11
+ #
12
+ # @return [Symbol]
13
+ # @!attribute [rw] items
14
+ # The body (or right-hand side) of the production. This can
15
+ # be array of terminals and nonterminals.
16
+ #
17
+ # @return [Array<Token>]
18
+ # @!attribute [rw] block
19
+ # The block of code to be executed when the production's right
20
+ # hand side is reduced.
21
+ #
22
+ # @return [String]
23
+ # @!attribute [rw] prec
24
+ # The precedence declaration for the production.
25
+ #
26
+ # @return [Ace::Precedence]
27
+ # @!attribute [rw] id
28
+ # The ID of the production. The starting production always
29
+ # has an ID of 0.
30
+ #
31
+ # @return [Numeric]
32
+
33
+ # Creates a new production from a hash. The hash's keys
34
+ # correspond to the attributes on this class.
35
+ #
36
+ # @param hash [Hash<(Symbol, Object)>]
37
+ def self.from_hash(hash)
38
+ new(hash[:label] || hash["label"],
39
+ hash[:items] || hash["items"],
40
+ hash[:block] || hash["block"],
41
+ hash[:prec] || hash["prec"],
42
+ hash[:id] || hash["id"])
43
+ end
44
+
45
+ # Create a new version of the production with duplicated values.
46
+ #
47
+ # @return [Production]
48
+ def clone
49
+ Production.new(label.dup,
50
+ items.map(&:dup),
51
+ block.dup,
52
+ prec.dup,
53
+ id)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,57 +1,57 @@
1
- module Antelope
2
- module Ace
3
- class Scanner
4
-
5
- # Represents an argument to a directive. It encapsulates a
6
- # string object, which is the value of the argument.
7
- class Argument < String
8
-
9
- # Initialize the argument.
10
- #
11
- # @param type [Symbol] the type of argument it is; it can be
12
- # a `:block`, `:text`, or `:caret`. The type is defined by
13
- # the encapsulating characters. If the encapsulating
14
- # characters are `{` and `}`, it's a `:block`; if they are
15
- # `<` and `>`, it's a `:caret`; otherwise, it's a `:text`.
16
- # @param value [String] the value of the argument.
17
- def initialize(type, value)
18
- @type = type
19
- super(value)
20
- end
21
-
22
- # If this argument is type `:block`.
23
- #
24
- # @return [Boolean]
25
- # @see type?
26
- def block?
27
- type? :block
28
- end
29
-
30
- # If this argument is type `:text`.
31
- #
32
- # @return [Boolean]
33
- # @see type?
34
- def text?
35
- type? :text
36
- end
37
-
38
- # If this argument is type `:caret`.
39
- #
40
- # @return [Boolean]
41
- # @see type?
42
- def caret?
43
- type? :caret
44
- end
45
-
46
- # Checks to see if any of the given arguments match the type
47
- # of this argument.
48
- #
49
- # @param inc [Array<Symbol>]
50
- # @return [Boolean]
51
- def type?(*inc)
52
- inc.include?(@type)
53
- end
54
- end
55
- end
56
- end
57
- end
1
+ module Antelope
2
+ module Ace
3
+ class Scanner
4
+
5
+ # Represents an argument to a directive. It encapsulates a
6
+ # string object, which is the value of the argument.
7
+ class Argument < String
8
+
9
+ # Initialize the argument.
10
+ #
11
+ # @param type [Symbol] the type of argument it is; it can be
12
+ # a `:block`, `:text`, or `:caret`. The type is defined by
13
+ # the encapsulating characters. If the encapsulating
14
+ # characters are `{` and `}`, it's a `:block`; if they are
15
+ # `<` and `>`, it's a `:caret`; otherwise, it's a `:text`.
16
+ # @param value [String] the value of the argument.
17
+ def initialize(type, value)
18
+ @type = type
19
+ super(value)
20
+ end
21
+
22
+ # If this argument is type `:block`.
23
+ #
24
+ # @return [Boolean]
25
+ # @see type?
26
+ def block?
27
+ type? :block
28
+ end
29
+
30
+ # If this argument is type `:text`.
31
+ #
32
+ # @return [Boolean]
33
+ # @see type?
34
+ def text?
35
+ type? :text
36
+ end
37
+
38
+ # If this argument is type `:caret`.
39
+ #
40
+ # @return [Boolean]
41
+ # @see type?
42
+ def caret?
43
+ type? :caret
44
+ end
45
+
46
+ # Checks to see if any of the given arguments match the type
47
+ # of this argument.
48
+ #
49
+ # @param inc [Array<Symbol>]
50
+ # @return [Boolean]
51
+ def type?(*inc)
52
+ inc.include?(@type)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,89 +1,89 @@
1
- # encoding: utf-8
2
-
3
- module Antelope
4
- module Ace
5
- class Scanner
6
-
7
- # Scans the first section of the file. This contains directives and
8
- # small blocks that can be copied directly into the body of the output.
9
- # The blocks are formatted as `%{ ... %}`; however, the ending tag _must_
10
- # be on its own line. The directive is formatted as `%<name> <value>`,
11
- # with `<name>` being the key, and `<value>` being the value. The value
12
- # can be a piece of straight-up text (no quotes), or it can be quoted.
13
- # There can be any number of values to a directive.
14
- module First
15
-
16
- # Scans until the first content boundry. If it encounters anything but
17
- # a block or a directive (or whitespace), it will raise an error.
18
- #
19
- # @raise [SyntaxError] if it encounters anything but whitespace, a
20
- # block, or a directive.
21
- # @return [void]
22
- def scan_first_part
23
- until @scanner.check(CONTENT_BOUNDRY)
24
- scan_first_copy || scan_first_directive ||
25
- scan_whitespace || error!
26
- end
27
- end
28
-
29
- # Scans for a block. It is called `copy` instead of `block` because
30
- # contents of the block is _copied_ directly into the body.
31
- #
32
- # @return [Boolean] if it matched.
33
- def scan_first_copy
34
- if @scanner.scan(/%{([\s\S]+?)\n\s*%}/)
35
- tokens << [:copy, @scanner[1]]
36
- end
37
- end
38
-
39
- # Scans a directive. A directive has one _name_, and any number of
40
- # arguments. Every argument is a _value_. The name can be any
41
- # combinations of alphabetical characters, underscores, and dashes;
42
- # the value can be word characters, or a quote-delimited string.
43
- # It emits a `:directive` token with the directive (Sring) as an
44
- # argument, and the passed arguments (Array<String>).
45
- #
46
- # @return [Boolean] if it matched.
47
- def scan_first_directive
48
- if @scanner.scan(/%(#{IDENTIFIER}) ?/)
49
- directive = @scanner[1]
50
- arguments = scan_first_directive_arguments
51
-
52
- tokens << [:directive, directive, arguments]
53
- end
54
- end
55
-
56
- # Scan the arguments for a directive. It keeps attempting to
57
- # scan arguments until the first newline that was not in a
58
- # block. Arguments can be blocks, carets, or text; blocks are
59
- # encapsulated with `{` and `}`, carets are encapsulated with
60
- # `<` and `>`, and text is encapsulated with quotes or
61
- # nothing.
62
- #
63
- # @return [Array<Argument>]
64
- def scan_first_directive_arguments
65
- arguments = []
66
- until @scanner.check(/\n/)
67
- if @scanner.scan(/\{/)
68
- argument =
69
- Argument.new(:block, _scan_block[1..-2])
70
- elsif @scanner.scan(/</)
71
- @scanner.scan(/((?:\\>|[^>])*)\>/)
72
- argument =
73
- Argument.new(:caret, @scanner[1])
74
- else
75
- @scanner.scan(/#{VALUE}/x) or error!
76
- argument = Argument.new(:text,
77
- @scanner[2] || @scanner[3])
78
- end
79
-
80
- arguments.push(argument)
81
- @scanner.scan(/ */)
82
- end
83
-
84
- arguments
85
- end
86
- end
87
- end
88
- end
89
- end
1
+ # encoding: utf-8
2
+
3
+ module Antelope
4
+ module Ace
5
+ class Scanner
6
+
7
+ # Scans the first section of the file. This contains directives and
8
+ # small blocks that can be copied directly into the body of the output.
9
+ # The blocks are formatted as `%{ ... %}`; however, the ending tag _must_
10
+ # be on its own line. The directive is formatted as `%<name> <value>`,
11
+ # with `<name>` being the key, and `<value>` being the value. The value
12
+ # can be a piece of straight-up text (no quotes), or it can be quoted.
13
+ # There can be any number of values to a directive.
14
+ module First
15
+
16
+ # Scans until the first content boundry. If it encounters anything but
17
+ # a block or a directive (or whitespace), it will raise an error.
18
+ #
19
+ # @raise [SyntaxError] if it encounters anything but whitespace, a
20
+ # block, or a directive.
21
+ # @return [void]
22
+ def scan_first_part
23
+ until @scanner.check(CONTENT_BOUNDRY)
24
+ scan_first_copy || scan_first_directive ||
25
+ scan_whitespace || error!
26
+ end
27
+ end
28
+
29
+ # Scans for a block. It is called `copy` instead of `block` because
30
+ # contents of the block is _copied_ directly into the body.
31
+ #
32
+ # @return [Boolean] if it matched.
33
+ def scan_first_copy
34
+ if @scanner.scan(/%{([\s\S]+?)\n\s*%}/)
35
+ tokens << [:copy, @scanner[1]]
36
+ end
37
+ end
38
+
39
+ # Scans a directive. A directive has one _name_, and any number of
40
+ # arguments. Every argument is a _value_. The name can be any
41
+ # combinations of alphabetical characters, underscores, and dashes;
42
+ # the value can be word characters, or a quote-delimited string.
43
+ # It emits a `:directive` token with the directive (Sring) as an
44
+ # argument, and the passed arguments (Array<String>).
45
+ #
46
+ # @return [Boolean] if it matched.
47
+ def scan_first_directive
48
+ if @scanner.scan(/%(#{IDENTIFIER}) ?/)
49
+ directive = @scanner[1]
50
+ arguments = scan_first_directive_arguments
51
+
52
+ tokens << [:directive, directive, arguments]
53
+ end
54
+ end
55
+
56
+ # Scan the arguments for a directive. It keeps attempting to
57
+ # scan arguments until the first newline that was not in a
58
+ # block. Arguments can be blocks, carets, or text; blocks are
59
+ # encapsulated with `{` and `}`, carets are encapsulated with
60
+ # `<` and `>`, and text is encapsulated with quotes or
61
+ # nothing.
62
+ #
63
+ # @return [Array<Argument>]
64
+ def scan_first_directive_arguments
65
+ arguments = []
66
+ until @scanner.check(/\n/)
67
+ if @scanner.scan(/\{/)
68
+ argument =
69
+ Argument.new(:block, _scan_block[1..-2])
70
+ elsif @scanner.scan(/</)
71
+ @scanner.scan(/((?:\\>|[^>])*)\>/)
72
+ argument =
73
+ Argument.new(:caret, @scanner[1])
74
+ else
75
+ @scanner.scan(/#{VALUE}/x) or error!
76
+ argument = Argument.new(:text,
77
+ @scanner[2] || @scanner[3])
78
+ end
79
+
80
+ arguments.push(argument)
81
+ @scanner.scan(/ */)
82
+ end
83
+
84
+ arguments
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end