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.
Files changed (269) hide show
  1. data/CHANGELOG.md +3 -121
  2. data/Gemfile +23 -1
  3. data/Gemfile.lock +32 -28
  4. data/LICENCE.md +18 -21
  5. data/Manifest.txt +4 -5
  6. data/README.md +100 -174
  7. data/Rakefile +1 -13
  8. data/bin/wlang +3 -29
  9. data/lib/wlang.rb +21 -394
  10. data/lib/wlang/command.rb +94 -0
  11. data/lib/wlang/compiler.rb +78 -0
  12. data/lib/wlang/compiler/autospacing.rb +60 -0
  13. data/lib/wlang/compiler/dialect_enforcer.rb +91 -0
  14. data/lib/wlang/compiler/filter.rb +32 -0
  15. data/lib/wlang/compiler/grammar.citrus +67 -0
  16. data/lib/wlang/compiler/parser.rb +26 -0
  17. data/lib/wlang/compiler/proc_call_removal.rb +15 -0
  18. data/lib/wlang/compiler/static_merger.rb +28 -0
  19. data/lib/wlang/compiler/strconcat_flattener.rb +25 -0
  20. data/lib/wlang/compiler/to_ruby_abstraction.rb +22 -0
  21. data/lib/wlang/compiler/to_ruby_code.rb +55 -0
  22. data/lib/wlang/dialect.rb +40 -237
  23. data/lib/wlang/dialect/dispatching.rb +51 -0
  24. data/lib/wlang/dialect/evaluation.rb +30 -0
  25. data/lib/wlang/dialect/tags.rb +50 -0
  26. data/lib/wlang/dummy.rb +32 -0
  27. data/lib/wlang/html.rb +106 -0
  28. data/lib/wlang/loader.rb +6 -0
  29. data/lib/wlang/mustang.rb +90 -0
  30. data/lib/wlang/scope.rb +57 -0
  31. data/lib/wlang/scope/binding_scope.rb +18 -0
  32. data/lib/wlang/scope/object_scope.rb +25 -0
  33. data/lib/wlang/scope/proxy_scope.rb +18 -0
  34. data/lib/wlang/scope/root_scope.rb +24 -0
  35. data/lib/wlang/template.rb +16 -86
  36. data/lib/wlang/version.rb +9 -8
  37. data/spec/fixtures/dialect/foobar.rb +31 -0
  38. data/spec/fixtures/dialect/upcasing.rb +13 -0
  39. data/spec/fixtures/templates/hello.tpl +1 -0
  40. data/spec/integration/examples/1-basics.txt +65 -0
  41. data/spec/integration/examples/2-imperative.txt +51 -0
  42. data/spec/integration/examples/3-partials.txt +76 -0
  43. data/spec/integration/examples/4-recursion.txt +16 -0
  44. data/spec/integration/html/test_ampersand.rb +15 -0
  45. data/spec/integration/html/test_bang.rb +38 -0
  46. data/spec/integration/html/test_caret.rb +33 -0
  47. data/spec/integration/html/test_dollar.rb +16 -0
  48. data/spec/integration/html/test_greater.rb +23 -0
  49. data/spec/integration/html/test_modulo.rb +16 -0
  50. data/spec/integration/html/test_plus.rb +48 -0
  51. data/spec/integration/html/test_question.rb +33 -0
  52. data/spec/integration/html/test_sharp.rb +21 -0
  53. data/spec/integration/html/test_slash.rb +16 -0
  54. data/spec/integration/html/test_star.rb +37 -0
  55. data/spec/integration/test_dummy.rb +51 -0
  56. data/spec/integration/test_examples.rb +29 -0
  57. data/spec/integration/test_mustang.rb +120 -0
  58. data/spec/integration/test_readme.rb +56 -0
  59. data/spec/integration/test_upcasing.rb +22 -0
  60. data/spec/spec_helper.rb +62 -1
  61. data/spec/test_wlang.rb +101 -0
  62. data/spec/unit/compiler/autospacing/test_right_strip.rb +30 -0
  63. data/spec/unit/compiler/autospacing/test_unindent.rb +30 -0
  64. data/spec/unit/compiler/test_dialect_enforcer.rb +168 -0
  65. data/spec/unit/compiler/test_grammar.rb +207 -0
  66. data/spec/unit/compiler/test_parser.rb +69 -0
  67. data/spec/unit/compiler/test_proc_call_removal.rb +24 -0
  68. data/spec/unit/compiler/test_static_merger.rb +29 -0
  69. data/spec/unit/compiler/test_strconcat_flattener.rb +30 -0
  70. data/spec/unit/compiler/test_to_ruby_abstraction.rb +59 -0
  71. data/spec/unit/compiler/test_to_ruby_code.rb +24 -0
  72. data/spec/unit/dialect/test_compile.rb +52 -0
  73. data/spec/unit/dialect/test_dispatching.rb +19 -0
  74. data/spec/unit/dialect/test_evaluate.rb +41 -0
  75. data/spec/unit/dialect/test_render.rb +33 -0
  76. data/spec/unit/dialect/test_tags.rb +32 -0
  77. data/spec/unit/dialect/test_with_scope.rb +18 -0
  78. data/spec/unit/scope/test_binding_scope.rb +27 -0
  79. data/spec/unit/scope/test_coerce.rb +22 -0
  80. data/spec/unit/scope/test_object_scope.rb +38 -0
  81. data/spec/unit/scope/test_proxy_scope.rb +22 -0
  82. data/spec/unit/scope/test_root_scope.rb +22 -0
  83. data/spec/unit/test_assumptions.rb +29 -0
  84. data/spec/unit/test_scope.rb +57 -0
  85. data/tasks/debug_mail.rake +42 -45
  86. data/tasks/gem.rake +22 -17
  87. data/tasks/spec_test.rake +9 -17
  88. data/tasks/unit_test.rake +11 -12
  89. data/tasks/yard.rake +13 -13
  90. data/wlang.gemspec +36 -32
  91. data/wlang.noespec +27 -35
  92. metadata +268 -451
  93. data/doc/specification/about.rdoc +0 -61
  94. data/doc/specification/analytics.wtpl +0 -13
  95. data/doc/specification/dialect.wtpl +0 -14
  96. data/doc/specification/dialects.wtpl +0 -3
  97. data/doc/specification/examples.rb +0 -3
  98. data/doc/specification/glossary.wtpl +0 -14
  99. data/doc/specification/hosting.rdoc +0 -0
  100. data/doc/specification/overview.rdoc +0 -116
  101. data/doc/specification/rulesets.wtpl +0 -87
  102. data/doc/specification/specification.css +0 -53
  103. data/doc/specification/specification.html +0 -1690
  104. data/doc/specification/specification.js +0 -8
  105. data/doc/specification/specification.wtpl +0 -42
  106. data/doc/specification/specification.yml +0 -432
  107. data/doc/specification/symbols.wtpl +0 -16
  108. data/lib/wlang/dialect_dsl.rb +0 -141
  109. data/lib/wlang/dialect_loader.rb +0 -74
  110. data/lib/wlang/dialects/bluecloth_dialect.rb +0 -16
  111. data/lib/wlang/dialects/coderay_dialect.rb +0 -45
  112. data/lib/wlang/dialects/hosted_dialect.rb +0 -50
  113. data/lib/wlang/dialects/plain_text_dialect.rb +0 -69
  114. data/lib/wlang/dialects/rdoc_dialect.rb +0 -33
  115. data/lib/wlang/dialects/redcloth_dialect.rb +0 -16
  116. data/lib/wlang/dialects/ruby_dialect.rb +0 -118
  117. data/lib/wlang/dialects/sql_dialect.rb +0 -38
  118. data/lib/wlang/dialects/standard_dialects.rb +0 -181
  119. data/lib/wlang/dialects/xhtml_dialect.rb +0 -63
  120. data/lib/wlang/dialects/yaml_dialect.rb +0 -30
  121. data/lib/wlang/encoder.rb +0 -62
  122. data/lib/wlang/encoder_set.rb +0 -122
  123. data/lib/wlang/errors.rb +0 -80
  124. data/lib/wlang/ext/hash_methodize.rb +0 -13
  125. data/lib/wlang/ext/string.rb +0 -44
  126. data/lib/wlang/hash_scope.rb +0 -89
  127. data/lib/wlang/hosted_language.rb +0 -146
  128. data/lib/wlang/intelligent_buffer.rb +0 -94
  129. data/lib/wlang/parser.rb +0 -332
  130. data/lib/wlang/parser_state.rb +0 -94
  131. data/lib/wlang/rule.rb +0 -66
  132. data/lib/wlang/rule_set.rb +0 -106
  133. data/lib/wlang/rulesets/basic_ruleset.rb +0 -83
  134. data/lib/wlang/rulesets/buffering_ruleset.rb +0 -115
  135. data/lib/wlang/rulesets/context_ruleset.rb +0 -111
  136. data/lib/wlang/rulesets/encoding_ruleset.rb +0 -73
  137. data/lib/wlang/rulesets/imperative_ruleset.rb +0 -132
  138. data/lib/wlang/rulesets/ruleset_utils.rb +0 -317
  139. data/lib/wlang/wlang_command.rb +0 -51
  140. data/lib/wlang/wlang_command_options.rb +0 -163
  141. data/spec/basic_object.spec +0 -40
  142. data/spec/coderay_dialect.spec +0 -8
  143. data/spec/dialect/apply_post_transform.spec +0 -16
  144. data/spec/global_extensions.rb +0 -2
  145. data/spec/hash_scope.spec +0 -76
  146. data/spec/redcloth_dialect.spec +0 -24
  147. data/spec/test_all.rb +0 -8
  148. data/spec/wlang.spec +0 -53
  149. data/spec/wlang_spec.rb +0 -8
  150. data/spec/xhtml_dialect.spec +0 -22
  151. data/tasks/genspec.rake +0 -5
  152. data/test/blackbox/basic/execution_1.exp +0 -1
  153. data/test/blackbox/basic/execution_1.tpl +0 -1
  154. data/test/blackbox/basic/execution_2.exp +0 -1
  155. data/test/blackbox/basic/execution_2.tpl +0 -1
  156. data/test/blackbox/basic/execution_3.exp +0 -1
  157. data/test/blackbox/basic/execution_3.tpl +0 -1
  158. data/test/blackbox/basic/execution_4.exp +0 -1
  159. data/test/blackbox/basic/execution_4.tpl +0 -1
  160. data/test/blackbox/basic/inclusion_1.exp +0 -1
  161. data/test/blackbox/basic/inclusion_1.tpl +0 -1
  162. data/test/blackbox/basic/inclusion_2.exp +0 -1
  163. data/test/blackbox/basic/inclusion_2.tpl +0 -1
  164. data/test/blackbox/basic/injection_1.exp +0 -1
  165. data/test/blackbox/basic/injection_1.tpl +0 -1
  166. data/test/blackbox/basic/injection_2.exp +0 -1
  167. data/test/blackbox/basic/injection_2.tpl +0 -1
  168. data/test/blackbox/basic/modulation_1.exp +0 -1
  169. data/test/blackbox/basic/modulation_1.tpl +0 -1
  170. data/test/blackbox/basic/modulation_2.exp +0 -1
  171. data/test/blackbox/basic/modulation_2.tpl +0 -1
  172. data/test/blackbox/basic/recursive_app_1.exp +0 -1
  173. data/test/blackbox/basic/recursive_app_1.tpl +0 -1
  174. data/test/blackbox/basic/recursive_app_2.exp +0 -1
  175. data/test/blackbox/basic/recursive_app_2.tpl +0 -1
  176. data/test/blackbox/buffering/data_1.rb +0 -1
  177. data/test/blackbox/buffering/data_assignment_1.exp +0 -1
  178. data/test/blackbox/buffering/data_assignment_1.tpl +0 -1
  179. data/test/blackbox/buffering/data_assignment_2.exp +0 -1
  180. data/test/blackbox/buffering/data_assignment_2.tpl +0 -1
  181. data/test/blackbox/buffering/data_assignment_3.exp +0 -1
  182. data/test/blackbox/buffering/data_assignment_3.tpl +0 -1
  183. data/test/blackbox/buffering/data_assignment_4.exp +0 -1
  184. data/test/blackbox/buffering/data_assignment_4.tpl +0 -1
  185. data/test/blackbox/buffering/input_1.exp +0 -1
  186. data/test/blackbox/buffering/input_1.tpl +0 -1
  187. data/test/blackbox/buffering/input_2.exp +0 -1
  188. data/test/blackbox/buffering/input_2.tpl +0 -1
  189. data/test/blackbox/buffering/input_3.exp +0 -1
  190. data/test/blackbox/buffering/input_3.tpl +0 -1
  191. data/test/blackbox/buffering/input_inclusion.exp +0 -1
  192. data/test/blackbox/buffering/input_inclusion.tpl +0 -1
  193. data/test/blackbox/buffering/input_inclusion_1.exp +0 -0
  194. data/test/blackbox/buffering/input_inclusion_1.tpl +0 -1
  195. data/test/blackbox/buffering/input_inclusion_2.exp +0 -1
  196. data/test/blackbox/buffering/input_inclusion_2.tpl +0 -1
  197. data/test/blackbox/buffering/input_inclusion_3.exp +0 -1
  198. data/test/blackbox/buffering/input_inclusion_3.tpl +0 -1
  199. data/test/blackbox/buffering/input_inclusion_4.exp +0 -0
  200. data/test/blackbox/buffering/input_inclusion_4.tpl +0 -1
  201. data/test/blackbox/buffering/input_inclusion_5.exp +0 -1
  202. data/test/blackbox/buffering/input_inclusion_5.tpl +0 -1
  203. data/test/blackbox/buffering/input_inclusion_6.exp +0 -1
  204. data/test/blackbox/buffering/input_inclusion_6.tpl +0 -1
  205. data/test/blackbox/buffering/input_inclusion_7.exp +0 -0
  206. data/test/blackbox/buffering/input_inclusion_7.tpl +0 -1
  207. data/test/blackbox/buffering/text_1.txt +0 -1
  208. data/test/blackbox/buffering/wlang.txt +0 -1
  209. data/test/blackbox/context/assignment_1.exp +0 -1
  210. data/test/blackbox/context/assignment_1.tpl +0 -1
  211. data/test/blackbox/context/assignment_2.exp +0 -1
  212. data/test/blackbox/context/assignment_2.tpl +0 -1
  213. data/test/blackbox/context/assignment_3.exp +0 -2
  214. data/test/blackbox/context/assignment_3.tpl +0 -2
  215. data/test/blackbox/context/assignment_4.exp +0 -1
  216. data/test/blackbox/context/assignment_4.tpl +0 -1
  217. data/test/blackbox/context/block_assignment_1.exp +0 -1
  218. data/test/blackbox/context/block_assignment_1.tpl +0 -1
  219. data/test/blackbox/context/block_assignment_2.exp +0 -1
  220. data/test/blackbox/context/block_assignment_2.tpl +0 -1
  221. data/test/blackbox/context/modulo_assignment_1.exp +0 -1
  222. data/test/blackbox/context/modulo_assignment_1.tpl +0 -1
  223. data/test/blackbox/context/modulo_assignment_2.exp +0 -1
  224. data/test/blackbox/context/modulo_assignment_2.tpl +0 -1
  225. data/test/blackbox/data_1.rb +0 -1
  226. data/test/blackbox/postblock/hello.exp +0 -1
  227. data/test/blackbox/postblock/hello.pre +0 -1
  228. data/test/blackbox/postblock/hello.tpl +0 -1
  229. data/test/blackbox/postblock/hello_input_inclusion.exp +0 -1
  230. data/test/blackbox/postblock/hello_input_inclusion.tpl +0 -1
  231. data/test/blackbox/postblock/hello_to_authors.exp +0 -1
  232. data/test/blackbox/postblock/hello_to_authors.tpl +0 -1
  233. data/test/blackbox/poststring/hello.exp +0 -1
  234. data/test/blackbox/poststring/hello.tpl +0 -1
  235. data/test/blackbox/test_all.rb +0 -70
  236. data/test/standard_dialects/ruby/data.rb +0 -7
  237. data/test/standard_dialects/ruby/inclusion.exp +0 -6
  238. data/test/standard_dialects/ruby/inclusion.tpl +0 -6
  239. data/test/standard_dialects/test_all.rb +0 -29
  240. data/test/standard_dialects/yaml/assumptions_test.rb +0 -13
  241. data/test/standard_dialects/yaml/data.rb +0 -3
  242. data/test/standard_dialects/yaml/inclusion_1.exp +0 -7
  243. data/test/standard_dialects/yaml/inclusion_1.tpl +0 -2
  244. data/test/standard_dialects/yaml/inclusion_2.exp +0 -5
  245. data/test/standard_dialects/yaml/inclusion_2.tpl +0 -3
  246. data/test/unit/test_all.rb +0 -9
  247. data/test/unit/wlang/anagram_bugs_test.rb +0 -111
  248. data/test/unit/wlang/basic_ruleset_test.rb +0 -52
  249. data/test/unit/wlang/buffering_ruleset_test.rb +0 -102
  250. data/test/unit/wlang/buffering_template1.wtpl +0 -1
  251. data/test/unit/wlang/buffering_template2.wtpl +0 -1
  252. data/test/unit/wlang/buffering_template3.wtpl +0 -1
  253. data/test/unit/wlang/buffering_template4.wtpl +0 -1
  254. data/test/unit/wlang/buffering_template5.wtpl +0 -1
  255. data/test/unit/wlang/context_ruleset_test.rb +0 -32
  256. data/test/unit/wlang/data.rb +0 -3
  257. data/test/unit/wlang/encoder_set_test.rb +0 -42
  258. data/test/unit/wlang/imperative_ruleset_test.rb +0 -107
  259. data/test/unit/wlang/intelligent_buffer_test.rb +0 -194
  260. data/test/unit/wlang/othersymbols_test.rb +0 -16
  261. data/test/unit/wlang/parser_test.rb +0 -88
  262. data/test/unit/wlang/plain_text_dialect_test.rb +0 -21
  263. data/test/unit/wlang/ruby_dialect_test.rb +0 -100
  264. data/test/unit/wlang/ruby_expected.rb +0 -3
  265. data/test/unit/wlang/ruby_template.wrb +0 -3
  266. data/test/unit/wlang/ruleset_utils_test.rb +0 -245
  267. data/test/unit/wlang/specification_examples_test.rb +0 -54
  268. data/test/unit/wlang/test_utils.rb +0 -25
  269. data/test/unit/wlang/wlang_test.rb +0 -80
@@ -0,0 +1,15 @@
1
+ module WLang
2
+ class Compiler
3
+ class ProcCallRemoval < Filter
4
+
5
+ def on_fn(core)
6
+ if core.first == :static
7
+ [:arg, core.last]
8
+ else
9
+ [:fn, call(core)]
10
+ end
11
+ end
12
+
13
+ end # class ProcCallRemoval
14
+ end # class Compiler
15
+ end # module WLang
@@ -0,0 +1,28 @@
1
+ module WLang
2
+ class Compiler
3
+ class StaticMerger < Filter
4
+
5
+ def on_strconcat(*exps)
6
+ result = [:strconcat]
7
+ text = nil
8
+
9
+ exps.each do |exp|
10
+ if exp.first == :static
11
+ if text
12
+ text << exp.last
13
+ else
14
+ text = exp.last.dup
15
+ result << [:static, text]
16
+ end
17
+ else
18
+ result << compile(exp)
19
+ text = nil
20
+ end
21
+ end
22
+
23
+ result
24
+ end
25
+
26
+ end # class StaticMerger
27
+ end # class Compiler
28
+ end # module WLang
@@ -0,0 +1,25 @@
1
+ module WLang
2
+ class Compiler
3
+ class StrconcatFlattener < Filter
4
+
5
+ def on_strconcat(*children)
6
+ if children.size == 1
7
+ call(children.first)
8
+ else
9
+ children.inject [:strconcat] do |rw,child|
10
+ child = call(child)
11
+ if child.first == :strconcat
12
+ child[1..-1].each do |subchild|
13
+ rw << subchild
14
+ end
15
+ else
16
+ rw << child
17
+ end
18
+ rw
19
+ end
20
+ end
21
+ end
22
+
23
+ end # class StrconcatFlattener
24
+ end # class Compiler
25
+ end # module WLang
@@ -0,0 +1,22 @@
1
+ module WLang
2
+ class Compiler
3
+ class ToRubyAbstraction < Filter
4
+
5
+ def on_strconcat(*cases)
6
+ [:multi] + cases.map{|c| call(c)}
7
+ end
8
+
9
+ def on_fn(code)
10
+ [:proc, call(code)]
11
+ end
12
+
13
+ def on_wlang(symbols, *fns)
14
+ meth = Dialect.tag_dispatching_name(symbols)
15
+ fns.inject [:dispatch, meth] do |rw, fn|
16
+ rw << call(fn)
17
+ end
18
+ end
19
+
20
+ end # class ToRubyAbstraction
21
+ end # class Compiler
22
+ end # module WLang
@@ -0,0 +1,55 @@
1
+ module WLang
2
+ class Compiler
3
+ class ToRubyCode < Temple::Generator
4
+
5
+ class IdGen
6
+ def initialize; @current = 0; end
7
+ def next; @current += 1; end
8
+ def to_s; @current.to_s; end
9
+ end
10
+
11
+ def idgen
12
+ options[:idgen] ? options[:idgen] : (@idgen ||= IdGen.new)
13
+ end
14
+
15
+ def myid
16
+ options[:myid] || 0
17
+ end
18
+
19
+ def call(x)
20
+ compile(x)
21
+ end
22
+
23
+ def on_template(fn)
24
+ call(fn)
25
+ end
26
+
27
+ def on_dispatch(meth, *procs)
28
+ procs = procs.map{|p| call(p)}.join(', ')
29
+ "d#{myid}.#{meth}(b#{myid}, #{procs})"
30
+ end
31
+
32
+ def on_arg(code)
33
+ code.inspect
34
+ end
35
+
36
+ def on_modulo(dialect, fn)
37
+ if fn.first == :arg
38
+ call(fn)
39
+ else
40
+ id = idgen.next
41
+ code = call(fn)
42
+ "Proc.new{|d#{id},b#{id}| #{code}.call(#{dialect}.factor(d#{id}.options), b#{id}) }"
43
+ end
44
+ end
45
+
46
+ def on_proc(code)
47
+ id = idgen.next
48
+ gen = ToRubyCode.new(:buffer => "b#{id}", :idgen => idgen, :myid => id)
49
+ code = gen.call(code)
50
+ "Proc.new{|d#{id},b#{id}| #{code} }"
51
+ end
52
+
53
+ end # class ToRubyCode
54
+ end # class Compiler
55
+ end # module WLang
@@ -1,250 +1,53 @@
1
- require 'wlang/encoder_set'
2
- require 'wlang/rule_set'
1
+ require 'wlang/dialect/dispatching'
2
+ require 'wlang/dialect/evaluation'
3
+ require 'wlang/dialect/tags'
3
4
  module WLang
4
-
5
- #
6
- # Implements the _dialect_ abstraction (see {README}[link://files/README.rdoc]).
7
- # A dialect instance is an aggregation of encoders and ruleset (through EncoderSet
8
- # and RuleSet classes). A dialect is also a node in the dialect tree and has a
9
- # qualified name through this tree. For example <tt>wlang/xhtml</tt> is the
10
- # qualified name of a <tt>xhtml</tt> dialect which is a child dialect of
11
- # <tt>wlang</tt>.
12
- #
13
- # Users are not intended to use this class directly. Use the Domain Specific
14
- # Language instead (see WLang::Dialect::DSL).
15
- #
16
- # === For developers only
17
- #
18
- # In order to avoid having users to install all required gems of all dialects
19
- # wlang implements a lazy load design pattern on the dialect tree, through the
20
- # WLang::Dialect::DSL and WLang::Dialect::Loader classes. The former only creates
21
- # Dialect instances as tree nodes (by chaining dialects through @parent) and
22
- # installs mapping with file extensions. Rules and encoders are not initially
23
- # installed (precisely: WLang::Dialect::DSL#require_ruby is simply ignored).
24
- # When a given dialect is needed by wlang it is first built (through the build!
25
- # method and the WLang::Dialect::Loader class).
26
- #
27
- # Standard dialect obtention methods (WLang#dialect as well as WLang::Dialect#dialect)
28
- # ensure that returned dialects are built. If you obtain dialects another way,
29
- # be sure that they are built before using them (is_built? and build! are your
30
- # friends to achieve that goal).
31
- #
32
- # Moreover, child dialects may require tools of their ancestors. The following
33
- # invariant should always be respected: if a dialect is built, all its ancestors
34
- # are built as well. This invariant is not enforced by the build! method because
35
- # it is trivially respected by the way WLang::Dialect#dialect is implemented.
36
- #
37
5
  class Dialect
38
-
39
- # Underlying ruleset
40
- attr_reader :ruleset
41
-
42
- # Underlying encoders
43
- attr_reader :encoders
6
+ include Dialect::Dispatching
7
+ include Dialect::Evaluation
8
+ include Dialect::Tags
44
9
 
45
- # Dialect name
46
- attr_reader :name
47
-
48
- # Parent dialect
49
- attr_reader :parent
50
-
51
- # Sub dialects by name
52
- attr_reader :dialects
53
-
54
- # Post transformer
55
- attr_accessor :post_transformer
56
-
57
- #
58
- # Creates a dialect instance. _builder_ block is a chunk of code of the DSL
59
- # that will be executed twice: once at construction time to create sub dialects
60
- # nodes and install file extensions and once at building time to install ruleset
61
- # and encoders.
62
- #
63
- def initialize(name, parent, &builder)
64
- @name, @parent = name, parent
65
- @builder, @built = builder, builder.nil?
66
- @dialects = nil
67
- @encoders = nil
68
- @ruleset = nil
69
- DSL.new(self).instance_eval(&builder) unless builder.nil?
70
- end
71
-
72
- ### Lazy load mechanism ######################################################
73
-
74
- #
75
- # Force the dialect to be built. Has no effect if it is already built. Invokes
76
- # the DSL chunk of code through WLang::DSL::Loader otherwise.
77
- #
78
- def build!
79
- unless is_built?
80
- WLang::Dialect::Loader.new(self).instance_eval(&@builder)
81
- @built = true
82
- end
83
- self
84
- end
10
+ class << self
85
11
 
86
- # Returns true if this dialect is already built, false otherwise.
87
- def is_built?
88
- return @built
89
- end
90
-
91
-
92
- ### Installation #############################################################
93
-
94
- #
95
- # Adds a child dialect under _name_. _name_ cannot be qualified and must be a
96
- # valid dialect name according to the wlang specification (see WLang::DIALECT_NAME_REGEXP).
97
- # _child_ must be a Dialect instance.
98
- #
99
- def add_child_dialect(name, child)
100
- raise(ArgumentError, "Invalid dialect name") unless WLang::DIALECT_NAME_REGEXP =~ name
101
- raise(ArgumentError, "Dialect expected") unless Dialect===child
102
- @dialects = {} if @dialects.nil?
103
- @dialects[name] = child
104
- end
105
-
106
- # See EncoderSet#add_encoder
107
- def add_encoder(name, &block)
108
- @encoders = EncoderSet.new if @encoders.nil?
109
- @encoders.add_encoder(name, &block)
110
- end
111
-
112
- # See EncoderSet#add_encoders
113
- def add_encoders(mod, pairs)
114
- @encoders = EncoderSet.new if @encoders.nil?
115
- @encoders.add_encoders(mod, pairs)
116
- end
117
-
118
- # See RuleSet::add_rule
119
- def add_rule(name, &block)
120
- @ruleset = RuleSet.new if @ruleset.nil?
121
- @ruleset.add_rule(name, &block)
122
- end
123
-
124
- # See RuleSet::add_rules
125
- def add_rules(mod, pairs)
126
- @ruleset = RuleSet.new if @ruleset.nil?
127
- @ruleset.add_rules(mod, pairs)
128
- end
129
-
130
- ### Query API ################################################################
131
-
132
- # Returns qualified name of this dialect
133
- def qualified_name
134
- parentname = @parent.nil? ? "" : @parent.to_s
135
- return ""==parentname ? @name : parentname + '/' + @name
136
- end
137
-
138
- #
139
- # Finds a child dialect by name. _name_ can be a String denoting a qualified
140
- # name as well as an Array of strings, resulting from a qualified name split.
141
- # This method should always be invoked on built dialects, it always returns nil
142
- # otherwise. When found, returned dialect is automatically built as well as all
143
- # its ancestors. When not found, the method returns nil.
144
- #
145
- def dialect(name)
146
- # implement argument conventions
147
- if String===name
148
- raise(ArgumentError, "Invalid dialect name #{name}") unless WLang::QUALIFIED_DIALECT_NAME_REGEXP =~ name
149
- name = name.split('/')
150
- elsif not(Array===name)
151
- raise(ArgumentError,"Invalid dialect name #{name}")
12
+ def factor(options = {})
13
+ new(default_options.merge(options))
152
14
  end
153
-
154
- # not built or no child at all
155
- return nil if @dialects.nil?
156
-
157
- # get first child name and find it
158
- child_name = name[0]
159
- child_dialect = @dialects[child_name]
160
-
161
- if child_dialect.nil?
162
- # unexisting, return nil
163
- return nil
164
- elsif name.length==1
165
- # found and last of qualified name -> build it
166
- return child_dialect.build!
167
- else
168
- # found but not last of qualified name -> build it and delegate
169
- child_dialect.build!
170
- return child_dialect.dialect(name[1..-1])
15
+
16
+ def default_options(options = {})
17
+ @default_options ||= (superclass.default_options.dup rescue {})
18
+ @default_options.merge!(options)
171
19
  end
172
- end
173
-
174
- # Applies post transformation
175
- def apply_post_transform(text)
176
- case self.post_transformer
177
- when String
178
- WLang::encode(text, self.post_transformer, {})
179
- when Proc
180
- self.post_transformer.call(text)
181
- else
182
- text
20
+
21
+ def compiler(options = {})
22
+ factor(options).compiler
183
23
  end
184
- end
185
-
186
- #
187
- # Finds an encoder by name.
188
- #
189
- def encoder(name)
190
- # implement argument conventions
191
- if String===name
192
- raise(ArgumentError, "Invalid encoder name #{name}") unless WLang::QUALIFIED_ENCODER_NAME_REGEXP =~ name
193
- name = name.split('/')
194
- elsif not(Array===name)
195
- raise(ArgumentError,"Invalid encoder name #{name}")
24
+
25
+ def compile(source, options = {})
26
+ compiler(options).compile(source)
196
27
  end
197
-
198
- # last name in qualified?
199
- if name.length==1
200
- # delegate to encoders
201
- return nil if @encoders.nil?
202
- return @encoders.get_encoder(name[0])
203
- else
204
- # find sub dialect, and delegate
205
- child_name = name[0]
206
- child_dialect = dialect(child_name)
207
- if child_dialect.nil?
208
- return nil
209
- else
210
- return child_dialect.encoder(name[1..-1])
211
- end
28
+
29
+ def to_ruby_code(source, options = {})
30
+ compiler(options).to_ruby_code(source)
212
31
  end
213
- end
214
-
215
- # Finds a encoder in dialect tree
216
- def find_encoder(name)
217
- raise(ArgumentError, "Invalid (relative) encoder name #{name}") unless String===name
218
- raise(ArgumentError, "Invalid (relative) encoder name #{name}") if name.include?("/")
219
- return nil if @encoders.nil?
220
- if @encoders.has_encoder?(name)
221
- @encoders.get_encoder(name)
222
- elsif @parent
223
- @parent.find_encoder(name)
224
- else
225
- nil
32
+
33
+ def render(source, scope = {}, buffer = "")
34
+ compile(source).call(scope, buffer)
226
35
  end
36
+
227
37
  end
228
-
229
- # See RuleSet#pattern.
230
- def pattern(block_symbols)
231
- return RuleSet.new.pattern(block_symbols) if @ruleset.nil?
232
- @ruleset.pattern(block_symbols)
233
- end
234
-
235
- ### Other utilities ##########################################################
236
-
237
- # Factors a spacing friendly buffer for instantiation in this dialect
238
- def factor_buffer
239
- #IntelligentBuffer.new
240
- ""
241
- end
242
-
243
- # Returns a string representation
244
- def to_s
245
- qualified_name
38
+
39
+ default_options :braces => WLang::BRACES,
40
+ :autospacing => false
41
+
42
+ attr_reader :options
43
+ def braces; options[:braces]; end
44
+
45
+ attr_reader :compiler
46
+
47
+ def initialize(options = {})
48
+ @options = options
49
+ @compiler = WLang::Compiler.new(self)
246
50
  end
247
-
51
+
248
52
  end # class Dialect
249
-
250
- end #module WLang
53
+ end # module WLang
@@ -0,0 +1,51 @@
1
+ module WLang
2
+ class Dialect
3
+ module Dispatching
4
+
5
+ module ClassMethods
6
+
7
+ def tag_dispatching_name(symbols, prefix = "_tag")
8
+ symbols = symbols.chars unless symbols.is_a?(Array)
9
+ chars = symbols.map{|s| s.ord}.join("_")
10
+ "#{prefix}_#{chars}".to_sym
11
+ end
12
+
13
+ private
14
+
15
+ def define_tag_method(symbols, dialects, code)
16
+ rulename = tag_dispatching_name(symbols, "_tag")
17
+ case code
18
+ when Symbol
19
+ module_eval %Q{ alias :#{rulename} #{code} }
20
+ when Proc
21
+ define_method(rulename, code)
22
+ else
23
+ raise "Unable to use #{code} for a tag"
24
+ end
25
+ dialects_info_name = tag_dispatching_name(symbols, "_diatag")
26
+ define_method(dialects_info_name) do dialects end
27
+ end
28
+
29
+ end # module ClassMethods
30
+
31
+ module InstanceMethods
32
+
33
+ def dialects_for(symbols)
34
+ info = Dialect.tag_dispatching_name(symbols, "_diatag")
35
+ if respond_to?(info)
36
+ send(info)
37
+ else
38
+ raise ArgumentError, "No tag for #{symbols}"
39
+ end
40
+ end
41
+
42
+ end # module InstanceMethods
43
+
44
+ def self.included(mod)
45
+ mod.instance_eval{ include(Dispatching::InstanceMethods) }
46
+ mod.extend(ClassMethods)
47
+ end
48
+
49
+ end # module Dispatching
50
+ end # class Dialect
51
+ end # module WLang