wlang 0.10.2 → 2.0.0.beta
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.
- data/CHANGELOG.md +3 -121
- data/Gemfile +23 -1
- data/Gemfile.lock +32 -28
- data/LICENCE.md +18 -21
- data/Manifest.txt +4 -5
- data/README.md +100 -174
- data/Rakefile +1 -13
- data/bin/wlang +3 -29
- data/lib/wlang.rb +21 -394
- data/lib/wlang/command.rb +94 -0
- data/lib/wlang/compiler.rb +78 -0
- data/lib/wlang/compiler/autospacing.rb +60 -0
- data/lib/wlang/compiler/dialect_enforcer.rb +91 -0
- data/lib/wlang/compiler/filter.rb +32 -0
- data/lib/wlang/compiler/grammar.citrus +67 -0
- data/lib/wlang/compiler/parser.rb +26 -0
- data/lib/wlang/compiler/proc_call_removal.rb +15 -0
- data/lib/wlang/compiler/static_merger.rb +28 -0
- data/lib/wlang/compiler/strconcat_flattener.rb +25 -0
- data/lib/wlang/compiler/to_ruby_abstraction.rb +22 -0
- data/lib/wlang/compiler/to_ruby_code.rb +55 -0
- data/lib/wlang/dialect.rb +40 -237
- data/lib/wlang/dialect/dispatching.rb +51 -0
- data/lib/wlang/dialect/evaluation.rb +30 -0
- data/lib/wlang/dialect/tags.rb +50 -0
- data/lib/wlang/dummy.rb +32 -0
- data/lib/wlang/html.rb +106 -0
- data/lib/wlang/loader.rb +6 -0
- data/lib/wlang/mustang.rb +90 -0
- data/lib/wlang/scope.rb +57 -0
- data/lib/wlang/scope/binding_scope.rb +18 -0
- data/lib/wlang/scope/object_scope.rb +25 -0
- data/lib/wlang/scope/proxy_scope.rb +18 -0
- data/lib/wlang/scope/root_scope.rb +24 -0
- data/lib/wlang/template.rb +16 -86
- data/lib/wlang/version.rb +9 -8
- data/spec/fixtures/dialect/foobar.rb +31 -0
- data/spec/fixtures/dialect/upcasing.rb +13 -0
- data/spec/fixtures/templates/hello.tpl +1 -0
- data/spec/integration/examples/1-basics.txt +65 -0
- data/spec/integration/examples/2-imperative.txt +51 -0
- data/spec/integration/examples/3-partials.txt +76 -0
- data/spec/integration/examples/4-recursion.txt +16 -0
- data/spec/integration/html/test_ampersand.rb +15 -0
- data/spec/integration/html/test_bang.rb +38 -0
- data/spec/integration/html/test_caret.rb +33 -0
- data/spec/integration/html/test_dollar.rb +16 -0
- data/spec/integration/html/test_greater.rb +23 -0
- data/spec/integration/html/test_modulo.rb +16 -0
- data/spec/integration/html/test_plus.rb +48 -0
- data/spec/integration/html/test_question.rb +33 -0
- data/spec/integration/html/test_sharp.rb +21 -0
- data/spec/integration/html/test_slash.rb +16 -0
- data/spec/integration/html/test_star.rb +37 -0
- data/spec/integration/test_dummy.rb +51 -0
- data/spec/integration/test_examples.rb +29 -0
- data/spec/integration/test_mustang.rb +120 -0
- data/spec/integration/test_readme.rb +56 -0
- data/spec/integration/test_upcasing.rb +22 -0
- data/spec/spec_helper.rb +62 -1
- data/spec/test_wlang.rb +101 -0
- data/spec/unit/compiler/autospacing/test_right_strip.rb +30 -0
- data/spec/unit/compiler/autospacing/test_unindent.rb +30 -0
- data/spec/unit/compiler/test_dialect_enforcer.rb +168 -0
- data/spec/unit/compiler/test_grammar.rb +207 -0
- data/spec/unit/compiler/test_parser.rb +69 -0
- data/spec/unit/compiler/test_proc_call_removal.rb +24 -0
- data/spec/unit/compiler/test_static_merger.rb +29 -0
- data/spec/unit/compiler/test_strconcat_flattener.rb +30 -0
- data/spec/unit/compiler/test_to_ruby_abstraction.rb +59 -0
- data/spec/unit/compiler/test_to_ruby_code.rb +24 -0
- data/spec/unit/dialect/test_compile.rb +52 -0
- data/spec/unit/dialect/test_dispatching.rb +19 -0
- data/spec/unit/dialect/test_evaluate.rb +41 -0
- data/spec/unit/dialect/test_render.rb +33 -0
- data/spec/unit/dialect/test_tags.rb +32 -0
- data/spec/unit/dialect/test_with_scope.rb +18 -0
- data/spec/unit/scope/test_binding_scope.rb +27 -0
- data/spec/unit/scope/test_coerce.rb +22 -0
- data/spec/unit/scope/test_object_scope.rb +38 -0
- data/spec/unit/scope/test_proxy_scope.rb +22 -0
- data/spec/unit/scope/test_root_scope.rb +22 -0
- data/spec/unit/test_assumptions.rb +29 -0
- data/spec/unit/test_scope.rb +57 -0
- data/tasks/debug_mail.rake +42 -45
- data/tasks/gem.rake +22 -17
- data/tasks/spec_test.rake +9 -17
- data/tasks/unit_test.rake +11 -12
- data/tasks/yard.rake +13 -13
- data/wlang.gemspec +36 -32
- data/wlang.noespec +27 -35
- metadata +268 -451
- data/doc/specification/about.rdoc +0 -61
- data/doc/specification/analytics.wtpl +0 -13
- data/doc/specification/dialect.wtpl +0 -14
- data/doc/specification/dialects.wtpl +0 -3
- data/doc/specification/examples.rb +0 -3
- data/doc/specification/glossary.wtpl +0 -14
- data/doc/specification/hosting.rdoc +0 -0
- data/doc/specification/overview.rdoc +0 -116
- data/doc/specification/rulesets.wtpl +0 -87
- data/doc/specification/specification.css +0 -53
- data/doc/specification/specification.html +0 -1690
- data/doc/specification/specification.js +0 -8
- data/doc/specification/specification.wtpl +0 -42
- data/doc/specification/specification.yml +0 -432
- data/doc/specification/symbols.wtpl +0 -16
- data/lib/wlang/dialect_dsl.rb +0 -141
- data/lib/wlang/dialect_loader.rb +0 -74
- data/lib/wlang/dialects/bluecloth_dialect.rb +0 -16
- data/lib/wlang/dialects/coderay_dialect.rb +0 -45
- data/lib/wlang/dialects/hosted_dialect.rb +0 -50
- data/lib/wlang/dialects/plain_text_dialect.rb +0 -69
- data/lib/wlang/dialects/rdoc_dialect.rb +0 -33
- data/lib/wlang/dialects/redcloth_dialect.rb +0 -16
- data/lib/wlang/dialects/ruby_dialect.rb +0 -118
- data/lib/wlang/dialects/sql_dialect.rb +0 -38
- data/lib/wlang/dialects/standard_dialects.rb +0 -181
- data/lib/wlang/dialects/xhtml_dialect.rb +0 -63
- data/lib/wlang/dialects/yaml_dialect.rb +0 -30
- data/lib/wlang/encoder.rb +0 -62
- data/lib/wlang/encoder_set.rb +0 -122
- data/lib/wlang/errors.rb +0 -80
- data/lib/wlang/ext/hash_methodize.rb +0 -13
- data/lib/wlang/ext/string.rb +0 -44
- data/lib/wlang/hash_scope.rb +0 -89
- data/lib/wlang/hosted_language.rb +0 -146
- data/lib/wlang/intelligent_buffer.rb +0 -94
- data/lib/wlang/parser.rb +0 -332
- data/lib/wlang/parser_state.rb +0 -94
- data/lib/wlang/rule.rb +0 -66
- data/lib/wlang/rule_set.rb +0 -106
- data/lib/wlang/rulesets/basic_ruleset.rb +0 -83
- data/lib/wlang/rulesets/buffering_ruleset.rb +0 -115
- data/lib/wlang/rulesets/context_ruleset.rb +0 -111
- data/lib/wlang/rulesets/encoding_ruleset.rb +0 -73
- data/lib/wlang/rulesets/imperative_ruleset.rb +0 -132
- data/lib/wlang/rulesets/ruleset_utils.rb +0 -317
- data/lib/wlang/wlang_command.rb +0 -51
- data/lib/wlang/wlang_command_options.rb +0 -163
- data/spec/basic_object.spec +0 -40
- data/spec/coderay_dialect.spec +0 -8
- data/spec/dialect/apply_post_transform.spec +0 -16
- data/spec/global_extensions.rb +0 -2
- data/spec/hash_scope.spec +0 -76
- data/spec/redcloth_dialect.spec +0 -24
- data/spec/test_all.rb +0 -8
- data/spec/wlang.spec +0 -53
- data/spec/wlang_spec.rb +0 -8
- data/spec/xhtml_dialect.spec +0 -22
- data/tasks/genspec.rake +0 -5
- data/test/blackbox/basic/execution_1.exp +0 -1
- data/test/blackbox/basic/execution_1.tpl +0 -1
- data/test/blackbox/basic/execution_2.exp +0 -1
- data/test/blackbox/basic/execution_2.tpl +0 -1
- data/test/blackbox/basic/execution_3.exp +0 -1
- data/test/blackbox/basic/execution_3.tpl +0 -1
- data/test/blackbox/basic/execution_4.exp +0 -1
- data/test/blackbox/basic/execution_4.tpl +0 -1
- data/test/blackbox/basic/inclusion_1.exp +0 -1
- data/test/blackbox/basic/inclusion_1.tpl +0 -1
- data/test/blackbox/basic/inclusion_2.exp +0 -1
- data/test/blackbox/basic/inclusion_2.tpl +0 -1
- data/test/blackbox/basic/injection_1.exp +0 -1
- data/test/blackbox/basic/injection_1.tpl +0 -1
- data/test/blackbox/basic/injection_2.exp +0 -1
- data/test/blackbox/basic/injection_2.tpl +0 -1
- data/test/blackbox/basic/modulation_1.exp +0 -1
- data/test/blackbox/basic/modulation_1.tpl +0 -1
- data/test/blackbox/basic/modulation_2.exp +0 -1
- data/test/blackbox/basic/modulation_2.tpl +0 -1
- data/test/blackbox/basic/recursive_app_1.exp +0 -1
- data/test/blackbox/basic/recursive_app_1.tpl +0 -1
- data/test/blackbox/basic/recursive_app_2.exp +0 -1
- data/test/blackbox/basic/recursive_app_2.tpl +0 -1
- data/test/blackbox/buffering/data_1.rb +0 -1
- data/test/blackbox/buffering/data_assignment_1.exp +0 -1
- data/test/blackbox/buffering/data_assignment_1.tpl +0 -1
- data/test/blackbox/buffering/data_assignment_2.exp +0 -1
- data/test/blackbox/buffering/data_assignment_2.tpl +0 -1
- data/test/blackbox/buffering/data_assignment_3.exp +0 -1
- data/test/blackbox/buffering/data_assignment_3.tpl +0 -1
- data/test/blackbox/buffering/data_assignment_4.exp +0 -1
- data/test/blackbox/buffering/data_assignment_4.tpl +0 -1
- data/test/blackbox/buffering/input_1.exp +0 -1
- data/test/blackbox/buffering/input_1.tpl +0 -1
- data/test/blackbox/buffering/input_2.exp +0 -1
- data/test/blackbox/buffering/input_2.tpl +0 -1
- data/test/blackbox/buffering/input_3.exp +0 -1
- data/test/blackbox/buffering/input_3.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion.exp +0 -1
- data/test/blackbox/buffering/input_inclusion.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_1.exp +0 -0
- data/test/blackbox/buffering/input_inclusion_1.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_2.exp +0 -1
- data/test/blackbox/buffering/input_inclusion_2.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_3.exp +0 -1
- data/test/blackbox/buffering/input_inclusion_3.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_4.exp +0 -0
- data/test/blackbox/buffering/input_inclusion_4.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_5.exp +0 -1
- data/test/blackbox/buffering/input_inclusion_5.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_6.exp +0 -1
- data/test/blackbox/buffering/input_inclusion_6.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_7.exp +0 -0
- data/test/blackbox/buffering/input_inclusion_7.tpl +0 -1
- data/test/blackbox/buffering/text_1.txt +0 -1
- data/test/blackbox/buffering/wlang.txt +0 -1
- data/test/blackbox/context/assignment_1.exp +0 -1
- data/test/blackbox/context/assignment_1.tpl +0 -1
- data/test/blackbox/context/assignment_2.exp +0 -1
- data/test/blackbox/context/assignment_2.tpl +0 -1
- data/test/blackbox/context/assignment_3.exp +0 -2
- data/test/blackbox/context/assignment_3.tpl +0 -2
- data/test/blackbox/context/assignment_4.exp +0 -1
- data/test/blackbox/context/assignment_4.tpl +0 -1
- data/test/blackbox/context/block_assignment_1.exp +0 -1
- data/test/blackbox/context/block_assignment_1.tpl +0 -1
- data/test/blackbox/context/block_assignment_2.exp +0 -1
- data/test/blackbox/context/block_assignment_2.tpl +0 -1
- data/test/blackbox/context/modulo_assignment_1.exp +0 -1
- data/test/blackbox/context/modulo_assignment_1.tpl +0 -1
- data/test/blackbox/context/modulo_assignment_2.exp +0 -1
- data/test/blackbox/context/modulo_assignment_2.tpl +0 -1
- data/test/blackbox/data_1.rb +0 -1
- data/test/blackbox/postblock/hello.exp +0 -1
- data/test/blackbox/postblock/hello.pre +0 -1
- data/test/blackbox/postblock/hello.tpl +0 -1
- data/test/blackbox/postblock/hello_input_inclusion.exp +0 -1
- data/test/blackbox/postblock/hello_input_inclusion.tpl +0 -1
- data/test/blackbox/postblock/hello_to_authors.exp +0 -1
- data/test/blackbox/postblock/hello_to_authors.tpl +0 -1
- data/test/blackbox/poststring/hello.exp +0 -1
- data/test/blackbox/poststring/hello.tpl +0 -1
- data/test/blackbox/test_all.rb +0 -70
- data/test/standard_dialects/ruby/data.rb +0 -7
- data/test/standard_dialects/ruby/inclusion.exp +0 -6
- data/test/standard_dialects/ruby/inclusion.tpl +0 -6
- data/test/standard_dialects/test_all.rb +0 -29
- data/test/standard_dialects/yaml/assumptions_test.rb +0 -13
- data/test/standard_dialects/yaml/data.rb +0 -3
- data/test/standard_dialects/yaml/inclusion_1.exp +0 -7
- data/test/standard_dialects/yaml/inclusion_1.tpl +0 -2
- data/test/standard_dialects/yaml/inclusion_2.exp +0 -5
- data/test/standard_dialects/yaml/inclusion_2.tpl +0 -3
- data/test/unit/test_all.rb +0 -9
- data/test/unit/wlang/anagram_bugs_test.rb +0 -111
- data/test/unit/wlang/basic_ruleset_test.rb +0 -52
- data/test/unit/wlang/buffering_ruleset_test.rb +0 -102
- data/test/unit/wlang/buffering_template1.wtpl +0 -1
- data/test/unit/wlang/buffering_template2.wtpl +0 -1
- data/test/unit/wlang/buffering_template3.wtpl +0 -1
- data/test/unit/wlang/buffering_template4.wtpl +0 -1
- data/test/unit/wlang/buffering_template5.wtpl +0 -1
- data/test/unit/wlang/context_ruleset_test.rb +0 -32
- data/test/unit/wlang/data.rb +0 -3
- data/test/unit/wlang/encoder_set_test.rb +0 -42
- data/test/unit/wlang/imperative_ruleset_test.rb +0 -107
- data/test/unit/wlang/intelligent_buffer_test.rb +0 -194
- data/test/unit/wlang/othersymbols_test.rb +0 -16
- data/test/unit/wlang/parser_test.rb +0 -88
- data/test/unit/wlang/plain_text_dialect_test.rb +0 -21
- data/test/unit/wlang/ruby_dialect_test.rb +0 -100
- data/test/unit/wlang/ruby_expected.rb +0 -3
- data/test/unit/wlang/ruby_template.wrb +0 -3
- data/test/unit/wlang/ruleset_utils_test.rb +0 -245
- data/test/unit/wlang/specification_examples_test.rb +0 -54
- data/test/unit/wlang/test_utils.rb +0 -25
- data/test/unit/wlang/wlang_test.rb +0 -80
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
require 'wlang'
|
|
2
|
+
require 'quickl'
|
|
3
|
+
module WLang
|
|
4
|
+
#
|
|
5
|
+
# wlang -- templating engine
|
|
6
|
+
#
|
|
7
|
+
# SYNOPSIS
|
|
8
|
+
# Usage: wlang [options] TEMPLATE
|
|
9
|
+
#
|
|
10
|
+
# OPTIONS:
|
|
11
|
+
# #{summarized_options}
|
|
12
|
+
#
|
|
13
|
+
# DESCRIPTION
|
|
14
|
+
# This command invokes the wlang templating engine on TEMPLATE
|
|
15
|
+
# and flushes the rendering result on standard output.
|
|
16
|
+
#
|
|
17
|
+
class Command < Quickl::Command(__FILE__, __LINE__)
|
|
18
|
+
|
|
19
|
+
options do |opt|
|
|
20
|
+
@output = nil
|
|
21
|
+
opt.on('--output=FILE', 'Render output in FILE') do |file|
|
|
22
|
+
@output = file
|
|
23
|
+
end
|
|
24
|
+
@yaml_front_matter = true
|
|
25
|
+
opt.on("--[no-]yaml-front-matter",
|
|
26
|
+
"Enable/disable YAML front mater (defaults to true)") do |val|
|
|
27
|
+
@yaml_front_matter = val
|
|
28
|
+
end
|
|
29
|
+
@ast = false
|
|
30
|
+
opt.on('--ast', "Debugs the AST") do
|
|
31
|
+
@ast = true
|
|
32
|
+
end
|
|
33
|
+
@compiling_options = {}
|
|
34
|
+
opt.on('--[no-]auto-spacing') do |val|
|
|
35
|
+
@compiling_options[:autospacing] = val
|
|
36
|
+
end
|
|
37
|
+
opt.on_tail("--help", "Show help") do
|
|
38
|
+
raise Quickl::Help
|
|
39
|
+
end
|
|
40
|
+
opt.on_tail("--version", "Show version") do
|
|
41
|
+
raise Quickl::Exit, "#{Quickl.program_name} #{WLang::VERSION} (c) 2009-2012, Bernard Lambeau"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def execute(argv)
|
|
46
|
+
install(argv)
|
|
47
|
+
|
|
48
|
+
compiler = @dialect.compiler(@compiling_options)
|
|
49
|
+
if @ast
|
|
50
|
+
require 'awesome_print'
|
|
51
|
+
ap compiler.ast(@template)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
with_output do |output|
|
|
55
|
+
compiler.compile(@template).render(@context, output)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def install(argv)
|
|
62
|
+
raise Quickl::Help unless argv.size == 1
|
|
63
|
+
|
|
64
|
+
# template file
|
|
65
|
+
unless File.file?(@tpl_file = argv.first)
|
|
66
|
+
raise Quickl::Exit, "No such template #{tpl_file}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# dialect
|
|
70
|
+
require 'wlang/html'
|
|
71
|
+
@dialect = WLang::Html
|
|
72
|
+
|
|
73
|
+
# template and context
|
|
74
|
+
@template = File.read(@tpl_file)
|
|
75
|
+
@context = {}
|
|
76
|
+
|
|
77
|
+
if @yaml_front_matter and
|
|
78
|
+
@template =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
|
79
|
+
require 'yaml'
|
|
80
|
+
@context.merge! YAML::load($1)
|
|
81
|
+
@template = $'
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def with_output(&proc)
|
|
86
|
+
if @output
|
|
87
|
+
File.open(@output, 'w', &proc)
|
|
88
|
+
else
|
|
89
|
+
proc.call($stdout)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end # class Command
|
|
94
|
+
end # module WLang
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'wlang/compiler/parser'
|
|
2
|
+
require 'wlang/compiler/filter'
|
|
3
|
+
require 'wlang/compiler/dialect_enforcer'
|
|
4
|
+
require 'wlang/compiler/strconcat_flattener'
|
|
5
|
+
require 'wlang/compiler/proc_call_removal'
|
|
6
|
+
require 'wlang/compiler/autospacing'
|
|
7
|
+
require 'wlang/compiler/to_ruby_abstraction'
|
|
8
|
+
require 'wlang/compiler/static_merger'
|
|
9
|
+
require 'wlang/compiler/to_ruby_code'
|
|
10
|
+
module WLang
|
|
11
|
+
#
|
|
12
|
+
# Provides the wlang compiler which works on the following AST abstractions:
|
|
13
|
+
#
|
|
14
|
+
# - :template, the root element [:template, [:fn, ...]]
|
|
15
|
+
# - :fn, a concrete function [:fn, code]
|
|
16
|
+
# - :wlang, a high-order function [:wlang, symbols, [:fn, ..], [:fn, ...], ...]
|
|
17
|
+
# - :strconcat, concatenation [:strconcat, [...], [...], [...]]
|
|
18
|
+
# - :modulo, modulation [:modulo, dialect, [:fn, ...]]
|
|
19
|
+
# - :static, constant text [:static, "..."]
|
|
20
|
+
#
|
|
21
|
+
class Compiler
|
|
22
|
+
|
|
23
|
+
attr_reader :dialect
|
|
24
|
+
|
|
25
|
+
def initialize(dialect)
|
|
26
|
+
@dialect = dialect
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def options
|
|
30
|
+
dialect.options
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def compile(source)
|
|
34
|
+
case source
|
|
35
|
+
when Template
|
|
36
|
+
source
|
|
37
|
+
when Proc
|
|
38
|
+
Template.new(@dialect, source)
|
|
39
|
+
else
|
|
40
|
+
code = to_ruby_code(source)
|
|
41
|
+
proc = eval(code, TOPLEVEL_BINDING)
|
|
42
|
+
Template.new(@dialect, proc)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def to_ruby_code(source)
|
|
47
|
+
engine.call(source)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def ast(source)
|
|
51
|
+
parser.new.call(source)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def parser
|
|
55
|
+
Class.new(Temple::Engine).tap{|c|
|
|
56
|
+
c.use Parser
|
|
57
|
+
c.use DialectEnforcer, :dialect => @dialect
|
|
58
|
+
c.use Autospacing if options[:autospacing]
|
|
59
|
+
c.use StrconcatFlattener
|
|
60
|
+
c.use StaticMerger
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def engine(gencode = true)
|
|
65
|
+
Class.new(Temple::Engine).tap{|c|
|
|
66
|
+
c.use Parser
|
|
67
|
+
c.use DialectEnforcer, :dialect => @dialect
|
|
68
|
+
c.use Autospacing if options[:autospacing]
|
|
69
|
+
c.use StrconcatFlattener
|
|
70
|
+
c.use StaticMerger
|
|
71
|
+
c.use ProcCallRemoval
|
|
72
|
+
c.use ToRubyAbstraction
|
|
73
|
+
c.use ToRubyCode if gencode
|
|
74
|
+
}.new
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
end # class Compiler
|
|
78
|
+
end # module WLang
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
class Compiler
|
|
3
|
+
class Autospacing < Filter
|
|
4
|
+
|
|
5
|
+
def on_strconcat(*exps)
|
|
6
|
+
optimized = []
|
|
7
|
+
exps.each_with_index do |exp,i|
|
|
8
|
+
optimized[i] = call(exp)
|
|
9
|
+
if exp.first == :wlang and multiline?(exp) and i != 0
|
|
10
|
+
optimized[i-1] = RightStrip.new.call(optimized[i-1])
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
[:strconcat] + optimized
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def on_wlang(symbols, *fns)
|
|
17
|
+
fns.inject [:wlang, symbols] do |rw,fn|
|
|
18
|
+
fn = Unindent.new.call(fn)
|
|
19
|
+
fn = RightStrip.new.call(fn)
|
|
20
|
+
rw << call(fn)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def multiline?(who)
|
|
27
|
+
case who.first
|
|
28
|
+
when :static
|
|
29
|
+
who.last =~ /\n/
|
|
30
|
+
when :wlang, :modulo
|
|
31
|
+
who[2..-1].any?{|s| s && multiline?(s)}
|
|
32
|
+
else
|
|
33
|
+
who[1..-1].any?{|s| s && multiline?(s)}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class RightStrip < Filter
|
|
38
|
+
|
|
39
|
+
def on_strconcat(*exps)
|
|
40
|
+
exps[-1] = call(exps[-1])
|
|
41
|
+
[:strconcat] + exps
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def on_static(text)
|
|
45
|
+
[:static, text.gsub(/\s+\Z/m, '')]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end # class RightStrip
|
|
49
|
+
|
|
50
|
+
class Unindent < Filter
|
|
51
|
+
|
|
52
|
+
def on_static(text)
|
|
53
|
+
[:static, text.gsub(/^ /m, '')]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end # class Unindent
|
|
57
|
+
|
|
58
|
+
end # class Autospacing
|
|
59
|
+
end # class Compiler
|
|
60
|
+
end # module WLang
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
class Compiler
|
|
3
|
+
class DialectEnforcer < Filter
|
|
4
|
+
|
|
5
|
+
def dialect; options[:dialect]; end
|
|
6
|
+
|
|
7
|
+
def on_wlang(symbols, *fns)
|
|
8
|
+
extra, meth = find_dispatching_method(symbols, :unbound_method)
|
|
9
|
+
if meth
|
|
10
|
+
argsize, arity = fns.size, meth.arity - 1
|
|
11
|
+
if extra.size > 0
|
|
12
|
+
rewrite_extra_symbols(extra, symbols[extra.length..-1], fns)
|
|
13
|
+
elsif argsize > arity
|
|
14
|
+
rewrite_trailing_fns(symbols, fns[0...arity], fns[arity..-1])
|
|
15
|
+
elsif argsize < arity
|
|
16
|
+
rewrite_missing_fns(symbols, fns, arity - argsize)
|
|
17
|
+
else
|
|
18
|
+
enforce_sub_dialects(symbols, fns)
|
|
19
|
+
end
|
|
20
|
+
else
|
|
21
|
+
rewrite_unknown_tag(symbols, fns)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def enforce_sub_dialects(symbols, fns)
|
|
28
|
+
ds = dialect.dialects_for(symbols) || []
|
|
29
|
+
fns.zip(ds).inject [:wlang, symbols] do |rw, (fn, d)|
|
|
30
|
+
if d
|
|
31
|
+
enforcer = DialectEnforcer.new(:dialect => d.factor)
|
|
32
|
+
rw << [:modulo, d, enforcer.call(fn)]
|
|
33
|
+
else
|
|
34
|
+
rw << call(fn)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def rewrite_missing_fns(symbols, fns, count)
|
|
40
|
+
count.times do
|
|
41
|
+
fns << [:arg, nil]
|
|
42
|
+
end
|
|
43
|
+
call([:wlang, symbols] + fns)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def rewrite_trailing_fns(symbols, fns, trailing)
|
|
47
|
+
wlanged = call([:wlang, symbols] + fns)
|
|
48
|
+
trailing.inject [:strconcat, wlanged] do |rw,fn|
|
|
49
|
+
rw << [:static, '{']
|
|
50
|
+
rw << call(fn.last)
|
|
51
|
+
rw << [:static, '}']
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def rewrite_extra_symbols(extra, symbols, fns)
|
|
56
|
+
wlang = fns.inject [:wlang, symbols] do |rw,fn|
|
|
57
|
+
rw << fn
|
|
58
|
+
end
|
|
59
|
+
[:strconcat, [:static, extra], call(wlang)]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def rewrite_unknown_tag(symbols, fns)
|
|
63
|
+
start, stop = dialect.braces
|
|
64
|
+
from = [:strconcat, [:static, symbols]]
|
|
65
|
+
fns.inject(from) do |rw, fn|
|
|
66
|
+
rw << [:static, start]
|
|
67
|
+
rw << call(fn.last)
|
|
68
|
+
rw << [:static, stop]
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def find_dispatching_method(symbols, kind = :name)
|
|
73
|
+
extra, symbols, found = [], symbols.chars.to_a, nil
|
|
74
|
+
dialect.tap do |d|
|
|
75
|
+
begin
|
|
76
|
+
meth = Dialect.tag_dispatching_name(symbols)
|
|
77
|
+
if d.respond_to?(meth)
|
|
78
|
+
found = d.class.instance_method(meth)
|
|
79
|
+
break
|
|
80
|
+
else
|
|
81
|
+
extra << symbols.shift
|
|
82
|
+
end
|
|
83
|
+
end until symbols.empty?
|
|
84
|
+
end
|
|
85
|
+
found = found.name.to_sym if found && kind == :name
|
|
86
|
+
[extra.join, found]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end # class DialectEnforcer
|
|
90
|
+
end # class Compiler
|
|
91
|
+
end # module WLang
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
class Compiler
|
|
3
|
+
class Filter < Temple::Filter
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
|
|
7
|
+
def recurse_on(*kinds)
|
|
8
|
+
kinds.each do |kind|
|
|
9
|
+
define_method(:"on_#{kind}") do |*args|
|
|
10
|
+
recurse(kind, *args)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
extend ClassMethods
|
|
17
|
+
|
|
18
|
+
module InstanceMethods
|
|
19
|
+
|
|
20
|
+
def recurse(kind, *args)
|
|
21
|
+
args.inject [kind] do |rw,arg|
|
|
22
|
+
rw << (arg.is_a?(Array) ? call(arg) : arg)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
include InstanceMethods
|
|
28
|
+
|
|
29
|
+
recurse_on :template, :fn, :wlang, :strconcat, :modulo, :static
|
|
30
|
+
end # class Filter
|
|
31
|
+
end # class Compiler
|
|
32
|
+
end # module WLang
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
grammar WLang::Grammar
|
|
2
|
+
|
|
3
|
+
rule template
|
|
4
|
+
(strconcat !.){
|
|
5
|
+
[:template, [:fn, strconcat.value]]
|
|
6
|
+
}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
rule strconcat
|
|
10
|
+
(non_static | static)* {
|
|
11
|
+
if matches.size == 1
|
|
12
|
+
matches.first.value
|
|
13
|
+
else
|
|
14
|
+
[:strconcat] + matches.map(&:value)
|
|
15
|
+
end
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
rule static
|
|
20
|
+
(!stop_char .)+ {
|
|
21
|
+
[:static, to_s]
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
rule non_static
|
|
26
|
+
block | wlang
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
rule block
|
|
30
|
+
(fn_start strconcat fn_stop){
|
|
31
|
+
[:static, to_s]
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
rule wlang
|
|
36
|
+
(symbols functions){
|
|
37
|
+
[:wlang, symbols.to_s] + functions.value
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
rule functions
|
|
42
|
+
function+ { matches.map{|fn| [:fn, fn.value]} }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
rule function
|
|
46
|
+
(fn_start strconcat fn_stop){
|
|
47
|
+
strconcat.value
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
rule stop_char
|
|
52
|
+
fn_start | fn_stop | (symbols fn_start)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
rule symbols
|
|
56
|
+
/[!\^%"\$&'\*\+\?@~\#,\-\.\/:;=<>\|_]+/
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
rule fn_start
|
|
60
|
+
'{'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
rule fn_stop
|
|
64
|
+
'}'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
Citrus.load(File.expand_path('../grammar', __FILE__))
|
|
3
|
+
class Parser
|
|
4
|
+
|
|
5
|
+
def initialize(options = {})
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def call(input)
|
|
9
|
+
return input if input.is_a?(Array)
|
|
10
|
+
parser.parse(parsing_source(input)).value
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def parser
|
|
16
|
+
WLang::Grammar
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def parsing_source(input)
|
|
20
|
+
input = File.read(input.to_path) if input.respond_to?(:to_path)
|
|
21
|
+
input = input.to_str if input.respond_to?(:to_str)
|
|
22
|
+
input
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end # class Engine
|
|
26
|
+
end # module WLang
|