Make .PackageInfo more driver-settings-ish

* Use braces instead of brackets for lists.
* Semicolons and newlines separate items now. Remove handling for comma.
* Allow '\'' as quotation character.
* Remove assignment after variable name.

This should make the .PackageInfo format driver settings compatible, but
not vice versa. It is still stricter.
This commit is contained in:
Ingo Weinhold 2011-06-27 19:12:35 +02:00
parent 7e346f1677
commit 91698de994
1 changed files with 41 additions and 42 deletions

View File

@ -32,9 +32,9 @@ enum TokenType {
TOKEN_OPERATOR_NOT_EQUAL, TOKEN_OPERATOR_NOT_EQUAL,
TOKEN_OPERATOR_GREATER_EQUAL, TOKEN_OPERATOR_GREATER_EQUAL,
TOKEN_OPERATOR_GREATER, TOKEN_OPERATOR_GREATER,
TOKEN_OPEN_BRACKET, TOKEN_OPEN_BRACE,
TOKEN_CLOSE_BRACKET, TOKEN_CLOSE_BRACE,
TOKEN_COMMA, TOKEN_ITEM_SEPARATOR,
// //
TOKEN_EOF, TOKEN_EOF,
}; };
@ -205,32 +205,39 @@ BPackageInfo::Parser::Parse(const BString& packageInfoString,
BPackageInfo::Parser::Token BPackageInfo::Parser::Token
BPackageInfo::Parser::_NextToken() BPackageInfo::Parser::_NextToken()
{ {
// eat any whitespace or comments // Eat any whitespace or comments. Also eat ';' -- they have the same
// function as newlines. We remember the last encountered ';' or '\n' and
// return it as a token afterwards.
const char* itemSeparatorPos = NULL;
bool inComment = false; bool inComment = false;
while ((inComment && *fPos != '\0') || isspace(*fPos) || *fPos == '#') { while ((inComment && *fPos != '\0') || isspace(*fPos) || *fPos == ';'
if (*fPos == '#') || *fPos == '#') {
if (*fPos == '#') {
inComment = true; inComment = true;
else if (*fPos == '\n') } else if (*fPos == '\n') {
itemSeparatorPos = fPos;
inComment = false; inComment = false;
} else if (!inComment && *fPos == ';')
itemSeparatorPos = fPos;
fPos++; fPos++;
} }
if (itemSeparatorPos != NULL) {
return Token(TOKEN_ITEM_SEPARATOR, itemSeparatorPos);
}
const char* tokenPos = fPos; const char* tokenPos = fPos;
switch (*fPos) { switch (*fPos) {
case '\0': case '\0':
return Token(TOKEN_EOF, fPos); return Token(TOKEN_EOF, fPos);
case ',': case '{':
fPos++; fPos++;
return Token(TOKEN_COMMA, tokenPos); return Token(TOKEN_OPEN_BRACE, tokenPos);
case '[': case '}':
fPos++; fPos++;
return Token(TOKEN_OPEN_BRACKET, tokenPos); return Token(TOKEN_CLOSE_BRACE, tokenPos);
case ']':
fPos++;
return Token(TOKEN_CLOSE_BRACKET, tokenPos);
case '<': case '<':
fPos++; fPos++;
@ -264,19 +271,21 @@ BPackageInfo::Parser::_NextToken()
return Token(TOKEN_OPERATOR_GREATER, tokenPos, 1); return Token(TOKEN_OPERATOR_GREATER, tokenPos, 1);
case '"': case '"':
case '\'':
{ {
char quoteChar = *fPos;
fPos++; fPos++;
const char* start = fPos; const char* start = fPos;
// anything until the next quote is part of the value // anything until the next quote is part of the value
bool lastWasEscape = false; bool lastWasEscape = false;
while ((*fPos != '"' || lastWasEscape) && *fPos != '\0') { while ((*fPos != quoteChar || lastWasEscape) && *fPos != '\0') {
if (lastWasEscape) if (lastWasEscape)
lastWasEscape = false; lastWasEscape = false;
else if (*fPos == '\\') else if (*fPos == '\\')
lastWasEscape = true; lastWasEscape = true;
fPos++; fPos++;
} }
if (*fPos != '"') if (*fPos != quoteChar)
throw ParseError("unterminated quoted-string", tokenPos); throw ParseError("unterminated quoted-string", tokenPos);
const char* end = fPos++; const char* end = fPos++;
return Token(TOKEN_QUOTED_STRING, start, end - start); return Token(TOKEN_QUOTED_STRING, start, end - start);
@ -417,7 +426,7 @@ BPackageInfo::Parser::_ParseList(ListElementParser& elementParser,
bool allowSingleNonListElement) bool allowSingleNonListElement)
{ {
Token openBracket = _NextToken(); Token openBracket = _NextToken();
if (openBracket.type != TOKEN_OPEN_BRACKET) { if (openBracket.type != TOKEN_OPEN_BRACE) {
if (!allowSingleNonListElement) if (!allowSingleNonListElement)
throw ParseError("expected start of list ('[')", openBracket.pos); throw ParseError("expected start of list ('[')", openBracket.pos);
@ -425,22 +434,13 @@ BPackageInfo::Parser::_ParseList(ListElementParser& elementParser,
return; return;
} }
bool needComma = false;
while (true) { while (true) {
Token token = _NextToken(); Token token = _NextToken();
if (token.type == TOKEN_CLOSE_BRACKET) if (token.type == TOKEN_CLOSE_BRACE)
return; return;
if (needComma) { if (token.type == TOKEN_ITEM_SEPARATOR)
if (token.type != TOKEN_COMMA) continue;
throw ParseError("expected comma", token.pos);
token = _NextToken();
if (token.type == TOKEN_CLOSE_BRACKET) {
// silently skip trailing comma at end of list
return;
}
} else
needComma = true;
elementParser(token); elementParser(token);
} }
@ -568,11 +568,12 @@ BPackageInfo::Parser::_ParseResolvableList(
// parse version // parse version
BPackageVersion version; BPackageVersion version;
Token op = parser._NextToken(); Token op = parser._NextToken();
if (op.type == TOKEN_OPERATOR_ASSIGN) if (op.type == TOKEN_OPERATOR_ASSIGN) {
parser._ParseVersionValue(&version, true); parser._ParseVersionValue(&version, true);
else if (op.type == TOKEN_COMMA || op.type == TOKEN_CLOSE_BRACKET) } else if (op.type == TOKEN_ITEM_SEPARATOR
|| op.type == TOKEN_CLOSE_BRACE) {
parser._RewindTo(op); parser._RewindTo(op);
else } else
throw ParseError("expected '=', comma or ']'", op.pos); throw ParseError("expected '=', comma or ']'", op.pos);
// parse compatible version // parse compatible version
@ -628,11 +629,12 @@ BPackageInfo::Parser::_ParseResolvableExprList(
|| op.type == TOKEN_OPERATOR_EQUAL || op.type == TOKEN_OPERATOR_EQUAL
|| op.type == TOKEN_OPERATOR_NOT_EQUAL || op.type == TOKEN_OPERATOR_NOT_EQUAL
|| op.type == TOKEN_OPERATOR_GREATER_EQUAL || op.type == TOKEN_OPERATOR_GREATER_EQUAL
|| op.type == TOKEN_OPERATOR_GREATER) || op.type == TOKEN_OPERATOR_GREATER) {
parser._ParseVersionValue(&version, true); parser._ParseVersionValue(&version, true);
else if (op.type == TOKEN_COMMA || op.type == TOKEN_CLOSE_BRACKET) } else if (op.type == TOKEN_ITEM_SEPARATOR
|| op.type == TOKEN_CLOSE_BRACE) {
parser._RewindTo(op); parser._RewindTo(op);
else { } else {
throw ParseError( throw ParseError(
"expected '<', '<=', '==', '!=', '>=', '>', comma or ']'", "expected '<', '<=', '==', '!=', '>=', '>', comma or ']'",
op.pos); op.pos);
@ -660,15 +662,12 @@ BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
const char* const* names = BPackageInfo::kElementNames; const char* const* names = BPackageInfo::kElementNames;
while (Token t = _NextToken()) { while (Token t = _NextToken()) {
if (t.type == TOKEN_ITEM_SEPARATOR)
continue;
if (t.type != TOKEN_WORD) if (t.type != TOKEN_WORD)
throw ParseError("expected word (a variable name)", t.pos); throw ParseError("expected word (a variable name)", t.pos);
Token opAssign = _NextToken();
if (opAssign.type != TOKEN_OPERATOR_ASSIGN) {
throw ParseError("expected assignment operator ('=')",
opAssign.pos);
}
if (t.text.ICompare(names[B_PACKAGE_INFO_NAME]) == 0) { if (t.text.ICompare(names[B_PACKAGE_INFO_NAME]) == 0) {
if (seen[B_PACKAGE_INFO_NAME]) { if (seen[B_PACKAGE_INFO_NAME]) {
BString error = BString(names[B_PACKAGE_INFO_NAME]) BString error = BString(names[B_PACKAGE_INFO_NAME])