aboutsummaryrefslogtreecommitdiff
path: root/build/lexer
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-09-08 13:28:26 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-09-08 13:43:26 +0200
commitb5940dd5562bfa12d6d76dceb61540b4480a4982 (patch)
tree1e8095300b5413ca510baa10bcb840101b06417c /build/lexer
parentefd76ff778c0b7b1f8cb9e0485bb9b4b62b149a7 (diff)
Use mode stack in lexer
Diffstat (limited to 'build/lexer')
-rw-r--r--build/lexer34
1 files changed, 27 insertions, 7 deletions
diff --git a/build/lexer b/build/lexer
index 9a0582d..1e253fd 100644
--- a/build/lexer
+++ b/build/lexer
@@ -7,7 +7,9 @@
#include <string>
#include <iosfwd>
+#include <cstddef> // size_t
#include <cstdint> // uint64_t
+#include <cassert>
#include <exception>
#include <butl/char-scanner>
@@ -27,13 +29,13 @@ namespace build
// pairs modes are automatically reset after the end of the line.
// The variable mode is automatically reset after the name token.
//
- enum class lexer_mode {normal, value, variable, pairs};
+ enum class lexer_mode {normal, variable, value, pairs};
class lexer: protected butl::char_scanner
{
public:
lexer (std::istream& is, const std::string& name)
- : char_scanner (is), fail (name) {}
+ : char_scanner (is), fail (name) {mode_.push (lexer_mode::normal);}
const std::string&
name () const {return fail.name_;}
@@ -44,12 +46,17 @@ namespace build
void
mode (lexer_mode m, char pair_separator = '=')
{
- next_mode_ = m;
+ mode_.push (m);
pair_separator_ = pair_separator;
}
+ // Expire the current mode early.
+ //
+ void
+ expire_mode () {mode_.pop ();}
+
lexer_mode
- mode () const {return mode_;}
+ mode () const {return mode_.top ();}
char
pair_separator () const {return pair_separator_;}
@@ -93,10 +100,23 @@ namespace build
private:
fail_mark fail;
- lexer_mode mode_ {lexer_mode::normal};
+ // Currently, the maximum mode nesting is 3: {normal, value, variable}.
+ //
+ struct mode_stack
+ {
+ static const size_t max_size = 3;
+
+ void push (lexer_mode m) {assert (n_ != max_size); d_[n_++] = m;}
+ void pop () {assert (n_ != 0); n_--;}
+ lexer_mode top () const {return d_[n_ - 1];}
+
+ private:
+ size_t n_ = 0;
+ lexer_mode d_[max_size];
+ };
+
+ mode_stack mode_;
char pair_separator_;
- lexer_mode next_mode_ {lexer_mode::normal}; // Switch to for next token.
- lexer_mode prev_mode_; // Return to after current mode expires.
};
}