aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/lexer14
-rw-r--r--build/lexer.cxx46
-rw-r--r--build/parser.cxx36
-rw-r--r--build/token3
4 files changed, 42 insertions, 57 deletions
diff --git a/build/lexer b/build/lexer
index 98a1390..5f91dc4 100644
--- a/build/lexer
+++ b/build/lexer
@@ -20,8 +20,8 @@ namespace build
// them in the variable values, e.g., 'foo = g++'. In contrast,
// in the variable mode, we restrict certain character (e.g., /)
// from appearing in the name. The pairs mode is just like value
- // except that we split names separated by '='. The pairs mode must
- // be set manually.
+ // except that we split names separated by the pair character.
+ // The pairs mode must be set manually.
//
enum class lexer_mode {normal, value, variable, pairs};
@@ -30,10 +30,15 @@ namespace build
public:
lexer (std::istream& is, const std::string& name): is_ (is), fail (name) {}
- // Note: sets mode for the next token.
+ // Note: sets mode for the next token. If mode is pairs, then
+ // the second argument specifies the separator character.
//
void
- mode (lexer_mode m) {next_mode_ = m;}
+ mode (lexer_mode m, char pair_separator = '=')
+ {
+ next_mode_ = m;
+ pair_separator_ = pair_separator;
+ }
lexer_mode
mode () const {return mode_;}
@@ -127,6 +132,7 @@ namespace build
bool eos_ {false};
lexer_mode mode_ {lexer_mode::normal};
+ 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.
};
diff --git a/build/lexer.cxx b/build/lexer.cxx
index 9683567..4cd9cda 100644
--- a/build/lexer.cxx
+++ b/build/lexer.cxx
@@ -64,6 +64,11 @@ namespace build
}
}
+ // Handle pair separator.
+ //
+ if (mode_ == lexer_mode::pairs && c == pair_separator_)
+ return token (token_type::pair_separator, sep, ln, cn);
+
// The following characters are not treated as special in the
// value or pairs mode.
//
@@ -85,26 +90,9 @@ namespace build
next_mode_ = lexer_mode::value;
return token (token_type::plus_equal, sep, ln, cn);
}
- }
- }
-
- // The following characters are not treated as special in the
- // value mode.
- //
- if (mode_ != lexer_mode::value)
- {
- // NOTE: remember to update name() if adding new punctuations.
- //
- switch (c)
- {
case '=':
{
- // Unless we are already in the pairs mode, switch to the
- // value mode.
- //
- if (next_mode_ != lexer_mode::pairs)
- next_mode_ = lexer_mode::value;
-
+ next_mode_ = lexer_mode::value;
return token (token_type::equal, sep, ln, cn);
}
}
@@ -126,6 +114,11 @@ namespace build
{
bool done (false);
+ // Handle pair separator.
+ //
+ if (mode_ == lexer_mode::pairs && c == pair_separator_)
+ break;
+
// The following characters are not treated as special in the
// value or pairs mode.
//
@@ -135,23 +128,6 @@ namespace build
{
case ':':
case '+':
- {
- done = true;
- break;
- }
- }
-
- if (done)
- break;
- }
-
- // The following characters are not treated as special in the
- // value mode.
- //
- if (mode_ != lexer_mode::value)
- {
- switch (c)
- {
case '=':
{
done = true;
diff --git a/build/parser.cxx b/build/parser.cxx
index b21dd6f..617f22b 100644
--- a/build/parser.cxx
+++ b/build/parser.cxx
@@ -976,7 +976,7 @@ namespace build
// A pair separator (only in the pair mode).
//
- if (tt == type::equal && lexer_->mode () == lexer_mode::pairs)
+ if (tt == type::pair_separator)
{
if (pair != 0)
fail (t) << "nested pair on the right hand side of a pair";
@@ -1043,9 +1043,10 @@ namespace build
lexer_ = &l;
scope_ = root_ = root_scope;
- // Turn on pairs recognition (e.g., src_root/=out_root/exe{foo bar}).
+ // Turn on pairs recognition with '@' as the pair separator (e.g.,
+ // src_root/@out_root/exe{foo bar}).
//
- lexer_->mode (lexer_mode::pairs);
+ lexer_->mode (lexer_mode::pairs, '@');
token t (type::eos, false, 0, 0);
type tt;
@@ -1084,9 +1085,9 @@ namespace build
// We always start with one or more names.
//
if (tt != type::name &&
- tt != type::lcbrace && // Untyped name group: '{foo ...'
- tt != type::dollar && // Variable expansion: '$foo ...'
- tt != type::equal) // Empty pair LHS: '=foo ...'
+ tt != type::lcbrace && // Untyped name group: '{foo ...'
+ tt != type::dollar && // Variable expansion: '$foo ...'
+ tt != type::pair_separator) // Empty pair LHS: '=foo ...'
fail (t) << "operation or target expected instead of " << t;
location l (get_location (t, &path_)); // Start of names.
@@ -1296,17 +1297,18 @@ namespace build
{
switch (t.type ())
{
- case token_type::eos: os << "<end-of-file>"; break;
- case token_type::newline: os << "<newline>"; break;
- case token_type::colon: os << ":"; break;
- case token_type::lcbrace: os << "{"; break;
- case token_type::rcbrace: os << "}"; break;
- case token_type::equal: os << "="; break;
- case token_type::plus_equal: os << "+="; break;
- case token_type::dollar: os << "$"; break;
- case token_type::lparen: os << "("; break;
- case token_type::rparen: os << ")"; break;
- case token_type::name: os << t.name (); break;
+ case token_type::eos: os << "<end-of-file>"; break;
+ case token_type::newline: os << "<newline>"; break;
+ case token_type::pair_separator: os << "<pair separator>"; break;
+ case token_type::colon: os << ":"; break;
+ case token_type::lcbrace: os << "{"; break;
+ case token_type::rcbrace: os << "}"; break;
+ case token_type::equal: os << "="; break;
+ case token_type::plus_equal: os << "+="; break;
+ case token_type::dollar: os << "$"; break;
+ case token_type::lparen: os << "("; break;
+ case token_type::rparen: os << ")"; break;
+ case token_type::name: os << t.name (); break;
}
return os;
diff --git a/build/token b/build/token
index 670207d..f7e45dc 100644
--- a/build/token
+++ b/build/token
@@ -18,6 +18,7 @@ namespace build
eos,
name,
newline,
+ pair_separator,
colon,
lcbrace,
rcbrace,
@@ -25,7 +26,7 @@ namespace build
plus_equal,
dollar,
lparen,
- rparen,
+ rparen
};
class token