-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
ebnf
executable file
·113 lines (102 loc) · 4.29 KB
/
ebnf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env ruby
# ebnf --- Process EBNF to generate the following:
# * S-Expression
# * Turtle
# * Either of the above, transformed to BNF
# * And with First/Follow rules
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", 'lib')))
require "bundler/setup"
require 'rubygems'
require 'getoptlong'
require 'ebnf'
options = {
output_format: :sxp,
prefix: "ttl",
namespace: "http://www.w3.org/ns/formats/Turtle#",
level: 4
}
input, out = nil, STDOUT
OPT_ARGS = [
["--debug", GetoptLong::NO_ARGUMENT, "Turn on debugging output"],
["--bnf", GetoptLong::NO_ARGUMENT, "Transform EBNF to BNF"],
["--evaluate","-e", GetoptLong::REQUIRED_ARGUMENT,"Evaluate argument as an EBNF document"],
["--format", "-f", GetoptLong::REQUIRED_ARGUMENT,"Specify output format one of abnf, abnfh, ebnf, html, isoebnf, isoebnfh, ttl, sxp, or rb"],
["--input-format", GetoptLong::REQUIRED_ARGUMENT,"Specify input format one of abnf, ebnf isoebnf, native, or sxp"],
["--ll1", GetoptLong::REQUIRED_ARGUMENT,"Generate First/Follow rules, argument is start symbol"],
["--mod-name", GetoptLong::REQUIRED_ARGUMENT,"Module name used when creating ruby tables"],
["--namespace", "-n", GetoptLong::REQUIRED_ARGUMENT,"Namespace to use when generating Turtle"],
["--output", "-o", GetoptLong::REQUIRED_ARGUMENT,"Output to the specified file path"],
["--peg", GetoptLong::NO_ARGUMENT, "Transform EBNF to PEG"],
["--prefix", "-p", GetoptLong::REQUIRED_ARGUMENT,"Prefix to use when generating Turtle"],
["--progress", "-v", GetoptLong::NO_ARGUMENT, "Detail on execution"],
["--renumber", GetoptLong::NO_ARGUMENT, "Renumber parsed reules"],
["--validate", GetoptLong::NO_ARGUMENT, "Validate grammar and any generated HTML"],
["--help", "-?", GetoptLong::NO_ARGUMENT, "This message"]
]
def usage
STDERR.puts %{#{$0} Version #{EBNF::VERSION}}
STDERR.puts %{Usage: #{$0} [options] file ...}
width = OPT_ARGS.map do |o|
l = o.first.length
l += o[1].length + 2 if o[1].is_a?(String)
l
end.max
OPT_ARGS.each do |o|
s = " %-*s " % [width, (o[1].is_a?(String) ? "#{o[0,2].join(', ')}" : o[0])]
s += o.last
STDERR.puts s
end
exit(1)
end
opts = GetoptLong.new(*OPT_ARGS.map {|o| o[0..-2]})
opts.each do |opt, arg|
case opt
when '--debug' then options[:level] = 0
when '--bnf' then options[:bnf] = true
when '--evaluate' then input = arg
when '--input-format'
unless %w(abnf ebnf isoebnf native sxp).include?(arg)
STDERR.puts("unrecognized input format #{arg}")
usage
end
options[:format] = arg.to_sym
when '--format'
unless %w(abnf abnfh ebnf html isoebnf isoebnfh rb sxp ttl).include?(arg)
STDERR.puts("unrecognized output format #{arg}")
usage
end
options[:output_format] = arg.to_sym
when '--ll1' then (options[:ll1] ||= []) << arg.to_sym
when '--mod-name' then options[:mod_name] = arg
when '--output' then out = File.open(arg, "w")
when '--peg' then options[:peg] = true
when '--prefix' then options[:prefix] = arg
when '--renumber' then options[:renumber] = true
when '--namespace' then options[:namespace] = arg
when '--progress' then options[:level] = 1 unless options[:level] == 0
when '--validate' then options[:validate] = true
when '--help' then usage
end
end
input = File.open(ARGV[0]) if ARGV[0]
ebnf = EBNF.parse(input || STDIN, **options)
ebnf.make_bnf if options[:bnf] || options[:ll1]
ebnf.make_peg if options[:peg]
if options[:ll1]
ebnf.first_follow(*options[:ll1])
ebnf.build_tables
end
ebnf.renumber! if options[:renumber]
res = case options[:output_format]
when :abnf then ebnf.to_s(format: :abnf)
when :abnfh then ebnf.to_html(format: :abnf, validate: options[:validate])
when :ebnf then ebnf.to_s
when :html then ebnf.to_html(validate: options[:validate])
when :isoebnf then ebnf.to_s(format: :isoebnf)
when :isoebnfh then ebnf.to_html(format: :isoebnf, validate: options[:validate])
when :sxp then ebnf.to_sxp
when :ttl then ebnf.to_ttl(options[:prefix], options[:namespace])
when :rb then ebnf.to_ruby(out, grammarFile: ARGV[0], **options)
else ebnf.ast.inspect
end
out.puts res