2 Aesalon, a tool to visualize a program's behaviour at run-time.
3 Copyright (C) 2010, Aesalon Development Team.
5 Aesalon is distributed under the terms of the GNU GPLv3. For more
6 licensing information, see the file LICENSE included with the distribution.
8 @file monitor/src/config/Parser.cpp
12 #include <iostream> // for debugging
20 #include "config/Parser.h"
21 #include "common/ParsingException.h"
22 #include "common/StreamAsString.h"
23 #include "common/PathSanitizer.h"
24 #include "config/ConcreteVault.h"
29 void Parser::parse(ConcreteVault
*vault
, const std::string
&configFile
) {
30 std::string currentModule
;
32 std::vector
<std::string
> paths
;
33 vault
->get("PATH", paths
);
35 openFile(Common::PathSanitizer::sanitize(configFile
, paths
));
37 if(!m_stream
->is_open()) return;
41 std::string token
= nextToken(tokenType
);
42 if(tokenType
== END_OF_FILE
) break;
44 //std::cout << '"' << token << '"' << " of type " << nameOf(tokenType) << std::endl;
46 if(tokenType
== WORD
&& token
== "include") {
47 Parser().parse(vault
, expectNextToken(QUOTED_WORD
));
48 expectNextSymbol(";");
50 else if(tokenType
== WORD
&& token
== "module") {
51 currentModule
= expectNextToken(WORD
);
52 expectNextSymbol("{");
54 else if(tokenType
== SYMBOL
&& token
== "}") {
55 if(currentModule
!= "") {
58 else throw Common::ParsingException("Extra \"}\"");
60 else if(tokenType
== WORD
&& token
== "use") {
61 /*std::cout << "Parser: Using module \"" << expectNextToken(WORD) << "\"\n";*/
62 std::string moduleName
= expectNextToken(WORD
);
64 Parser().parse(vault
, Common::PathSanitizer::sanitize(moduleName
+ "/module.conf", paths
));
66 expectNextSymbol(";");
68 else if(tokenType
== WORD
) {
69 std::string op
= expectNextToken(SYMBOL
);
71 if(op
== "=") vault
->clear(token
);
75 std::string next
= nextToken(nextType
);
77 //if(nextType == SYMBOL && next == ";") break;
79 if(nextType
== WORD
|| nextType
== QUOTED_WORD
) {
80 if(currentModule
!= "") vault
->set(
81 Common::StreamAsString() << currentModule
<< ":" << token
, next
);
83 else vault
->set(token
, next
);
85 /*std::cout << "Set \"" << currentModule << "::" << token << "\" to \""
86 << next << "\" with operator " << op << std::endl;*/
88 else throw Common::ParsingException("Invalid RHS");
90 std::string sym
= expectNextToken(SYMBOL
);
92 else if(sym
== ",") {}
94 throw Common::ParsingException(Common::StreamAsString()
95 << "Expected \",\" or \";\", got \"" << sym
<< "\"");
100 throw Common::ParsingException(Common::StreamAsString()
101 << "Syntax error at token \"" << token
<< "\"");
103 //std::cout << "\"" << token << "\"\n";
109 void Parser::openFile(const std::string
&configFile
) {
110 m_stream
= new std::ifstream(configFile
.c_str());
113 std::string
Parser::nextToken(TokenType
&type
) {
114 std::ifstream
&stream
= *m_stream
;
123 if(stream
.peek() == '#') {
125 std::getline(stream
, line
);
126 return nextToken(type
);
128 else if(stream
.peek() == '"') {
129 stream
.get(); // skip "
132 while(stream
.peek() != '"') {
133 word
+= stream
.get();
136 stream
.get(); // skip "
141 else if(std::isalnum(stream
.peek())) {
143 while(std::isalnum(stream
.peek())) {
144 word
+= stream
.get();
150 else if(stream
.peek() == '+') {
151 stream
.get(); // skip '+'
152 if(stream
.peek() == '=') {
153 stream
.get(); // skip '='
161 throw Common::ParsingException(Common::StreamAsString()
162 << "Unrecognized token: \"+" << rest
<< "\"");
166 token
+= stream
.get();
173 std::string
Parser::expectNextToken(TokenType expected
) {
175 std::string token
= nextToken(actual
);
177 if(actual
!= expected
) {
178 throw Common::ParsingException(Common::StreamAsString()
179 << "Expected " << nameOf(expected
) << " token, found " << nameOf(actual
)
180 << " token: \"" << token
<< "\"");
186 void Parser::expectNextSymbol(const std::string
&symbol
) {
187 std::string s
= expectNextToken(SYMBOL
);
189 throw Common::ParsingException(Common::StreamAsString()
190 << "Expected token \"" << symbol
<< "\", got \"" << s
<< "\"");
194 void Parser::skipWhitespace() {
195 std::ifstream
&stream
= *m_stream
;
197 while(!stream
.fail() && std::isspace(stream
.peek())) {
202 void Parser::closeFile() {
207 const char *Parser::nameOf(TokenType type
) const {
208 static const char *name
[] = {
218 } // namespace Config
219 } // namespace Monitor