43 |
// to save us typing work in the rules action definitions |
// to save us typing work in the rules action definitions |
44 |
#define LSCPSERVER ((yyparse_param_t*) yyparse_param)->pServer |
#define LSCPSERVER ((yyparse_param_t*) yyparse_param)->pServer |
45 |
#define SESSION_PARAM ((yyparse_param_t*) yyparse_param) |
#define SESSION_PARAM ((yyparse_param_t*) yyparse_param) |
46 |
#define INCREMENT_LINE { SESSION_PARAM->iLine++; SESSION_PARAM->iColumn = 0; sParsed.clear(); } |
#define INCREMENT_LINE { SESSION_PARAM->onNextLine(); sParsed.clear(); } |
47 |
|
|
48 |
// clears input buffer |
// clears input buffer |
49 |
void restart(yyparse_param_t* pparam, int& yychar); |
void restart(yyparse_param_t* pparam, int& yychar); |
1840 |
* because it would end up in an endless loop otherwise. |
* because it would end up in an endless loop otherwise. |
1841 |
* |
* |
1842 |
* This solution consumes a lot of memory, but unfortunately there is no other |
* This solution consumes a lot of memory, but unfortunately there is no other |
1843 |
* easy way to solve it. With our grammar and today's memory heap & memory stack |
* easy way to solve it. With our grammar and today's memory heap size & memory |
1844 |
* it should be fine though. |
* stack size it should be fine though. |
1845 |
*/ |
*/ |
1846 |
typedef std::set< std::vector<YYTYPE_INT16> > YYStackHistory; |
typedef std::set< std::vector<YYTYPE_INT16> > YYStackHistory; |
1847 |
|
|
2009 |
* application will only have to show the results of the LSCP server's |
* application will only have to show the results of the LSCP server's |
2010 |
* evaluation to the user on the screen. |
* evaluation to the user on the screen. |
2011 |
* |
* |
2012 |
|
* @param line - the current command line to be evaluated by LSCP parser |
2013 |
|
* @param param = reentrant parser session parameters |
2014 |
|
* @param possibilities - whether all possibilities shall be shown |
2015 |
* @returns LSCP shell response line to be returned to the client |
* @returns LSCP shell response line to be returned to the client |
2016 |
*/ |
*/ |
2017 |
String lscpParserProcessShellInteraction(String& line, yyparse_param_t* param) { |
String lscpParserProcessShellInteraction(String& line, yyparse_param_t* param, bool possibilities) { |
2018 |
// first, determine how many characters (starting from the left) of the |
// first, determine how many characters (starting from the left) of the |
2019 |
// given input line are already syntactically correct |
// given input line are already syntactically correct |
2020 |
std::vector<YYTYPE_INT16> stack; |
std::vector<YYTYPE_INT16> stack; |
2029 |
line.replace(0, nMin, l.substr(0, nMin)); |
line.replace(0, nMin, l.substr(0, nMin)); |
2030 |
} |
} |
2031 |
|
|
2032 |
|
size_t cursorPos = line.size() + param->iCursorOffset; |
2033 |
|
if (cursorPos < 0) cursorPos = 0; |
2034 |
|
|
2035 |
// generate an info string that will be sent to the LSCP shell for letting |
// generate an info string that will be sent to the LSCP shell for letting |
2036 |
// it know which part is correct, which one is wrong, where is the cursor, etc. |
// it know which part is correct, which one is wrong, where is the cursor, etc. |
2037 |
String result = line; |
String result = line; |
2038 |
result.insert(n <= result.length() ? n : result.length(), LSCP_SHK_GOOD_FRONT); |
result.insert(n <= result.length() ? n : result.length(), LSCP_SHK_GOOD_FRONT); |
2039 |
|
result.insert(cursorPos <= n ? cursorPos : cursorPos + String(LSCP_SHK_GOOD_FRONT).length(), LSCP_SHK_CURSOR); |
2040 |
int code = (n > line.length()) ? LSCP_SHU_COMPLETE : (n < line.length()) ? |
int code = (n > line.length()) ? LSCP_SHU_COMPLETE : (n < line.length()) ? |
2041 |
LSCP_SHU_SYNTAX_ERR : LSCP_SHU_INCOMPLETE; |
LSCP_SHU_SYNTAX_ERR : LSCP_SHU_INCOMPLETE; |
2042 |
result = "SHU:" + ToString(code) + ":" + result + LSCP_SHK_CURSOR; |
result = "SHU:" + ToString(code) + ":" + result; |
2043 |
//if (n > line.length()) result += " [OK]"; |
//if (n > line.length()) result += " [OK]"; |
2044 |
|
|
2045 |
// get a clean parser stack to the last valid parse position |
// get a clean parser stack to the last valid parse position |
2051 |
if (!l.empty()) yyValidCharacters(stack, l, param->bShellAutoCorrect); |
if (!l.empty()) yyValidCharacters(stack, l, param->bShellAutoCorrect); |
2052 |
|
|
2053 |
// generate auto completion suggestion (based on the current parser stack) |
// generate auto completion suggestion (based on the current parser stack) |
2054 |
String sSuggestion = yyAutoComplete(stack); |
std::vector<YYTYPE_INT16> stackCopy = stack; // make a copy, since yyAutoComplete() might alter the stack |
2055 |
|
String sSuggestion = yyAutoComplete(stackCopy); |
2056 |
if (!sSuggestion.empty()) result += LSCP_SHK_SUGGEST_BACK + sSuggestion; |
if (!sSuggestion.empty()) result += LSCP_SHK_SUGGEST_BACK + sSuggestion; |
2057 |
|
|
2058 |
|
if (!possibilities) return result; |
2059 |
|
|
2060 |
|
// finally append all possible terminals and non-terminals according to |
2061 |
|
// current parser state |
2062 |
|
String notUsedHere; |
2063 |
|
std::map<String,BisonSymbolInfo> expectedSymbols; |
2064 |
|
walkAndFillExpectedSymbols(stack, expectedSymbols, notUsedHere); |
2065 |
|
{ |
2066 |
|
// pretend to LSCP shell that the following terminal symbols were |
2067 |
|
// non-terminal symbols (since they are not human visible for auto |
2068 |
|
// completion on the shell's screen) |
2069 |
|
std::set<String> specialNonTerminals; |
2070 |
|
specialNonTerminals.insert("SP"); |
2071 |
|
specialNonTerminals.insert("CR"); |
2072 |
|
specialNonTerminals.insert("LF"); |
2073 |
|
|
2074 |
|
String sPossibilities; |
2075 |
|
int iNonTerminals = 0; |
2076 |
|
int iTerminals = 0; |
2077 |
|
for (std::map<String,BisonSymbolInfo>::const_iterator it = expectedSymbols.begin(); |
2078 |
|
it != expectedSymbols.end(); ++it) |
2079 |
|
{ |
2080 |
|
if (!sPossibilities.empty()) sPossibilities += " | "; |
2081 |
|
if (it->second.isTerminalSymbol && !specialNonTerminals.count(it->first)) { |
2082 |
|
sPossibilities += it->first; |
2083 |
|
iTerminals++; |
2084 |
|
} else { |
2085 |
|
sPossibilities += "<" + it->first + ">"; |
2086 |
|
iNonTerminals++; |
2087 |
|
} |
2088 |
|
} |
2089 |
|
if (!sPossibilities.empty() && (iNonTerminals || iTerminals > 1)) { |
2090 |
|
result += LSCP_SHK_POSSIBILITIES_BACK + sPossibilities; |
2091 |
|
} |
2092 |
|
} |
2093 |
|
|
2094 |
#if DEBUG_SHELL_INTERACTION |
#if DEBUG_SHELL_INTERACTION |
2095 |
printf("%s\n", result.c_str()); |
printf("%s\n", result.c_str()); |
2096 |
#endif |
#endif |