From: Mikko Rasa Date: Fri, 21 Jun 2019 11:27:32 +0000 (+0300) Subject: Record statement source lines and emit #line directives to output X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=71972b08fd031e177a005eb1924a5c7a15459291 Record statement source lines and emit #line directives to output --- diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 50e4f585..518b31e1 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -58,7 +58,7 @@ void ProgramCompiler::compile(const string &source, const string &src_name) module = new Module(); ProgramParser parser; imported_names.insert(src_name); - append_module(parser.parse(source, src_name)); + append_module(parser.parse(source, src_name, 1)); process(); } @@ -69,7 +69,7 @@ void ProgramCompiler::compile(IO::Base &io, Resources *res, const string &src_na module = new Module(); ProgramParser parser; imported_names.insert(src_name); - append_module(parser.parse(io, src_name)); + append_module(parser.parse(io, src_name, 1)); process(); } @@ -199,7 +199,7 @@ void ProgramCompiler::import(const string &name) if(!io) throw runtime_error(format("module %s not found", name)); ProgramParser import_parser; - append_module(import_parser.parse(*io, fn)); + append_module(import_parser.parse(*io, fn, imported_names.size())); } void ProgramCompiler::generate(Stage &stage) @@ -307,6 +307,7 @@ void ProgramCompiler::BlockModifier::visit(Block &block) ProgramCompiler::Formatter::Formatter(): + source_line(1), indent(0), parameter_list(false) { } @@ -335,11 +336,34 @@ void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s) void ProgramCompiler::Formatter::append(const string &text) { formatted += text; + for(string::const_iterator i=text.begin(); i!=text.end(); ++i) + if(*i=='\n') + ++source_line; } void ProgramCompiler::Formatter::append(char c) { formatted += c; + if(c=='\n') + ++source_line; +} + +void ProgramCompiler::Formatter::set_source(unsigned index, unsigned line) +{ + if(index!=source_index || (index && line!=source_line)) + { + if(index==source_index && line==source_line+1) + formatted += '\n'; + else + { + unsigned l = line; + if(stage->required_versionsource, (*i)->line); append(spaces); (*i)->visit(*this); } @@ -549,7 +574,9 @@ void ProgramCompiler::Formatter::visit(Conditional &cond) Conditional *else_cond = dynamic_cast(cond.else_body.body.front().get()); if(cond.else_body.body.size()==1 && else_cond) { - append(format("\n%selse ", string(indent*2, ' '))); + append('\n'); + set_source(else_cond->source, else_cond->line); + append(format("%selse ", string(indent*2, ' '))); else_cond->visit(*this); } else diff --git a/source/programcompiler.h b/source/programcompiler.h index 9c20e090..697c6086 100644 --- a/source/programcompiler.h +++ b/source/programcompiler.h @@ -44,6 +44,8 @@ private: typedef std::string ResultType; std::string formatted; + unsigned source_index; + unsigned source_line; unsigned indent; bool parameter_list; std::string block_interface; @@ -55,6 +57,7 @@ private: using Visitor::visit; void append(const std::string &); void append(char); + void set_source(unsigned, unsigned); virtual void visit(ProgramSyntax::Block &); virtual void visit(ProgramSyntax::Literal &); virtual void visit(ProgramSyntax::ParenthesizedExpression &); diff --git a/source/programparser.cpp b/source/programparser.cpp index 39393662..ca554f42 100644 --- a/source/programparser.cpp +++ b/source/programparser.cpp @@ -70,18 +70,20 @@ ProgramParser::~ProgramParser() delete module; } -Module &ProgramParser::parse(const string &s, const string &n) +Module &ProgramParser::parse(const string &s, const string &n, unsigned i) { source = s; source_name = n; + source_index = i; parse_source(); return *module; } -Module &ProgramParser::parse(IO::Base &io, const string &n) +Module &ProgramParser::parse(IO::Base &io, const string &n, unsigned i) { source = string(); source_name = n; + source_index = i; while(!io.eof()) { char buffer[4096]; @@ -443,6 +445,8 @@ RefPtr ProgramParser::parse_global_declaration() if(is_interface_qualifier(token) && peek_token(1)==";") { RefPtr iface_lo = new InterfaceLayout; + iface_lo->source = source_index; + iface_lo->line = current_line; iface_lo->layout.qualifiers = layout->qualifiers; iface_lo->interface = parse_token(); expect(";"); @@ -496,6 +500,8 @@ RefPtr ProgramParser::parse_statement() else if(token=="break" || token=="continue" || token=="discard") { RefPtr jump = new Jump; + jump->source = source_index; + jump->line = current_line; jump->keyword = parse_token(); expect(";"); @@ -506,6 +512,8 @@ RefPtr ProgramParser::parse_statement() else if(!token.empty()) { RefPtr expr = new ExpressionStatement; + expr->source = source_index; + expr->line = current_line; expr->expression = parse_expression(); expect(";"); @@ -522,6 +530,8 @@ RefPtr ProgramParser::parse_import() expect("import"); RefPtr import = new Import; + import->source = source_index; + import->line = current_line; import->module = expect_identifier(); expect(";"); return import; @@ -531,6 +541,8 @@ RefPtr ProgramParser::parse_precision() { expect("precision"); RefPtr precision = new Precision; + precision->source = source_index; + precision->line = current_line; precision->precision = parse_token(); if(!is_precision_qualifier(precision->precision)) @@ -717,6 +729,8 @@ RefPtr ProgramParser::parse_struct_declaration() { expect("struct"); RefPtr strct = new StructDeclaration; + strct->source = source_index; + strct->line = current_line; strct->name = expect_identifier(); parse_block(strct->members, true); @@ -729,6 +743,8 @@ RefPtr ProgramParser::parse_struct_declaration() RefPtr ProgramParser::parse_variable_declaration() { RefPtr var = new VariableDeclaration; + var->source = source_index; + var->line = current_line; string token = peek_token(); while(is_qualifier(token)) @@ -770,6 +786,8 @@ RefPtr ProgramParser::parse_variable_declaration() RefPtr ProgramParser::parse_function_declaration() { RefPtr func = new FunctionDeclaration; + func->source = source_index; + func->line = current_line; func->return_type = expect_type(); func->name = expect_identifier(); @@ -806,6 +824,8 @@ RefPtr ProgramParser::parse_function_declaration() RefPtr ProgramParser::parse_interface_block() { RefPtr iface = new InterfaceBlock; + iface->source = source_index; + iface->line = current_line; iface->interface = parse_token(); if(!is_interface_qualifier(iface->interface)) @@ -830,8 +850,10 @@ RefPtr ProgramParser::parse_interface_block() RefPtr ProgramParser::parse_conditional() { expect("if"); - expect("("); RefPtr cond = new Conditional; + cond->source = source_index; + cond->line = current_line; + expect("("); cond->condition = parse_expression(); expect(")"); @@ -850,8 +872,10 @@ RefPtr ProgramParser::parse_conditional() RefPtr ProgramParser::parse_for() { expect("for"); - expect("("); RefPtr loop = new Iteration; + loop->source = source_index; + loop->line = current_line; + expect("("); string token = peek_token(); if(is_type(token)) loop->init_statement = parse_statement(); @@ -880,8 +904,10 @@ RefPtr ProgramParser::parse_for() RefPtr ProgramParser::parse_while() { expect("while"); - expect("("); RefPtr loop = new Iteration; + loop->source = source_index; + loop->line = current_line; + expect("("); loop->condition = parse_expression(); expect(")"); @@ -894,6 +920,8 @@ RefPtr ProgramParser::parse_passthrough() { expect("passthrough"); RefPtr pass = new Passthrough; + pass->source = source_index; + pass->line = current_line; if(cur_stage->type==GEOMETRY) { expect("["); @@ -908,6 +936,8 @@ RefPtr ProgramParser::parse_return() { expect("return"); RefPtr ret = new Return; + ret->source = source_index; + ret->line = current_line; if(peek_token()!=";") ret->expression = parse_expression(); expect(";"); diff --git a/source/programparser.h b/source/programparser.h index 72817e7e..dc94bd00 100644 --- a/source/programparser.h +++ b/source/programparser.h @@ -38,6 +38,7 @@ private: std::string source; std::string source_name; + unsigned source_index; unsigned current_line; std::string::const_iterator iter; std::string::const_iterator source_end; @@ -55,8 +56,8 @@ public: ProgramParser(); ~ProgramParser(); - ProgramSyntax::Module &parse(const std::string &, const std::string &); - ProgramSyntax::Module &parse(IO::Base &, const std::string &); + ProgramSyntax::Module &parse(const std::string &, const std::string &, unsigned = 0); + ProgramSyntax::Module &parse(IO::Base &, const std::string &, unsigned = 0); private: void parse_source(); diff --git a/source/programsyntax.cpp b/source/programsyntax.cpp index edd38eaa..6dea029f 100644 --- a/source/programsyntax.cpp +++ b/source/programsyntax.cpp @@ -15,6 +15,12 @@ NodeContainer::NodeContainer(const NodeContainer &c): } +Statement::Statement(): + source(0), + line(1) +{ } + + Block::Block(): use_braces(false) { } diff --git a/source/programsyntax.h b/source/programsyntax.h index 3db059c4..59042951 100644 --- a/source/programsyntax.h +++ b/source/programsyntax.h @@ -66,6 +66,11 @@ struct FunctionDeclaration; struct Statement: Node { + unsigned source; + unsigned line; + + Statement(); + virtual Statement *clone() const = 0; };