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,53 +0,0 @@
1
- Productions:
2
- %len = grammar.all_productions.size.to_s.size
3
- %productions = recognizer.states.map(&:rules).inject(:merge).
4
- % select(&:final?).map { |x| [x.to_s(false), x.production.block] }
5
- %body = productions.map { |_| _[0].size }.max
6
- %productions.each do |prod|
7
- {{= sprintf("%-#{body}s", prod[0]) }} %{prod[1]}
8
- %end
9
-
10
- %if unused_symbols.any?
11
- Symbols unused in grammar:
12
- % unused_symbols.each do |sym|
13
- %{sym}
14
- % end
15
- %end
16
-
17
- Precedence:
18
- --- highest
19
- % grammar.precedence.each do |pr|
20
- %{"%-8s" % pr.type} %{pr.level}:
21
- {{= "{" << pr.tokens.to_a.join(", ") << "}" }}
22
- % end
23
- --- lowest
24
-
25
- %states = grammar.states.to_a
26
- %table.each_with_index do |v, i|
27
- % state = states[i]
28
- State %{i}:
29
- % state.rules.each do |rule|
30
- %{rule}
31
- {%{rule.lookahead.to_a.join(", ")}}
32
- % end
33
- % transitions = v.each.select { |_, a| a && a[0] == :state }
34
- % reductions = v.each.select { |_, a| a && a[0] == :reduce}
35
- % accepting = v.each.select { |_, a| a && a[0] == :accept}
36
- % thing = [:transitions, :reductions, :accepting]
37
- % num_type = {
38
- % transitions: "State",
39
- % reductions: "Rule",
40
- % accepting: "Rule"
41
- % }
42
- % h = Hash[thing.zip([transitions, reductions, accepting])]
43
- % h.each do |key, value|
44
- % next unless value.any?
45
- %{key}:
46
- % value.each do |token, (_, name)|
47
- % token_value = grammar.terminals.
48
- % find { |_| _.name == token } || token
49
- %{token_value}: %{num_type[key]} %{name}
50
- % end
51
- % end
52
-
53
- %end
@@ -1,78 +0,0 @@
1
- module Antelope
2
- class Template
3
- class Compiler
4
-
5
- attr_reader :buffer
6
-
7
- attr_reader :tokens
8
-
9
- def initialize(tokens, buffer_variable = "_out")
10
- @tokens = tokens.dup
11
- @buffer = ""
12
- @buffer_variable = buffer_variable
13
- end
14
-
15
- def compile
16
- merge_text_tokens
17
-
18
- @buffer = "\# encoding: utf-8\n#{@buffer_variable} ||= \"\"\n"
19
-
20
- until @tokens.empty?
21
- token = @tokens.shift
22
- parse_method = "parse_#{token[0]}".intern
23
-
24
- send(parse_method, token[1])
25
- end
26
-
27
- @buffer << "#{@buffer_variable}\n"
28
-
29
- @buffer
30
-
31
- rescue NoMethodError => e
32
-
33
- if e.name == parse_method
34
- raise NoTokenError, "No token #{token[0]} exists"
35
- else
36
- raise
37
- end
38
- end
39
-
40
- private
41
-
42
- def parse_text(value)
43
- buffer << "#{@buffer_variable} << #{value.to_s.inspect}\n"
44
- end
45
-
46
- def parse_tag(value)
47
- value.gsub!(/\A([\s\S]*?)\s*\Z/, "\\1")
48
- buffer << "#{value}\n"
49
- end
50
-
51
- def parse_output_tag(value)
52
- value.gsub!(/\A\s*([\s\S]*?)\s*\Z/, "\\1")
53
- buffer << "#{@buffer_variable} << begin\n " \
54
- "#{value}\nend.to_s\n"
55
- end
56
-
57
- def parse_newline(_)
58
- parse_text("\n")
59
- end
60
-
61
- def parse_comment_tag(_)
62
- end
63
-
64
- def merge_text_tokens
65
- new_tokens = []
66
- @tokens.chunk(&:first).each do |type, tokens|
67
- if type == :text
68
- new_tokens << [:text, tokens.map(&:last).join('')]
69
- else
70
- new_tokens.push(*tokens)
71
- end
72
- end
73
-
74
- @tokens = new_tokens
75
- end
76
- end
77
- end
78
- end
@@ -1,9 +0,0 @@
1
- module Antelope
2
- class Template
3
- class Error < Antelope::Error; end
4
-
5
- class SyntaxError < Error; end
6
-
7
- class NoTokenError < Error; end
8
- end
9
- end
@@ -1,109 +0,0 @@
1
- require 'strscan'
2
-
3
- module Antelope
4
- class Template
5
- class Scanner
6
- attr_reader :scanner
7
-
8
- attr_reader :tokens
9
-
10
- def initialize(input, source = "(template)")
11
- @scanner = StringScanner.new(input)
12
- @source = source
13
- @tokens = nil
14
- @line = 1
15
- end
16
-
17
- def scan
18
-
19
- @tokens ||= begin
20
- @tokens = []
21
- @line = 1
22
- @scanner.pos = 0
23
- until @scanner.eos?
24
- scan_tag || scan_until_tag || scan_until_end
25
- end
26
-
27
- @tokens
28
- end
29
-
30
- rescue SyntaxError => e
31
- start = [@scanner.pos - 8, 0].max
32
- stop = [@scanner.pos + 8, @scanner.string.length].min
33
- snip = @scanner.string[start..stop].inspect
34
- char = @scanner.string[@scanner.pos]
35
- char = if char
36
- char.inspect
37
- else
38
- "EOF"
39
- end
40
-
41
- new_line = "#{@source}:#{@line}:#{@scanner.pos}: "\
42
- "unexpected #{char} (near #{snip})"
43
-
44
- raise e, e.message, [new_line, *e.backtrace]
45
- end
46
-
47
- private
48
-
49
- def scan_until_tag
50
- case
51
- when value = @scanner.scan_until(/(\%|\{|\}|\\|\n)/)
52
- @scanner.pos -= 1
53
- tokens << [:text, value[0..-2]]
54
- end
55
- end
56
-
57
- def scan_until_end
58
- tokens << [:text, @scanner.scan(/.+/m)]
59
- end
60
-
61
- def scan_tag
62
- case
63
- when @scanner.scan(/\\(\{\{|\}\}|\%)/)
64
- tokens << [:text, @scanner[1]]
65
- when @scanner.scan(/\%\%/)
66
- tokens << [:text, "%"]
67
- when @scanner.scan(/\n?\%\{/)
68
- update_line
69
- scan_tag_start(:output_tag, /\}/)
70
- when @scanner.scan(/(\n|\A)\%/)
71
- update_line
72
- #tokens << [:tag]
73
- scan_tag_start(:tag, /\n/)
74
- @scanner.pos -= 1
75
- when @scanner.scan(/\n?\{\{=/)
76
- update_line
77
- scan_tag_start(:output_tag)
78
- when @scanner.scan(/\n?\{\{!/)
79
- update_line
80
- scan_tag_start(:comment_tag)
81
- when @scanner.scan(/\n?\{\{/)
82
- update_line
83
- scan_tag_start(:tag)
84
- when @scanner.scan(/\}\}/)
85
- @scanner.pos -= 2
86
- error!
87
- when @scanner.scan(/\{|\}|\%|\\|\n/)
88
- tokens << [:text, @scanner[0]]
89
- else
90
- false
91
- end
92
- end
93
-
94
- def scan_tag_start(type, ending = /\}\}/)
95
- value = @scanner.scan_until(ending) or error!
96
- tokens << [type, value[0..-(@scanner[0].length + 1)]]
97
- end
98
-
99
- def error!
100
- raise SyntaxError, "invalid syntax"
101
- end
102
-
103
- def update_line
104
- @line += @scanner[0].count("\n")
105
- end
106
-
107
- end
108
- end
109
- end
@@ -1,64 +0,0 @@
1
- require "antelope/template/errors"
2
- require "antelope/template/scanner"
3
- require "antelope/template/compiler"
4
-
5
-
6
- module Antelope
7
- class Template
8
-
9
- NO_SOURCE = Object.new
10
-
11
-
12
- def initialize(input, source = NO_SOURCE)
13
- @input = normalize_input(input)
14
- @source = determine_source(input, source)
15
- end
16
-
17
- def parse
18
- @result ||= begin
19
- scanner = Scanner.new(@input, @source)
20
- compiler = Compiler.new(scanner.scan)
21
- compiler.compile
22
- end
23
- end
24
-
25
- def result(binding = TOPLEVEL_BINDING.dup)
26
- eval(parse, binding, fake_name, 0)
27
- end
28
-
29
- alias_method :run, :result
30
- alias_method :call, :result
31
-
32
- private
33
-
34
- def normalize_input(input)
35
- case
36
- when String === input
37
- input
38
- when input.respond_to?(:read)
39
- input.read
40
- when input.respond_to?(:open)
41
- input.open("r") { |f| f.read }
42
- else
43
- raise ArgumentError, "Received #{input.class}, expected " \
44
- "#{String}, #read"
45
- end
46
- end
47
-
48
- def determine_source(input, source)
49
- case
50
- when source != NO_SOURCE
51
- source
52
- when input.respond_to?(:to_path)
53
- input.to_path
54
- else
55
- "(template)"
56
- end
57
- end
58
-
59
- def fake_name
60
- File.join(File.dirname(@source),
61
- "_#{File.basename(@source, '.*')}.rb")
62
- end
63
- end
64
- end
@@ -1,50 +0,0 @@
1
- describe Template do
2
-
3
- let(:content) { "hello {{ world }} test" }
4
-
5
- subject { Template.new(content) }
6
-
7
- it "generates ruby code" do
8
- expect(subject.parse).to eq %Q(# encoding: utf-8\n_out ||= ""\n_out << "hello "\n world\n_out << " test"\n_out\n)
9
- end
10
-
11
- context "when the tag is on its own line" do
12
-
13
- let :content do
14
- <<-TEST
15
- hello
16
- {{= something }}
17
- world
18
-
19
- {{ thing }}
20
- a
21
-
22
- TEST
23
- end
24
-
25
- it "removes surrounding whitespace" do
26
- expect(subject.parse).to eq <<-TEST
27
- # encoding: utf-8
28
- _out ||= ""
29
- _out << "hello"
30
- _out << begin
31
- something
32
- end.to_s
33
- _out << "\\nworld\\n"
34
- thing
35
- _out << "\\na\\n\\n"
36
- _out
37
- TEST
38
- end
39
-
40
- it "runs in ruby" do
41
- object = Object.new
42
- result = nil
43
- def object.something; "-" end
44
- def object.thing; end
45
-
46
- expect { result = object.instance_eval(subject.parse) }.to_not raise_error
47
- expect(result).to eq "hello-\nworld\n\na\n\n"
48
- end
49
- end
50
- end