Class: Sprout::FCSHLexer
- Inherits:
-
Object
- Object
- Sprout::FCSHLexer
- Defined in:
- lib/sprout/fcsh_lexer.rb
Overview
This class should allow us to parse the stream output that FCSH provides. It was largely inspired by “LittleLexer” (rubyforge.org/projects/littlelexer/) which is a beautiful and concise general purpose lexer written by John Carter. Unfortunately, LittleLexer did not support streamed input, which we definitely need.
Constant Summary collapse
- PROMPT =
':prompt'
- WARNING =
':warning'
- ERROR =
':error'
- PRELUDE =
':prelude'
- PRELUDE_EXPRESSION =
/(Adobe Flex Compiler.*\n.*\nCopyright.*\n)/m
Instance Method Summary collapse
-
#initialize(out = nil) ⇒ FCSHLexer
constructor
A new instance of FCSHLexer.
- #scan_process(process_runner) ⇒ Object
-
#scan_stream(reader) ⇒ Object
We need to scan the stream as FCSH writes to it.
Constructor Details
#initialize(out = nil) ⇒ FCSHLexer
Returns a new instance of FCSHLexer.
39 40 41 42 43 44 45 46 47 |
# File 'lib/sprout/fcsh_lexer.rb', line 39 def initialize(out=nil) @out = out || $stdout @regex_to_token = [ [/(.*Warning:.*\^.*)\n/m, WARNING], # Warning encountered [/(.*Error:.*\^.*)\n/m, ERROR], # Error encountered [PRELUDE_EXPRESSION, PRELUDE], [/\n\(fcsh\)/, PROMPT] # Prompt for input ] end |
Instance Method Details
#scan_process(process_runner) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/sprout/fcsh_lexer.rb', line 49 def scan_process(process_runner) tokens = []; # Collect Errors and Warnings in a way that doesn't # Block forever when we have none.... t = Thread.new { scan_stream(process_runner.e) do |token| yield token if block_given? tokens << token end } # Collect stdout from the process: scan_stream(process_runner.r) do |token| yield token if block_given? tokens << token end process_runner.e.sync = true # GROSS HACK! # It seems we need to wait # for the fsch $stderr buffer to flush? # There must be a better way... Anyone? # Should we move to Highline for interactive # shell applications? # http://rubyforge.org/projects/highline/ # In fact - this problem actually ruins # the entire implementation, the larger/longer # it takes for errors to be bufferred, the more # likely it is we'll return without displaying them. # The only way to overcome this with the current # implementation, is to increase the timeout so that # FCSH takes a long, long time on every compilation!!! sleep(0.2) t.kill return tokens end |
#scan_stream(reader) ⇒ Object
We need to scan the stream as FCSH writes to it. Since FCSH is a persistent CLI application, it never sends an EOF or even a consistent EOL. In order to tokenize the output, we need to attempt to check tokens with each character added. scan_stream will block and read characters from the reader provided until it encounters a PROMPT token, at that time, it will return an array of all tokens found. It will additionally yield each token as it’s found if a block is provided.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/sprout/fcsh_lexer.rb', line 96 def scan_stream(reader) tokens = [] partial = '' index = 0 while(true) do code = reader.getc return if code.nil? partial << code.chr token = next_token(partial) if(token) tokens << token yield token if block_given? partial = '' break if(token[:name] == PROMPT || token[:name] == ERROR) end end return tokens end |