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
18 #include "config/Parser.h"
19 #include "common/ParsingException.h"
20 #include "common/StreamAsString.h"
21 #include "config/ConcreteVault.h"
26 void Parser::parse(ConcreteVault
*vault
, const std::string
&configFile
) {
27 std::string currentModule
;
33 std::string token
= nextToken(tokenType
);
34 if(tokenType
== END_OF_FILE
) break;
36 //std::cout << '"' << token << '"' << " of type " << nameOf(tokenType) << std::endl;
38 if(tokenType
== WORD
&& token
== "include") {
39 Parser().parse(vault
, expectNextToken(QUOTED_WORD
));
40 expectNextSymbol(";");
42 else if(tokenType
== WORD
&& token
== "module") {
43 currentModule
= expectNextToken(WORD
);
44 expectNextSymbol("{");
46 else if(tokenType
== SYMBOL
&& token
== "}") {
47 if(currentModule
!= "") {
50 else throw Common::ParsingException("Extra \"}\"");
52 else if(tokenType
== WORD
&& token
== "use") {
53 /*std::cout << "Parser: Using module \"" << expectNextToken(WORD) << "\"\n";*/
54 vault
->set("LD_PRELOAD", expectNextToken(WORD
));
55 expectNextSymbol(";");
57 else if(tokenType
== WORD
) {
58 std::string op
= expectNextToken(SYMBOL
);
60 if(op
== "=") vault
->clear(token
);
64 std::string next
= nextToken(nextType
);
66 //if(nextType == SYMBOL && next == ";") break;
68 if(nextType
== WORD
|| nextType
== QUOTED_WORD
) {
69 if(currentModule
!= "") vault
->set(
70 Common::StreamAsString() << currentModule
<< ":" << token
, next
);
72 else vault
->set(token
, next
);
74 std::cout
<< "Set \"" << currentModule
<< "::" << token
<< "\" to \""
75 << next
<< "\" with operator " << op
<< std::endl
;
77 else throw Common::ParsingException("Invalid RHS");
79 std::string sym
= expectNextToken(SYMBOL
);
81 else if(sym
== ",") {}
83 throw Common::ParsingException(Common::StreamAsString()
84 << "Expected \",\" or \";\", got \"" << sym
<< "\"");
89 throw Common::ParsingException(Common::StreamAsString()
90 << "Syntax error at token \"" << token
<< "\"");
92 //std::cout << "\"" << token << "\"\n";
98 void Parser::openFile(const std::string
&configFile
) {
99 m_stream
= new std::ifstream(configFile
.c_str());
100 if(!m_stream
->is_open()) {
101 std::cout
<< "Error opening config file \"" << configFile
<< "\"\n";
105 std::string
Parser::nextToken(TokenType
&type
) {
106 std::ifstream
&stream
= *m_stream
;
115 if(stream
.peek() == '#') {
117 std::getline(stream
, line
);
118 return nextToken(type
);
120 else if(stream
.peek() == '"') {
121 stream
.get(); // skip "
124 while(stream
.peek() != '"') {
125 word
+= stream
.get();
128 stream
.get(); // skip "
133 else if(std::isalnum(stream
.peek())) {
135 while(std::isalnum(stream
.peek())) {
136 word
+= stream
.get();
142 else if(stream
.peek() == '+') {
143 stream
.get(); // skip '+'
144 if(stream
.peek() == '=') {
145 stream
.get(); // skip '='
153 throw Common::ParsingException(Common::StreamAsString()
154 << "Unrecognized token: \"+" << rest
<< "\"");
158 token
+= stream
.get();
165 std::string
Parser::expectNextToken(TokenType expected
) {
167 std::string token
= nextToken(actual
);
169 if(actual
!= expected
) {
170 throw Common::ParsingException(Common::StreamAsString()
171 << "Expected " << nameOf(expected
) << " token, found " << nameOf(actual
)
172 << " token: \"" << token
<< "\"");
178 void Parser::expectNextSymbol(const std::string
&symbol
) {
179 std::string s
= expectNextToken(SYMBOL
);
181 throw Common::ParsingException(Common::StreamAsString()
182 << "Expected token \"" << symbol
<< "\", got \"" << s
<< "\"");
186 void Parser::skipWhitespace() {
187 std::ifstream
&stream
= *m_stream
;
189 while(!stream
.fail() && std::isspace(stream
.peek())) {
194 void Parser::closeFile() {
199 const char *Parser::nameOf(TokenType type
) const {
200 static const char *name
[] = {
210 } // namespace Config
211 } // namespace Monitor