Class: BBSexp::Compiler
- Inherits:
-
Object
- Object
- BBSexp::Compiler
- Defined in:
- lib/bbsexp/compiler.rb
Instance Method Summary collapse
- #build ⇒ Object
- #eval_exp(exp) ⇒ Object
- #eval_string(string) ⇒ Object
-
#initialize(parser, text) ⇒ Compiler
constructor
A new instance of Compiler.
- #register(token) ⇒ Object
- #terminate(token) ⇒ Object
- #tokens {|[:string, scanner.rest]| ... } ⇒ Object
Constructor Details
#initialize(parser, text) ⇒ Compiler
Returns a new instance of Compiler.
3 4 5 6 7 8 9 10 11 |
# File 'lib/bbsexp/compiler.rb', line 3 def initialize(parser, text) @parser = parser @text = text @result = '' @stack = [] @func_stack = [] @state = [3] @locks = Hash[ @parser.exps.keys.map{|k| [k, false] } ] end |
Instance Method Details
#build ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/bbsexp/compiler.rb', line 13 def build @result << tokens.map do |type, value| case type when :string then eval_string value when :exp then eval_exp value end end.join # close unclosed expressions @result << @stack.reverse.map {|token| token.reverse.map {|exp| @parser.exps[exp]..last }.join }.join end |
#eval_exp(exp) ⇒ Object
44 45 46 47 48 49 50 51 52 53 |
# File 'lib/bbsexp/compiler.rb', line 44 def eval_exp(exp) # dont parse if we are in the no parse zone return eval_string(@parser.brackets(exp)) if @state.last == 0 and not exp.include? @parser.no_parse # process expressions unless exp[0] == @parser.end_exp register(exp) #returns start tags else terminate(exp) #returns end tags end end |
#eval_string(string) ⇒ Object
39 40 41 42 |
# File 'lib/bbsexp/compiler.rb', line 39 def eval_string(string) # run callbacks on string @func_stack.reduce(string) {|memo, func| func.(memo) } end |
#register(token) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/bbsexp/compiler.rb', line 55 def register(token) @stack << active_exps = # append valid expressions to the stack token.chars.to_a.uniq.select do |exp| # ignore redundant and illegal expressions @locks[exp] == false and @parser.exps[exp] <= @state.last end.sort do |a,b| @parser.exps[b] <=> @parser.exps[a] # sort nocode > block > inline end.map do |exp| @locks[exp] = true # lock this expression to prevent its use deeper in the stack @state << @parser.exps[exp].state # set parser state to current element's level exp # return to token.active_exps as a valid expression end @func_stack += active_exps.map {|exp| @parser.exps[exp].block }.compact # return the start tags for the token active_exps.map {|exp| @parser.exps[exp]..first }.join end |
#terminate(token) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/bbsexp/compiler.rb', line 73 def terminate(token) return @parser.brackets(token) if @stack.empty? # don't do anything if the stack is empty token.chars.map do |close| if exps = @stack.pop exps.map do |exp| @locks[exp] = false # unlock this expression so it can be used again @state.pop # return parser state to parent scope @func_stack.pop if @parser.exps[exp].block # disable function @parser.exps[exp]..last # return end tag end.reverse.join end end.join end |
#tokens {|[:string, scanner.rest]| ... } ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/bbsexp/compiler.rb', line 27 def tokens return to_enum(:tokens) unless block_given? scanner = StringScanner.new(@text) while string = scanner.scan_until(@parser.regexp) exp = scanner.matched yield [:string, string[0..-(exp.size + 1)]] unless string == exp yield [:exp, exp[1..-2]] end yield [:string, scanner.rest] unless scanner.eos? end |