/*
Ousía
Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include "OsmlParser.hpp"
#include "OsmlStreamParser.hpp"
namespace ousia {
using namespace parser_stack;
/**
* The OsmlParserImplementation class contains the actual implementation of the
* parsing process and is created in the "doParse" function of the OsmlParser.
*/
class OsmlParserImplementation {
private:
/**
* Reference at the logger.
*/
Logger &logger;
/**
* Reference at the parser context.
*/
ParserContext &ctx;
/**
* OsmlStreamParser instance responsible for converting the input stream
* into a series of osml events that are relayed to the Stack class.
*/
OsmlStreamParser parser;
/**
* Pushdown automaton responsible for converting the osml events into an
* actual Node tree.
*/
Stack stack;
public:
/**
* Constructor of the OsmlParserImplementation class.
*
* @param reader is a reference to the CharReader instance from which the
* osml should be read.
* @param ctx is a reference to the ParserContext instance that should be
* used.
*/
OsmlParserImplementation(CharReader &reader, ParserContext &ctx)
: logger(ctx.getLogger()),
ctx(ctx),
parser(reader, logger),
stack(parser, ctx, GenericParserStates)
{
}
/**
* Starts the actual parsing process.
*/
void parse()
{
// Flag set to true if a "document" element needs to be created
bool needsDocument = ctx.getScope().select() == nullptr;
while (true) {
OsmlStreamParser::State state = parser.parse();
logger.setDefaultLocation(parser.getLocation());
switch (state) {
case OsmlStreamParser::State::COMMAND_START: {
// Implicitly create a "document" element if the first
// command is not any other top-level command
if (needsDocument) {
const std::string &cmd =
parser.getCommandName().asString();
if (cmd != "typesystem" && cmd != "document" &&
cmd != "ontology") {
stack.commandStart("document", Variant::mapType{},
false);
}
needsDocument = false;
}
stack.commandStart(parser.getCommandName(),
parser.getCommandArguments().asMap(),
parser.inRangeCommand());
break;
}
case OsmlStreamParser::State::RANGE_END:
stack.rangeEnd();
break;
case OsmlStreamParser::State::ANNOTATION_START:
stack.annotationStart(parser.getCommandName(),
parser.getCommandArguments().asMap(),
parser.inRangeCommand());
break;
case OsmlStreamParser::State::ANNOTATION_END: {
Variant elementName = Variant::fromString(std::string{});
stack.annotationEnd(parser.getCommandName(), parser.getCommandArguments().asMap());
break;
}
case OsmlStreamParser::State::FIELD_START:
stack.fieldStart(parser.inDefaultField());
break;
case OsmlStreamParser::State::FIELD_END:
stack.fieldEnd();
break;
case OsmlStreamParser::State::DATA:
stack.data(parser.getData());
break;
case OsmlStreamParser::State::END:
return;
}
}
}
};
void OsmlParser::doParse(CharReader &reader, ParserContext &ctx)
{
OsmlParserImplementation parser(reader, ctx);
parser.parse();
}
}