summaryrefslogtreecommitdiff
path: root/src/formats
diff options
context:
space:
mode:
Diffstat (limited to 'src/formats')
-rw-r--r--src/formats/osml/OsmlStreamParser.cpp78
-rw-r--r--src/formats/osml/OsmlStreamParser.hpp45
2 files changed, 93 insertions, 30 deletions
diff --git a/src/formats/osml/OsmlStreamParser.cpp b/src/formats/osml/OsmlStreamParser.cpp
index 6b00eef..6606120 100644
--- a/src/formats/osml/OsmlStreamParser.cpp
+++ b/src/formats/osml/OsmlStreamParser.cpp
@@ -61,6 +61,11 @@ public:
TokenTypeId FieldEnd;
/**
+ * Id of the default field start token.
+ */
+ TokenTypeId DefaultFieldStart;
+
+ /**
* Registers the plain format tokens in the internal tokenizer.
*/
PlainFormatTokens()
@@ -71,6 +76,7 @@ public:
BlockCommentEnd = registerToken("}%");
FieldStart = registerToken("{");
FieldEnd = registerToken("}");
+ DefaultFieldStart = registerToken("{!");
}
};
@@ -164,7 +170,7 @@ OsmlStreamParser::OsmlStreamParser(CharReader &reader, Logger &logger)
: reader(reader), logger(logger), tokenizer(Tokens)
{
// Place an intial command representing the complete file on the stack
- commands.push(Command{"", Variant::mapType{}, true, true, true});
+ commands.push(Command{"", Variant::mapType{}, true, true, true, false});
}
Variant OsmlStreamParser::parseIdentifier(size_t start, bool allowNSSep)
@@ -365,7 +371,7 @@ void OsmlStreamParser::pushCommand(Variant commandName,
commands.pop();
}
commands.push(Command{std::move(commandName), std::move(commandArguments),
- hasRange, false, false});
+ hasRange, false, false, false});
}
OsmlStreamParser::State OsmlStreamParser::parseCommand(size_t start)
@@ -482,6 +488,29 @@ bool OsmlStreamParser::checkIssueFieldStart()
return false;
}
+bool OsmlStreamParser::closeField()
+{
+ // Try to end an open field of the current command -- if the current command
+ // is not inside an open field, end this command and try to close the next
+ // one
+ for (int i = 0; i < 2 && commands.size() > 1; i++) {
+ Command &cmd = commands.top();
+ if (!cmd.inRangeField) {
+ if (cmd.inField) {
+ cmd.inField = false;
+ if (cmd.inDefaultField) {
+ commands.pop();
+ }
+ return true;
+ }
+ commands.pop();
+ } else {
+ return false;
+ }
+ }
+ return false;
+}
+
OsmlStreamParser::State OsmlStreamParser::parse()
{
// Handler for incomming data
@@ -579,27 +608,29 @@ OsmlStreamParser::State OsmlStreamParser::parse()
}
logger.error(
"Got field start token \"{\", but no command for which to "
- "start the field. Did you mean \"\\{\"?",
+ "start the field. Write \"\\{\" to insert this sequence as "
+ "text.",
token);
} else if (token.type == Tokens.FieldEnd) {
- // Try to end an open field of the current command -- if the current
- // command is not inside an open field, end this command and try to
- // close the next one
- for (int i = 0; i < 2 && commands.size() > 1; i++) {
- Command &cmd = commands.top();
- if (!cmd.inRangeField) {
- if (cmd.inField) {
- cmd.inField = false;
- return State::FIELD_END;
- }
- commands.pop();
- } else {
- break;
- }
+ if (closeField()) {
+ return State::FIELD_END;
+ }
+ logger.error(
+ "Got field end token \"}\", but there is no field to end. "
+ "Write \"\\}\" to insert this sequence as text.",
+ token);
+ } else if (token.type == Tokens.DefaultFieldStart) {
+ // Try to start a default field the first time the token is reached
+ Command &topCmd = commands.top();
+ if (!topCmd.inField) {
+ topCmd.inField = true;
+ topCmd.inDefaultField = true;
+ return State::FIELD_START;
}
logger.error(
- "Got field end token \"}\", but there is no field to end. Did "
- "you mean \"\\}\"?",
+ "Got default field start token \"{!\", but no command for "
+ "which to start the field. Write \"\\{!\" to insert this "
+ "sequence as text",
token);
} else {
logger.error("Unexpected token \"" + token.content + "\"", token);
@@ -627,14 +658,19 @@ OsmlStreamParser::State OsmlStreamParser::parse()
return State::END;
}
-const Variant &OsmlStreamParser::getCommandName()
+const Variant &OsmlStreamParser::getCommandName() const
{
return commands.top().name;
}
-const Variant &OsmlStreamParser::getCommandArguments()
+const Variant &OsmlStreamParser::getCommandArguments() const
{
return commands.top().arguments;
}
+
+bool OsmlStreamParser::inDefaultField() const
+{
+ return commands.top().inRangeField || commands.top().inDefaultField;
+}
}
diff --git a/src/formats/osml/OsmlStreamParser.hpp b/src/formats/osml/OsmlStreamParser.hpp
index 1508012..bb5db65 100644
--- a/src/formats/osml/OsmlStreamParser.hpp
+++ b/src/formats/osml/OsmlStreamParser.hpp
@@ -153,9 +153,15 @@ public:
bool inRangeField;
/**
+ * Set to true if we are currently in a field that has been especially
+ * marked as default field (using the "|") syntax.
+ */
+ bool inDefaultField;
+
+ /**
* Default constructor.
*/
- Command() : hasRange(false), inField(false), inRangeField(false) {}
+ Command() : hasRange(false), inField(false), inRangeField(false), inDefaultField() {}
/**
* Constructor of the Command class.
@@ -168,16 +174,19 @@ public:
* explicit range.
* @param inField is set to true if we currently are inside a field
* of this command.
- * @param inRangeField is set to true if we currently inside the outer
- * field of the command.
+ * @param inRangeField is set to true if we currently are inside the
+ * outer field of a ranged command.
+ * @param inDefaultField is set to true if we currently are in a
+ * specially marked default field.
*/
Command(Variant name, Variant arguments, bool hasRange, bool inField,
- bool inRangeField)
+ bool inRangeField, bool inDefaultField)
: name(std::move(name)),
arguments(std::move(arguments)),
hasRange(hasRange),
inField(inField),
- inRangeField(inRangeField)
+ inRangeField(inRangeField),
+ inDefaultField(inDefaultField)
{
}
};
@@ -289,6 +298,16 @@ private:
*/
bool checkIssueFieldStart();
+ /**
+ * Closes a currently open field. Note that the command will be removed from
+ * the internal command stack if the field that is being closed is a
+ * field marked as default field.
+ *
+ * @return true if the field could be closed, false if there was no field
+ * to close.
+ */
+ bool closeField();
+
public:
/**
* Constructor of the OsmlStreamParser class. Attaches the new
@@ -317,7 +336,7 @@ public:
* @return a reference at a variant containing the data parsed by the
* "parse" function.
*/
- const Variant &getData() { return data; }
+ const Variant &getData() const { return data; }
/**
* Returns a reference at the internally stored command name. Only valid if
@@ -326,7 +345,7 @@ public:
* @return a reference at a variant containing name and location of the
* parsed command.
*/
- const Variant &getCommandName();
+ const Variant &getCommandName() const;
/**
* Returns a reference at the internally stored command name. Only valid if
@@ -335,14 +354,22 @@ public:
* @return a reference at a variant containing arguments given to the
* command.
*/
- const Variant &getCommandArguments();
+ const Variant &getCommandArguments() const;
+
+ /**
+ * Returns true if the current field is the "default" field. This is true if
+ * the parser either is in the outer range of a range command or inside a
+ * field that has been especially marked as "default" field (using the "|"
+ * syntax).
+ */
+ bool inDefaultField() const;
/**
* Returns a reference at the char reader.
*
* @return the last internal token location.
*/
- SourceLocation &getLocation() { return location; }
+ const SourceLocation &getLocation() const { return location; }
};
}