aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/parser11
-rw-r--r--build2/parser.cxx73
-rw-r--r--tests/if-else/buildfile26
-rw-r--r--tests/if-else/test.out3
4 files changed, 86 insertions, 27 deletions
diff --git a/build2/parser b/build2/parser
index 0962348..af5c500 100644
--- a/build2/parser
+++ b/build2/parser
@@ -56,8 +56,15 @@ namespace build2
// Recursive descent parser.
//
protected:
- void
- clause (token&, token_type&);
+ // If one is true then parse a single (logical) line (logical means it
+ // can actually be several lines, e.g., an if-block). Return false if
+ // nothing has been parsed (i.e., we are on the same token).
+ //
+ // Note that after this function returns, the token is the first token on
+ // the next line (or eos).
+ //
+ bool
+ clause (token&, token_type&, bool one = false);
void
print (token&, token_type&);
diff --git a/build2/parser.cxx b/build2/parser.cxx
index 1987945..04accd2 100644
--- a/build2/parser.cxx
+++ b/build2/parser.cxx
@@ -192,8 +192,8 @@ namespace build2
return make_pair (move (lhs), move (t));
}
- void parser::
- clause (token& t, type& tt)
+ bool parser::
+ clause (token& t, type& tt, bool one)
{
tracer trace ("parser::clause", &path_);
@@ -203,7 +203,9 @@ namespace build2
// for if-else blocks, directory scopes, etc., that assume the } token
// they see is on the new line.
//
- while (tt != type::eos)
+ bool parsed (false);
+
+ while (tt != type::eos && !(one && parsed))
{
// Extract attributes if any.
//
@@ -228,6 +230,11 @@ namespace build2
break;
}
+ // Now we will either parse something or fail.
+ //
+ if (!parsed)
+ parsed = true;
+
// See if this is one of the directives.
//
if (tt == type::name && keyword (t))
@@ -689,6 +696,8 @@ namespace build2
fail (t) << "unexpected " << t;
}
+
+ return parsed;
}
void parser::
@@ -1286,33 +1295,51 @@ namespace build2
fail (t) << "expected newline instead of " << t << " after " << k
<< (k != "else" ? "-expression" : "");
- if (next (t, tt) != type::lcbrace)
- fail (t) << "expected { instead of " << t << " at the beginning of "
- << k << "-block";
+ // This can be a block or a single line.
+ //
+ if (next (t, tt) == type::lcbrace)
+ {
+ if (next (t, tt) != type::newline)
+ fail (t) << "expected newline after {";
- if (next (t, tt) != type::newline)
- fail (t) << "expected newline after {";
+ next (t, tt);
- next (t, tt);
+ if (take)
+ {
+ clause (t, tt);
+ taken = true;
+ }
+ else
+ skip_block (t, tt);
- if (take)
- {
- clause (t, tt);
- taken = true;
+ if (tt != type::rcbrace)
+ fail (t) << "expected } instead of " << t << " at the end of " << k
+ << "-block";
+
+ next (t, tt);
+
+ if (tt == type::newline)
+ next (t, tt);
+ else if (tt != type::eos)
+ fail (t) << "expected newline after }";
}
else
- skip_block (t, tt);
-
- if (tt != type::rcbrace)
- fail (t) << "expected } instead of " << t << " at the end of " << k
- << "-block";
+ {
+ if (take)
+ {
+ if (!clause (t, tt, true))
+ fail (t) << "expected " << k << "-line instead of " << t;
- next (t, tt);
+ taken = true;
+ }
+ else
+ {
+ skip_line (t, tt);
- if (tt == type::newline)
- next (t, tt);
- else if (tt != type::eos)
- fail (t) << "expected newline after }";
+ if (tt == type::newline)
+ next (t, tt);
+ }
+ }
// See if we have another el* keyword.
//
diff --git a/tests/if-else/buildfile b/tests/if-else/buildfile
index a54092d..25fabf0 100644
--- a/tests/if-else/buildfile
+++ b/tests/if-else/buildfile
@@ -104,8 +104,6 @@ if! $f
print 1
}
-./:
-
# With eval context.
#
if (foo == foo)
@@ -128,8 +126,32 @@ if ([uint64] 01 == [uint64] 1)
print 1
}
+# Single line.
+#
+
+#if true
+#} # expected if-line
+
+if true
+ print 1
+
+if false
+
+ print 0
+else
+ # Comment.
+ print 1
+
+if true
+ if false
+ print 0
+ else
+ print 1
+
# EOF test.
#
+./:
+
if true
{
print 1
diff --git a/tests/if-else/test.out b/tests/if-else/test.out
index 71c9a23..58501cb 100644
--- a/tests/if-else/test.out
+++ b/tests/if-else/test.out
@@ -11,3 +11,6 @@
1
1
1
+1
+1
+1