brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 1 | class QStmt |
| 2 | def set_line(val) |
| 3 | @file_line = val |
| 4 | return self |
| 5 | end |
| 6 | def q_stack_name() |
| 7 | @file_line |
| 8 | end |
| 9 | def self.method_added(name) |
| 10 | @wrapped ||= {} |
| 11 | return if(name != :q_eval && name != :q_eval_extern) |
| 12 | return if(@wrapped[name]) |
| 13 | @wrapped[name] = true |
| 14 | method = self.instance_method(name) |
| 15 | define_method(name) do |*args,&blk| |
| 16 | begin |
| 17 | method.bind(self).call(*args,&blk) |
| 18 | rescue QError => e |
| 19 | e.qstacktrace << self |
| 20 | raise e |
| 21 | end |
| 22 | end |
| 23 | end |
| 24 | |
| 25 | end |
| 26 | class ImportStmt < QStmt |
| 27 | def initialize(filename) |
| 28 | @filename = filename |
| 29 | end |
| 30 | def q_eval(locals) |
| 31 | filename = locals.globals.find_file(@filename) |
| 32 | #puts "importing #{filename.inspect}" |
| 33 | q_file = QFile.parse(filename) |
| 34 | q_output = q_file.q_eval_extern(locals.globals) |
| 35 | q_output.extern = true |
| 36 | return Target::QInclude.new(@filename + ".h") |
| 37 | end |
| 38 | def self.parse(tokens) |
| 39 | line = tokens.pos |
| 40 | to_import = (tokens.expect(:tString) do |token| |
| 41 | <<ERROR_MSG |
| 42 | I found a #{token.humanize} at #{token.pos}. |
| 43 | \tI was really looking for a "filename" for this import statement. |
| 44 | \tSomething like: import "super_cool_file"; |
| 45 | \tWot.Wot |
| 46 | ERROR_MSG |
| 47 | end).data |
| 48 | tokens.expect(:tSemi) do |token| |
| 49 | <<ERROR_MSG |
| 50 | I found a #{token.humanize} at #{token.pos}. |
| 51 | \tI was really looking for a ";" to finish off this import statement |
| 52 | \tat line #{line}; |
| 53 | \tSomething like: import #{to_import.inspect}; |
| 54 | \tWot.Wot #{" "*to_import.inspect.length}^ |
| 55 | ERROR_MSG |
| 56 | end |
| 57 | return self.new(to_import).set_line(line) |
| 58 | end |
| 59 | end |
| 60 | class PackageStmt < QStmt |
| 61 | def initialize(name) |
| 62 | @name = name |
| 63 | end |
| 64 | def q_eval(locals) |
| 65 | locals.package = @name |
| 66 | return nil |
| 67 | end |
| 68 | def self.parse(tokens) |
| 69 | line = tokens.pos |
| 70 | qualified_name = QualifiedName.parse(tokens) |
| 71 | tokens.expect(:tSemi) |
| 72 | return self.new(qualified_name).set_line(line) |
| 73 | end |
| 74 | end |
| 75 | class QFile |
| 76 | attr_accessor :namespace |
| 77 | def initialize(filename,suite) |
| 78 | @filename,@suite = filename,suite |
| 79 | end |
| 80 | def q_eval(globals = Globals.new()) |
| 81 | local_pos = LocalSituation.new(globals) |
| 82 | q_file = Target::QFile.new() |
| 83 | @suite.each do |name| |
| 84 | val = name.q_eval(local_pos) |
| 85 | if(val) |
| 86 | if(val.respond_to?(:create)) |
| 87 | q_file.add_type(val) |
| 88 | end |
| 89 | end |
| 90 | end |
| 91 | @namespace = local_pos.local |
| 92 | return q_file |
| 93 | end |
| 94 | def q_eval_extern(globals) |
| 95 | local_pos = LocalSituation.new(globals) |
| 96 | q_file = Target::QFile.new() |
| 97 | @suite.each do |name| |
| 98 | if(name.respond_to?(:q_eval_extern)) |
| 99 | val = name.q_eval_extern(local_pos) |
| 100 | else |
| 101 | val = name.q_eval(local_pos) |
| 102 | end |
| 103 | if(val) |
| 104 | if(val.respond_to?(:create)) |
| 105 | q_file.add_type(val) |
| 106 | end |
| 107 | end |
| 108 | end |
| 109 | return q_file |
| 110 | end |
| 111 | def self.parse(filename) |
| 112 | tokens = Tokenizer.new(filename) |
| 113 | suite = [] |
| 114 | while(tokens.peak != :tEnd) |
| 115 | token = tokens.expect(:tWord) do |token| #symbol |
| 116 | <<ERROR_MSG |
| 117 | I found a #{token.humanize} at #{token.pos}. |
| 118 | \tI was really looking for a "package", "import", "queue_group", |
| 119 | \t"message", or "queue" statement to get things moving. |
| 120 | \tSomething like: import "super_cool_file"; |
| 121 | \tWot.Wot |
| 122 | ERROR_MSG |
| 123 | end |
| 124 | case token.data |
| 125 | when "package" |
| 126 | suite << PackageStmt.parse(tokens) |
| 127 | when "import" |
| 128 | suite << ImportStmt.parse(tokens) |
| 129 | when "queue_group" |
| 130 | suite << QueueGroupStmt.parse(tokens) |
| 131 | when "message" |
| 132 | suite << MessageStmt.parse(tokens) |
| 133 | when "queue" |
| 134 | suite << QueueStmt.parse(tokens) |
| 135 | when "interface" |
| 136 | suite << InterfaceStmt.parse(tokens) |
Parker Schuh | 343481e | 2014-02-09 18:28:43 -0800 | [diff] [blame] | 137 | when "struct" |
| 138 | suite << StructStmt.parse(tokens) |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 139 | else |
| 140 | tokens.qError(<<ERROR_MSG) |
Brian Silverman | 61e41fd | 2014-02-16 19:08:50 -0800 | [diff] [blame] | 141 | expected a "package","import","queue","struct","queue_group", or "message" statement rather |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 142 | than a #{token.data.inspect}, (whatever that is?) |
| 143 | oh! no! a feature request!? |
| 144 | Wot. Wot. |
| 145 | ERROR_MSG |
| 146 | end |
| 147 | end |
| 148 | return self.new(filename,suite) |
| 149 | end |
| 150 | end |