wlang 0.10.2 → 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
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