• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *
3  * Copyright 2012 BMW Car IT GmbH
4  *
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  ****************************************************************************/
19 #include "ExpressionInterpreter.h"
20 #include "Expression.h"
21 #include "ilm_control.h"
22 #include <string>
23 #include <sstream>
24 #include <algorithm> // transform
25 #include <ctype.h> // tolower
26 
27 #include <iostream>
28 
29 Expression* ExpressionInterpreter::mpRoot = NULL;
30 
ExpressionInterpreter()31 ExpressionInterpreter::ExpressionInterpreter()
32 : mErrorText("No error.")
33 {
34 }
35 
addExpression(callback funcPtr,string command)36 bool ExpressionInterpreter::addExpression(callback funcPtr, string command)
37 {
38     bool result = false;
39 
40     string text;
41     stringstream ss;
42     ss << command;
43 
44     if (!mpRoot)
45     {
46         mpRoot = new Expression("[root]", NULL);
47     }
48 
49     Expression* currentWord = mpRoot;
50 
51     while (!ss.eof())
52     {
53         ss >> text;
54         transform(text.begin(), text.end(), text.begin(), ::tolower);
55 
56         Expression* nextWord = currentWord->getNextExpression(text);
57 
58         if (!nextWord)
59         {
60             nextWord = new Expression(text, currentWord);
61             currentWord->addNextExpression(nextWord);
62         }
63 
64         currentWord = nextWord;
65     }
66 
67     currentWord->setFunc(funcPtr);
68 
69     return result;
70 }
71 
interpretCommand(string userInput)72 CommandResult ExpressionInterpreter::interpretCommand(string userInput)
73 {
74     CommandResult result = CommandSuccess;
75     string text;
76     stringstream ss;
77     ss << userInput;
78 
79     ExpressionList currentState;
80     currentState.push_back(mpRoot);
81     ExpressionList nextState;
82 
83     while (result == CommandSuccess && !ss.eof())
84     {
85         ss >> text;
86 
87         ExpressionList::const_iterator iter = currentState.begin();
88         ExpressionList::const_iterator end = currentState.end();
89         for (; iter != end; ++iter)
90         {
91             Expression* expr = *iter;
92             ExpressionList exprNextList = expr->getNextExpressionClosure(text);
93             nextState.splice(nextState.end(), exprNextList);
94         }
95 
96         if (nextState.size() > 0)
97         {
98             currentState = nextState;
99             nextState.clear();
100         }
101         else
102         {
103             mErrorText = "'" + text + "' not recognized.";
104             result = CommandInvalid;
105         }
106     }
107 
108     //remove impossible expressions in the final state before checking for ambiguity
109     nextState.clear();
110     ExpressionList::const_iterator iter = currentState.begin();
111     ExpressionList::const_iterator end = currentState.end();
112     for (; iter != end; ++iter)
113     {
114         Expression* expr = *iter;
115         if (expr->isExecutable())
116         {
117             nextState.push_back(expr);
118         }
119         else
120         {
121             ExpressionList children = expr->getNextExpressions();
122 
123             bool flag = false;
124 
125             ExpressionList::const_iterator iter = children.begin();
126             ExpressionList::const_iterator end = children.end();
127             for (; iter != end; ++iter)
128             {
129                 if ((*iter)->getName()[0] == '[')
130                 {
131                     flag = true;
132                 }
133             }
134 
135             if (flag || children.size() == 0)
136             {
137                 nextState.push_back(expr);
138             }
139         }
140     }
141 
142     currentState = nextState;
143 
144     if (currentState.size() != 1)
145     {
146         mErrorText = "'" + text + "' ambiguous or incomplete.";
147         result = CommandInvalid;
148     }
149 
150     //run command if executable and non-ambiguous
151     if (result == CommandSuccess)
152     {
153         Expression* expr = *(currentState.begin());
154 
155         ExpressionList executables = expr->getClosureExecutables(false);
156         if (executables.size() == 1)
157         {
158             ilmErrorTypes initResult = ilm_init();
159             if (ILM_SUCCESS != initResult)
160             {
161                 mErrorText = ILM_ERROR_STRING(initResult);
162                 result = CommandExecutionFailed;
163             }
164             else
165             {
166                 Expression* exec = executables.front();
167                 exec->execute();
168                 ilm_commitChanges();
169                 ilm_destroy();
170             }
171         }
172         else if (executables.size() == 0)
173         {
174             mErrorText = "command is incomplete.";
175             result = CommandIncomplete;
176         }
177         else
178         {
179             mErrorText = "command is ambiguous.";
180             result = CommandIncomplete;
181         }
182     }
183 
184     return result;
185 }
186 
printExpressionTree()187 void ExpressionInterpreter::printExpressionTree()
188 {
189     mpRoot->printTree();
190 }
191 
printExpressionList()192 void ExpressionInterpreter::printExpressionList()
193 {
194     mpRoot->printList();
195 }
196 
getLastError()197 string ExpressionInterpreter::getLastError()
198 {
199     string tmp = mErrorText;
200     mErrorText = "no error.";
201     return tmp;
202 }
203