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:
parent
7e346f1677
commit
91698de994
|
@ -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])
|
||||||
|
|
Loading…
Reference in New Issue