aboutsummaryrefslogtreecommitdiff
path: root/build2/cc/lexer.hxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-05-27 15:24:25 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-05-27 15:24:25 +0200
commit2e19434e09b819105055ddc8e58f69db98ec8669 (patch)
treee806e15f6e940a9135f0e7d8cf9ba08637512bd8 /build2/cc/lexer.hxx
parentde417f02b2b1f3a02c5c9d206f399c574a93bf7f (diff)
Handle #line directives in C/C++ lexer
This way the parser now reports logical rather than physical location in diagnostics.
Diffstat (limited to 'build2/cc/lexer.hxx')
-rw-r--r--build2/cc/lexer.hxx38
1 files changed, 22 insertions, 16 deletions
diff --git a/build2/cc/lexer.hxx b/build2/cc/lexer.hxx
index 7865a4e..8767606 100644
--- a/build2/cc/lexer.hxx
+++ b/build2/cc/lexer.hxx
@@ -22,8 +22,10 @@ namespace build2
//
// The input is a (partially-)preprocessed translation unit that may still
// contain comments, line continuations, and preprocessor directives such
- // as #line, #pragma, etc. Currently all preprocessor directives are
- // discarded and no values are saved for literals.
+ // as #line, #pragma, etc., but not #include's. Currently all preprocessor
+ // directives except #line are ignored and no values are saved from
+ // literals. The #line directive (and its shorthand notation) is
+ // recognized to provide the logical token location.
//
enum class token_type
{
@@ -51,6 +53,7 @@ namespace build2
token_type type;
string value;
+ path file;
uint64_t line;
uint64_t column;
@@ -74,7 +77,10 @@ namespace build2
{
public:
lexer (istream& is, const path& name)
- : char_scanner (is, false), name_ (name), fail ("error", &name_) {}
+ : char_scanner (is, false),
+ name_ (name),
+ fail ("error", &name_),
+ log_file_ (name) {}
const path&
name () const {return name_;}
@@ -121,6 +127,9 @@ namespace build2
void
literal_suffix (xchar);
+ void
+ line_directive (token&, xchar);
+
xchar
skip_spaces (bool newline = true);
@@ -134,7 +143,7 @@ namespace build2
get (bool escape = true);
void
- get (const xchar& peeked) {base::get (peeked);}
+ get (const xchar& peeked);
xchar
peek (bool escape = true);
@@ -142,23 +151,20 @@ namespace build2
private:
const path name_;
const fail_mark fail;
+
+ // Logical file and line as set by the #line directives. Note that the
+ // lexer diagnostics still uses the physical file/lines.
+ //
+ path log_file_;
+ optional<uint64_t> log_line_;
};
- // Diagnostics plumbing. We assume that any diag stream for which we can
- // use token as location has its aux data pointing to pointer to path.
+ // Diagnostics plumbing.
//
inline location
- get_location (const token& t, const path& p)
- {
- return location (&p, t.line, t.column);
- }
-
- inline location
- get_location (const token& t, const void* data)
+ get_location (const token& t, const void*)
{
- assert (data != nullptr); // E.g., must be &parser::path_.
- const path* p (*static_cast<const path* const*> (data));
- return get_location (t, *p);
+ return location (&t.file, t.line, t.column);
}
}
}