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
@@ -1,62 +0,0 @@
1
- module WLang
2
-
3
- #
4
- # Encapsulates some encoding algorithm. This class is to EncoderSet what Rule
5
- # is to RuleSet. Encoders are always installed on a EncoderSet (using EncoderSet#add_encoder),
6
- # which is itself installed on a Dialect. Note that the method mentionned previously
7
- # provides a DRY shortcut, allowing not using this class directly.
8
- #
9
- # Example:
10
- # # Encoder subclassing can be avoided by providing a block to new
11
- # # The following encoder job is to upcase the text:
12
- # encoder = Encoder.new do |src,options|
13
- # src.upcase
14
- # end
15
- #
16
- # # It is even better to use the DSL
17
- # WLang::dialect("mydialect") do
18
- # # The following encoder job is to upcase the text and will be installed
19
- # # under mydialect/myupcaser qualified name
20
- # encoder("myupcaser") do |src,options|
21
- # src.upcase
22
- # end
23
- # end
24
- #
25
- # Creating a a new encoder can be made in two ways: by subclassing this class and
26
- # overriding the encoder method or by passing a block to new. In both cases,
27
- # <b>encoders should always be stateless</b>, to allow reusable dialects that could
28
- # even be used in a multi-threading environment.
29
- #
30
- # == Detailed API
31
- class Encoder
32
-
33
- #
34
- # Creates a new encoder. If no block is given, the invocation of new MUST be made
35
- # on a subclass overriding encoder. Otherwise, the block is considered as the
36
- # effective stateless implementation of encoder and will be called with the
37
- # same arguments.
38
- #
39
- def initialize(&block)
40
- @block = block
41
- end
42
-
43
- #
44
- # Fired by the parser when a rule request encoding of some instantiated text.
45
- # Typical example is the standard tag <tt>^{encoder/qualified/name}{...}</tt>
46
- # (see WLang::RuleSet::Basic) which requires the second block instantiation to
47
- # be encoded by the encoder whose qualified name is given by the first block.
48
- # This method must simply return the encoded text.
49
- #
50
- # Arguments:
51
- # - src: source text to encode.
52
- # - options: encoding options through a Hash. Available options are documented
53
- # by encoders themselve.
54
- #
55
- def encode(src, options = {})
56
- raise(NotImplementedError) unless @block
57
- @block.call(src, options)
58
- end
59
-
60
- end # class Encoder
61
-
62
- end
@@ -1,122 +0,0 @@
1
- require 'wlang/encoder'
2
- module WLang
3
-
4
- #
5
- # This class allows grouping encoders together to build a given dialect.
6
- # Encoders are always added with add_encoder, which also allows creating simple
7
- # encoders on the fly (that is, without subclassing Encoder).
8
- #
9
- # Examples:
10
- # # we will create a simple encoder set with two encoders, one for upcasing
11
- # # the other for downcasing.
12
- # encoders = EncoderSet.new
13
- # encoder.add_encoder 'upcaser' do |src,options|
14
- # src.upcase
15
- # end
16
- # encoder.add_encoder 'downcaser' do |src,options|
17
- # src.downcase
18
- # end
19
- #
20
- # == Detailed API
21
- class EncoderSet
22
-
23
- # Creates an empty encoder set.
24
- def initialize
25
- @encoders = {}
26
- end
27
-
28
- # Yields the block with name, encoder pairs
29
- def each
30
- @encoders.each_pair{|name,encoder| yield(name, encoder)}
31
- end
32
-
33
- #
34
- # Adds an encoder under a specific name. Supported signatures are as follows:
35
- # - _name_ is a symbol: _encoder_ and _block_ are ignored and encoder is
36
- # interpreted as being a method of the String class whose name is the symbol.
37
- # - _name_ is a String and a block is provided: encoder is expected to be
38
- # implemented by the block which takes |src,options| arguments.
39
- # - _name_ is a String and _encoder_ is a Proc: same as if _encoder_ was a
40
- # given block.
41
- #
42
- # Examples:
43
- # encoders = EncoderSet.new
44
- # # add an encoder by reusing String method
45
- # encoders.add_encoder(:upcase)
46
- #
47
- # # add an encoder by providing a block
48
- # encoders.add_encoder("ucase") do |src,options|
49
- # src.upcase
50
- # end
51
- #
52
- # # add an encoder by providing a Proc
53
- # upcaser = Proc.new {|src,options| src.upcase}
54
- # encoders.add_encoder("upcase", upcaser)
55
- #
56
- def add_encoder(name, encoder=nil, &block)
57
- # handle String method through symbol
58
- if Symbol===name
59
- encoder, block = nil, Proc.new {|src,options| src.send(name)}
60
- name = name.to_s
61
- elsif Proc===encoder
62
- encoder, block = nil, encoder
63
- end
64
-
65
- # check arguments
66
- if encoder.nil?
67
- raise(ArgumentError,"Block required") if block.nil?
68
- encoder = Encoder.new(&block)
69
- end
70
- raise(ArgumentError, "Encoder expected") unless Encoder===encoder
71
-
72
- # save encoder
73
- @encoders[name] = encoder
74
- end
75
-
76
- #
77
- # Adds reusable encoders defined in a Ruby module. _mod_ must be a Module instance.
78
- # If _pairs_ is ommitted (nil), all encoders of the module are added, under their
79
- # standard names (see DEFAULT_ENCODERS under WLang::EncoderSet::XHtml for example).
80
- # Otherwise, _pairs_ is expected to be a Hash providing a mapping between encoder
81
- # names and _mod_ methods (whose names are given by ruby symbols).
82
- #
83
- def add_encoders(mod, pairs=nil)
84
- raise(ArgumentError,"Module expected",caller) unless Module===mod
85
- pairs = mod::DEFAULT_ENCODERS if pairs.nil?
86
- pairs.each_pair do |name,method|
87
- meth = mod.method(method)
88
- raise(ArgumentError,"No such method: #{method} in #{mod}") if meth.nil?
89
- add_encoder(name, &meth.to_proc)
90
- end
91
- end
92
-
93
- # Checks if an encoder is installed under _name.
94
- def has_encoder?(name)
95
- @encoders.has_key?(name)
96
- end
97
-
98
- # Returns an encoder by its name, nil if no such encoder.
99
- def get_encoder(name)
100
- @encoders[name]
101
- end
102
-
103
- #
104
- # Shortcut for <tt>get_encoder(encoder).encode(source,options)</tt>
105
- #
106
- def encode(encoder, src, options=nil)
107
- if String===encoder then
108
- ename, encoder = encoder, get_encoder(encoder)
109
- raise(ArgumentError,"No such encoder: #{ename}") if encoder.nil?
110
- end
111
- raise(ArgumentError,"Invalid encoder: #{encoder}") unless Encoder===encoder
112
- encoder.encode(src, options)
113
- end
114
-
115
- # Returns a string with comma separated encoder names.
116
- def to_s
117
- @encoders.keys.join(", ")
118
- end
119
-
120
- end # class EncoderSet
121
-
122
- end
@@ -1,80 +0,0 @@
1
- module WLang
2
-
3
- # Main error of all WLang errors.
4
- class Error < StandardError
5
-
6
- # The parser state whe this error has been raised
7
- attr_accessor :parser_state
8
-
9
- # Optional cause (other lower level exception)
10
- attr_accessor :cause
11
-
12
- # Creates an error instance with a given parser state
13
- def initialize(msg = nil, parser_state = nil, cause = nil)
14
- raise ArgumentError, "msg expected to be nil or a String" unless (msg.nil? or String===msg)
15
- raise ArgumentError, "parser_state expected to be nil or a State"\
16
- unless (parser_state.nil? or ::WLang::Parser::State===parser_state)
17
- super(msg)
18
- @parser_state = parser_state
19
- @cause = cause
20
- end
21
-
22
- # Returns a friendly wlang backtrace
23
- def wlang_backtrace
24
- parser_state ? parser_state.backtrace : ["no backtrace information, sorry"]
25
- end
26
-
27
- end # class Error
28
-
29
- #
30
- # Raised by hosted languages when something fails during
31
- # evaluation.
32
- #
33
- class EvalError < ::WLang::Error
34
-
35
- # The expression whose evaluation failed
36
- attr_accessor :expression
37
-
38
- # Creates an error instance with an optional expression that
39
- # failed
40
- def initialize(msg = nil, parser_state = nil, expression = nil, cause = nil)
41
- super(msg, parser_state, cause)
42
- @expression = expression
43
- end
44
-
45
- def to_s
46
- "Evaluation of #{@expression} failed, #{@cause ? @cause.message : ''}"
47
- end
48
-
49
- end # class EvalError
50
-
51
- #
52
- # Raised when a variable may not be found in the current
53
- # parser scope
54
- #
55
- class UndefinedVariableError < ::WLang::EvalError
56
-
57
- # Name of the variable that could not be found
58
- attr_accessor :variable
59
-
60
- # Creates an error instance with an optional variable name
61
- def initialize(msg = nil, parser_state = nil, expression = nil, variable = nil)
62
- super(msg, parser_state, expression)
63
- @variable = variable
64
- end
65
-
66
- def to_s
67
- "Unable to find variable #{@variable}"
68
- end
69
-
70
- end # class UndefinedVariableError
71
-
72
- # Error raised by a WLang parser instanciation when an error occurs.
73
- class ParseError < ::WLang::Error
74
-
75
- # Where did the parsing failed
76
- attr_accessor :line, :column
77
-
78
- end # class ParseError
79
-
80
- end # module WLang
@@ -1,13 +0,0 @@
1
- class Hash
2
-
3
- # Allows using hash.key as a synonym for hash[:key] and
4
- # hash['key']
5
- def method_missing(name, *args, &block)
6
- if args.empty? and block.nil?
7
- self[name] || self[name.to_s]
8
- else
9
- super(name, *args, &block)
10
- end
11
- end
12
-
13
- end
@@ -1,44 +0,0 @@
1
- #
2
- # Installs _wlang_ utility methods on Ruby String.
3
- #
4
- class String
5
-
6
- # Converts the string to a wlang template
7
- def wlang_template(dialect = "wlang/active-string", block_symbols = :braces)
8
- WLang::template(self, dialect, block_symbols)
9
- end
10
-
11
- #
12
- # Instantiates the string as a wlang template using
13
- # a context object and a dialect.
14
- #
15
- def wlang_instantiate(context = nil, dialect = "wlang/active-string", block_symbols = :braces)
16
- WLang::instantiate(self, context, dialect, block_symbols)
17
- end
18
- alias :wlang :wlang_instantiate
19
-
20
- # Computes the column number for a given offset in
21
- # this string
22
- def __wlang_column_of(index)
23
- return 1 if index == 0
24
- newline_index = rindex("\n", index - 1)
25
- if newline_index
26
- index - newline_index
27
- else
28
- index + 1
29
- end
30
- end
31
-
32
- # Computes the line number for a given offset in
33
- # this string
34
- def __wlang_line_of(index)
35
- self[0...index].count("\n") + 1
36
- end
37
-
38
- def __wlang_realign(offset, strip_first = false)
39
- s = gsub(/^/, ' ' * offset)
40
- strip_first ? s.gsub(/\A\s*/, "") : s
41
- end
42
-
43
- end
44
-
@@ -1,89 +0,0 @@
1
- require 'delegate'
2
- module WLang
3
- #
4
- # Implements a scoping mechanism on top of a ruby hash (accessible through pairing).
5
- # Such a scope mimics hashses for has_key?, [] and []= methods. A scope has an
6
- # accessible parent. Scopes form a tree, the root being accessible using its
7
- # natural accessor. Scope lookup (has_key? and []) uses the hierarchy to find
8
- # accessible variables.
9
- #
10
- # Branching a scope allows installing new variables that hide variables with the
11
- # same name in the parent scope. Branching is made easy through the branch methods
12
- # that accepts a block, passing the child as first argument:
13
- #
14
- # scope = HashScope.new(:name => 'wlang')
15
- # puts scope[:name] # prints 'wlang'
16
- # scope.branch(:name => 'other') do |child|
17
- # puts child[:name] # prints 'other'
18
- # end
19
- # puts scope[:name] # prints 'wlang'
20
- #
21
- # This branching mechanism is intended to be used to keep a current scope as instance
22
- # variable of a using class:
23
- #
24
- # # We create an initial scope at construction
25
- # def initialize
26
- # @scope = HashScope.new
27
- # end
28
- #
29
- # # Appends the current scope with new key/value pairs. Yields the block
30
- # # with the new scope and restore the original one after that.
31
- # def do_something_with_a_new_scope(hash = {})
32
- # @scope = @scope.branch(:name => 'other')
33
- # yield if block_given?
34
- # @scope = @scope.parent
35
- # end
36
- #
37
- class HashScope
38
-
39
- # The parent scope, or nil if no such parent
40
- attr_reader :parent
41
-
42
- # The key/value pairing inside this scope
43
- attr_reader :pairing
44
-
45
- # Creates a scope instance with a parent and initial
46
- # pairing through a Hash
47
- def initialize(pairing = nil, parent = nil)
48
- raise ArgumentError, "Hash expected for pairing #{pairing.class} received" unless (pairing.nil? or Hash===pairing)
49
- @pairing = pairing || {}
50
- @parent = parent
51
- end
52
-
53
- # Returns the root scope
54
- def root
55
- @root ||= (parent ? parent.root : self)
56
- end
57
-
58
- # Checks if a key exists in this scope, delegating to
59
- # parent if not found and allowed
60
- def has_key?(key, delegate = true)
61
- pairing.has_key?(key) || (!delegate.nil? && !parent.nil? && parent.has_key?(key))
62
- end
63
-
64
- # Returns the value associated to a key, delegating to parent
65
- # if not found and allowed
66
- def [](key, delegate = true)
67
- pairing.has_key?(key) ? pairing[key] : (delegate && parent && parent[key])
68
- end
69
-
70
- # Associates a key to a value inside this scope
71
- def []=(key, value)
72
- pairing[key] = value
73
- end
74
-
75
- # Creates a new child scope and returns it. If a block is given,
76
- # yields the block with the child scope
77
- def branch(pairing = nil)
78
- child = HashScope.new(pairing, self)
79
- yield child if block_given?
80
- child
81
- end
82
-
83
- # Converts this scope to a full hash with all variables
84
- def to_h
85
- parent ? parent.to_h.merge(pairing) : pairing.dup
86
- end
87
-
88
- end # class HashScope
89
- end # module WLang
@@ -1,146 +0,0 @@
1
- module WLang
2
- #
3
- # Implements the hosted language abstraction of WLang. The hosted language is
4
- # mainly responsible of evaluating expressions (see evaluate). This abstraction
5
- # may be implemented by a user's own class, providing that it respected the
6
- # evaluate method specification.
7
- #
8
- # This default implementation implements the ruby hosted language. It works
9
- # with ::WLang::HostedLanguage::DSL, which uses instance_eval for evaluating
10
- # the expression. Calls to missing methods (without parameter and block) are
11
- # converted in scope lookups. The DSL class is strictly private, as it uses
12
- # a somewhat complex ruby introspection mechanism to ensure that scoping will
13
- # not be perturbated by Kernel methods and Object private methods even if
14
- # additional gems are loaded later.
15
- #
16
- # If you want to intall low-priority variables and tools available in all wlang
17
- # templates (global scoping) you can reopen the HostedLanguage class itself and
18
- # override variable_missing. Note that "low-priority" means that these methods
19
- # will be hidden if a user installs a variable with the same name in its template.
20
- #
21
- # class WLang::HostedLanguage
22
- #
23
- # # Low-priority now variable
24
- # def now
25
- # Time.now
26
- # end
27
- #
28
- # # Low-priority variables are checked before raising an UndefinedVariableError
29
- # def variable_missing(name)
30
- # case name
31
- # when :who, ...
32
- # self.send(name)
33
- # else
34
- # raise ::WLang::UndefinedVariableError.new(nil, nil, nil, name)
35
- # end
36
- # end
37
- #
38
- # end
39
- #
40
- # This class is thread safe, meaning that the same hosting language instance may be
41
- # safely shared by concurrent wlang parsers. Extending or re-opening this class and using
42
- # instance variables will make it non thread-safe.
43
- #
44
- class HostedLanguage
45
-
46
- # The hosted language DSL, interpreting expressions
47
- class DSL
48
-
49
- # Methods that we keep
50
- KEPT_METHODS = [ "__send__", "__id__", "instance_eval", "initialize", "object_id",
51
- "singleton_method_added", "singleton_method_undefined", "method_missing",
52
- "__evaluate__", "knows?"]
53
-
54
- class << self
55
- def __clean_scope__
56
- # Removes all methods that are not needed to the class
57
- (instance_methods + private_instance_methods).each do |m|
58
- m_to_s = m.to_s
59
- undef_method(m_to_s.to_sym) unless ('__' == m_to_s[0..1]) or KEPT_METHODS.include?(m_to_s)
60
- end
61
- end
62
- end
63
-
64
- # Creates a DSL instance for a given hosted language and
65
- # parser state
66
- def initialize(hosted, parser_state)
67
- @hosted, @parser_state = hosted, parser_state
68
- class << self
69
- __clean_scope__
70
- end
71
- end
72
-
73
- # Delegates the missing lookup to the current parser scope or raises an
74
- # UndefinedVariableError (calls @hosted.variable_missing precisely)
75
- def method_missing(name, *args, &block)
76
- if @parser_state and args.empty? and block.nil?
77
- if effname = knows?(name)
78
- @parser_state.scope[effname]
79
- else
80
- @hosted.variable_missing(name)
81
- end
82
- else
83
- super(name, *args, &block)
84
- end
85
- end
86
-
87
- # Checks if a variable is known in the current parser scope
88
- def knows?(name)
89
- if @parser_state.scope.has_key?(name)
90
- name
91
- elsif @parser_state.scope.has_key?(name.to_s)
92
- name.to_s
93
- else
94
- nil
95
- end
96
- end
97
-
98
- # Evaluates an expression
99
- def __evaluate__(__expression__)
100
- __result__ = instance_eval(__expression__)
101
-
102
- # backward compatibility with >= 0.8.4 where 'using self'
103
- # was allowed. This will be removed in wlang 1.0.0
104
- if __result__.object_id == self.object_id
105
- Kernel.puts "Warning: using deprecated 'using self' syntax (#{@parser_state.where})\n"\
106
- "will be removed in wlang 1.0.0. Use 'share all', extends "\
107
- "::WLang::HostedLanguage::DSL with useful methods or create your own"\
108
- " hosted language."
109
- __result__ = @parser_state.scope.to_h
110
- end
111
-
112
- __result__
113
- rescue ::WLang::Error => ex
114
- ex.parser_state = @parser_state
115
- ex.expression = __expression__ if ex.respond_to?(:expression=)
116
- Kernel.raise ex
117
- rescue Exception => ex
118
- Kernel.raise ::WLang::EvalError.new(ex.message, @parser_state, __expression__, ex)
119
- end
120
-
121
- end # class DSL
122
-
123
- #
124
- # Called when a variable cannot be found (name is a Symbol object). This default
125
- # implementation raises an UndefinedVariableError. This method is intended to be
126
- # overriden for handling such a situation more friendly or for installing
127
- # low-priority global variables (see class documentation).
128
- #
129
- def variable_missing(name)
130
- raise ::WLang::UndefinedVariableError.new(nil, nil, nil, name)
131
- end
132
-
133
- #
134
- # Evaluates a given expression in the context of a given
135
- # parser state.
136
- #
137
- # This method should always raise
138
- # - an UndefinedVariableError when a given template variable cannot be found.
139
- # - an EvalError when something more severe occurs
140
- #
141
- def evaluate(expression, parser_state)
142
- ::WLang::HostedLanguage::DSL.new(self, parser_state).__evaluate__(expression)
143
- end
144
-
145
- end # class HostedLanguage
146
- end # module WLang