summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPeter Kuemmel <syntheticpp@gmx.net>2012-01-29 13:26:24 (GMT)
committerPeter Kuemmel <syntheticpp@gmx.net>2012-01-29 13:26:24 (GMT)
commit2e481086ad7337bb868327f12ffd317dc5143a3e (patch)
tree970d5c7fb9207ec96beff9d9fdfcf60c60a06e0d /src
parent88c9491f515f7ba479b5334ef834743fed539730 (diff)
downloadNinja-2e481086ad7337bb868327f12ffd317dc5143a3e.zip
Ninja-2e481086ad7337bb868327f12ffd317dc5143a3e.tar.gz
Ninja-2e481086ad7337bb868327f12ffd317dc5143a3e.tar.bz2
parse $:
'$:' is a valid string now, it expands to ':' update error messages and show a hint when something went wrong.
Diffstat (limited to 'src')
-rw-r--r--src/lexer.cc20
-rw-r--r--src/lexer.h4
-rw-r--r--src/lexer.in.cc20
-rw-r--r--src/parsers.cc1
-rw-r--r--src/parsers_test.cc37
5 files changed, 78 insertions, 4 deletions
diff --git a/src/lexer.cc b/src/lexer.cc
index a1bedf5..9e4392c 100644
--- a/src/lexer.cc
+++ b/src/lexer.cc
@@ -90,6 +90,26 @@ const char* Lexer::TokenName(Token t) {
return NULL; // not reached
}
+const char* Lexer::TokenErrorHint(Token t) {
+ switch (t) {
+ case ERROR: return "";
+ case BUILD: return "";
+ case COLON: return " ($ also escapes ':')";
+ case DEFAULT: return "";
+ case EQUALS: return "";
+ case IDENT: return "";
+ case INCLUDE: return "";
+ case INDENT: return "";
+ case NEWLINE: return "";
+ case PIPE2: return "";
+ case PIPE: return "";
+ case RULE: return "";
+ case SUBNINJA: return "";
+ case TEOF: return "";
+ }
+ return "";
+}
+
void Lexer::UnreadToken() {
ofs_ = last_token_;
}
diff --git a/src/lexer.h b/src/lexer.h
index c872b98..75c1b2f 100644
--- a/src/lexer.h
+++ b/src/lexer.h
@@ -46,6 +46,10 @@ struct Lexer {
/// Return a human-readable form of a token, used in error messages.
static const char* TokenName(Token t);
+
+ /// Return a human-readable token hint, used in error messages.
+ static const char* TokenErrorHint(Token t);
+
/// Start parsing some input.
void Start(StringPiece filename, StringPiece input);
diff --git a/src/lexer.in.cc b/src/lexer.in.cc
index 9caaa36..28a5bdf 100644
--- a/src/lexer.in.cc
+++ b/src/lexer.in.cc
@@ -89,6 +89,26 @@ const char* Lexer::TokenName(Token t) {
return NULL; // not reached
}
+const char* Lexer::TokenErrorHint(Token t) {
+ switch (t) {
+ case ERROR: return "";
+ case BUILD: return "";
+ case COLON: return " ($ also escapes ':')";
+ case DEFAULT: return "";
+ case EQUALS: return "";
+ case IDENT: return "";
+ case INCLUDE: return "";
+ case INDENT: return "";
+ case NEWLINE: return "";
+ case PIPE2: return "";
+ case PIPE: return "";
+ case RULE: return "";
+ case SUBNINJA: return "";
+ case TEOF: return "";
+ }
+ return "";
+}
+
void Lexer::UnreadToken() {
ofs_ = last_token_;
}
diff --git a/src/parsers.cc b/src/parsers.cc
index c1badd8..5d347b2 100644
--- a/src/parsers.cc
+++ b/src/parsers.cc
@@ -313,6 +313,7 @@ bool ManifestParser::ExpectToken(Lexer::Token expected, string* err) {
if (token != expected) {
string message = string("expected ") + Lexer::TokenName(expected);
message += string(", got ") + Lexer::TokenName(token);
+ message += Lexer::TokenErrorHint(expected);
return lexer_.Error(message, err);
}
return true;
diff --git a/src/parsers_test.cc b/src/parsers_test.cc
index f3ac517..2a30a83 100644
--- a/src/parsers_test.cc
+++ b/src/parsers_test.cc
@@ -377,14 +377,30 @@ TEST_F(ParserTest, Errors) {
ManifestParser parser(&state, NULL);
string err;
EXPECT_FALSE(parser.ParseTest("rule cat\n"
- " command = cat\nbuild $: cat foo\n",
+ " command = cat\n"
+ "build $.: cat foo\n",
&err));
EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
- "build $: cat foo\n"
+ "build $.: cat foo\n"
" ^ near here"
, err);
}
+
+ {
+ State state;
+ ManifestParser parser(&state, NULL);
+ string err;
+ EXPECT_FALSE(parser.ParseTest("rule cat\n"
+ " command = cat\n"
+ "build $: cat foo\n",
+ &err));
+ EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
+ "build $: cat foo\n"
+ " ^ near here"
+ , err);
+ }
+
{
State state;
ManifestParser parser(&state, NULL);
@@ -413,10 +429,10 @@ TEST_F(ParserTest, Errors) {
ManifestParser parser(&state, NULL);
string err;
EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n"
- "build $: cc bar.cc\n",
+ "build $.: cc bar.cc\n",
&err));
EXPECT_EQ("input:3: bad $-escape (literal $ must be written as $$)\n"
- "build $: cc bar.cc\n"
+ "build $.: cc bar.cc\n"
" ^ near here"
, err);
}
@@ -425,6 +441,19 @@ TEST_F(ParserTest, Errors) {
State state;
ManifestParser parser(&state, NULL);
string err;
+ EXPECT_FALSE(parser.ParseTest("rule cc\n command = foo\n"
+ "build $: cc bar.cc\n",
+ &err));
+ EXPECT_EQ("input:3: expected ':', got newline ($ also escapes ':')\n"
+ "build $: cc bar.cc\n"
+ " ^ near here"
+ , err);
+ }
+
+ {
+ State state;
+ ManifestParser parser(&state, NULL);
+ string err;
EXPECT_FALSE(parser.ParseTest("default\n",
&err));
EXPECT_EQ("input:1: expected target name\n"