/[svn]/linuxsampler/trunk/src/network/lscp.y
ViewVC logotype

Diff of /linuxsampler/trunk/src/network/lscp.y

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2531 by schoenebeck, Wed Mar 5 00:02:21 2014 UTC revision 2532 by schoenebeck, Wed Mar 5 17:29:15 2014 UTC
# Line 1450  inline static int _yyDefaultReduce(std:: Line 1450  inline static int _yyDefaultReduce(std::
1450    
1451  static bool yyValid(std::vector<YYTYPE_INT16>& stack, char ch);  static bool yyValid(std::vector<YYTYPE_INT16>& stack, char ch);
1452    
1453    /**
1454     * A set of parser symbol stacks. This type is used for the recursive algorithms
1455     * in a) yyAutoComplete() and b) walkAndFillExpectedSymbols() for detecting
1456     * endless recursions.
1457     *
1458     * This unique container is used to keep track of all previous parser states
1459     * (stacks), for detecting a parser symbol stack that has already been
1460     * encountered before. Because if yyAutoComplete() or
1461     * walkAndFillExpectedSymbols() reach the exactly same parser symbol stack
1462     * again, that means there is an endless recursion in that part of the grammar
1463     * tree branch and shall not be evaluated any further, since it would end up in
1464     * an endless loop of the algorithm otherwise.
1465     *
1466     * This solution consumes a lot of memory, but unfortunately there is no other
1467     * easy way to solve it. With our grammar and today's usual memory heap size &
1468     * memory stack size in modern devices, it should be fine though.
1469     */
1470    typedef std::set< std::vector<YYTYPE_INT16> > YYStackHistory;
1471    
1472  #define DEBUG_BISON_SYNTAX_ERROR_WALKER 0  #define DEBUG_BISON_SYNTAX_ERROR_WALKER 0
1473    
1474  /**  /**
# Line 1472  static bool yyValid(std::vector<YYTYPE_I Line 1491  static bool yyValid(std::vector<YYTYPE_I
1491   * @param nextExpectedChars - just for internal purpose, due to the recursive   * @param nextExpectedChars - just for internal purpose, due to the recursive
1492   *                            implementation of this function, do supply an   *                            implementation of this function, do supply an
1493   *                            empty character for this argument   *                            empty character for this argument
1494     * @param history - only for internal purpose, keeps a history of all previous
1495     *                  parser symbol stacks (just for avoiding endless recursion in
1496     *                  this recursive algorithm)
1497   * @param depth - just for internal debugging purposes   * @param depth - just for internal debugging purposes
1498   */   */
1499  static void walkAndFillExpectedSymbols(  static void walkAndFillExpectedSymbols(
1500      std::vector<YYTYPE_INT16>& stack,      std::vector<YYTYPE_INT16>& stack,
1501      std::map<String,BisonSymbolInfo>& expectedSymbols,      std::map<String,BisonSymbolInfo>& expectedSymbols,
1502      String& nextExpectedChars, int depth = 0)      String& nextExpectedChars, YYStackHistory& history, int depth = 0)
1503  {  {
1504  #if DEBUG_BISON_SYNTAX_ERROR_WALKER  #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1505      printf("\n");      printf("\n");
# Line 1490  static void walkAndFillExpectedSymbols( Line 1512  static void walkAndFillExpectedSymbols(
1512  #endif  #endif
1513      startLabel:      startLabel:
1514    
1515        // detect endless recursion
1516        if (history.count(stack)) return;
1517        history.insert(stack);
1518    
1519      if (stack.empty()) {      if (stack.empty()) {
1520  #if DEBUG_BISON_SYNTAX_ERROR_WALKER  #if DEBUG_BISON_SYNTAX_ERROR_WALKER
1521          for (int i = 0; i < depth; ++i) printf("\t");          for (int i = 0; i < depth; ++i) printf("\t");
# Line 1586  static void walkAndFillExpectedSymbols( Line 1612  static void walkAndFillExpectedSymbols(
1612              nextExpectedChars += _tokenName(token);              nextExpectedChars += _tokenName(token);
1613              nextExpectedCharsLen = nextExpectedChars.size();              nextExpectedCharsLen = nextExpectedChars.size();
1614              walkAndFillExpectedSymbols( //FIXME: could cause stack overflow (should be a loop instead), is probably fine with our current grammar though              walkAndFillExpectedSymbols( //FIXME: could cause stack overflow (should be a loop instead), is probably fine with our current grammar though
1615                  stackCopy, expectedSymbols, nextExpectedChars, depth + 1                  stackCopy, expectedSymbols, nextExpectedChars, history, depth + 1
1616              );              );
1617              nextExpectedChars.resize(nextExpectedCharsLen); // restore 'nextExpectedChars'              nextExpectedChars.resize(nextExpectedCharsLen); // restore 'nextExpectedChars'
1618              continue;              continue;
# Line 1632  static void walkAndFillExpectedSymbols( Line 1658  static void walkAndFillExpectedSymbols(
1658          stack.push_back(action);          stack.push_back(action);
1659          nextExpectedChars += _tokenName(token);          nextExpectedChars += _tokenName(token);
1660          walkAndFillExpectedSymbols( //FIXME: could cause stack overflow (should be a loop instead), is probably fine with our current grammar though          walkAndFillExpectedSymbols( //FIXME: could cause stack overflow (should be a loop instead), is probably fine with our current grammar though
1661              stack, expectedSymbols, nextExpectedChars, depth + 1              stack, expectedSymbols, nextExpectedChars, history, depth + 1
1662          );          );
1663          stack.resize(stackSize); // restore stack          stack.resize(stackSize); // restore stack
1664          nextExpectedChars.resize(nextExpectedCharsLen); // restore 'nextExpectedChars'          nextExpectedChars.resize(nextExpectedCharsLen); // restore 'nextExpectedChars'
# Line 1673  static void walkAndFillExpectedSymbols( Line 1699  static void walkAndFillExpectedSymbols(
1699  #endif  #endif
1700  }  }
1701    
1702    /**
1703     * Just a convenience wrapper on top of the actual walkAndFillExpectedSymbols()
1704     * implementation above, which can be called with less parameters than the
1705     * implementing function above actually requires.
1706     */
1707    static void walkAndFillExpectedSymbols(
1708        std::vector<YYTYPE_INT16>& stack,
1709        std::map<String,BisonSymbolInfo>& expectedSymbols)
1710    {
1711        String nextExpectedChars;
1712        YYStackHistory history;
1713    
1714        walkAndFillExpectedSymbols(
1715            stack, expectedSymbols, nextExpectedChars, history
1716        );
1717    }
1718    
1719  #define DEBUG_PUSH_PARSE 0  #define DEBUG_PUSH_PARSE 0
1720    
1721  /**  /**
# Line 1818  static std::set<String> yyExpectedSymbol Line 1861  static std::set<String> yyExpectedSymbol
1861      for (int i = 0; i < iStackSize; ++i) {      for (int i = 0; i < iStackSize; ++i) {
1862          stack.push_back(ss[i]);          stack.push_back(ss[i]);
1863      }      }
     String notUsedHere;  
1864      // do the actual parser work      // do the actual parser work
1865      walkAndFillExpectedSymbols(stack, expectedSymbols, notUsedHere);      walkAndFillExpectedSymbols(stack, expectedSymbols);
1866    
1867      // convert expectedSymbols to the result set      // convert expectedSymbols to the result set
1868      std::set<String> result;      std::set<String> result;
# Line 1832  static std::set<String> yyExpectedSymbol Line 1874  static std::set<String> yyExpectedSymbol
1874  #define DEBUG_YY_AUTO_COMPLETE 0  #define DEBUG_YY_AUTO_COMPLETE 0
1875    
1876  /**  /**
  * A set of parser symbol stacks. This type is used in yyAutoComplete() to keep  
  * track of all previous parser states, for detecting a parser symbol stack that  
  * has already been before. Because if yyAutoComplete() reaches the exactly same  
  * parser symbol stack again, it means there is an endless recursion in that  
  * part of the grammar tree branch and shall not be evaluated any further,  
  * because it would end up in an endless loop otherwise.  
  *  
  * This solution consumes a lot of memory, but unfortunately there is no other  
  * easy way to solve it. With our grammar and today's memory heap size & memory  
  * stack size it should be fine though.  
  */  
 typedef std::set< std::vector<YYTYPE_INT16> > YYStackHistory;  
   
 /**  
1877   * Generates and returns an auto completion string for the current parser   * Generates and returns an auto completion string for the current parser
1878   * state given by @a stack. That means, this function will return the longest   * state given by @a stack. That means, this function will return the longest
1879   * sequence of characters that is uniqueley expected to be sent next by the LSCP   * sequence of characters that is uniqueley expected to be sent next by the LSCP
# Line 1874  typedef std::set< std::vector<YYTYPE_INT Line 1902  typedef std::set< std::vector<YYTYPE_INT
1902   */   */
1903  static String yyAutoComplete(std::vector<YYTYPE_INT16>& stack, YYStackHistory& history, int depth = 0) {  static String yyAutoComplete(std::vector<YYTYPE_INT16>& stack, YYStackHistory& history, int depth = 0) {
1904      std::map<String,BisonSymbolInfo> expectedSymbols;      std::map<String,BisonSymbolInfo> expectedSymbols;
1905      String notUsedHere;      walkAndFillExpectedSymbols(stack, expectedSymbols);
     walkAndFillExpectedSymbols(stack, expectedSymbols, notUsedHere);  
1906      if (expectedSymbols.size() == 1) {      if (expectedSymbols.size() == 1) {
1907          String name          = expectedSymbols.begin()->first;          String name          = expectedSymbols.begin()->first;
1908          BisonSymbolInfo info = expectedSymbols.begin()->second;          BisonSymbolInfo info = expectedSymbols.begin()->second;
# Line 2059  String lscpParserProcessShellInteraction Line 2086  String lscpParserProcessShellInteraction
2086    
2087      // finally append all possible terminals and non-terminals according to      // finally append all possible terminals and non-terminals according to
2088      // current parser state      // current parser state
     String notUsedHere;  
2089      std::map<String,BisonSymbolInfo> expectedSymbols;      std::map<String,BisonSymbolInfo> expectedSymbols;
2090      walkAndFillExpectedSymbols(stack, expectedSymbols, notUsedHere);      walkAndFillExpectedSymbols(stack, expectedSymbols);
2091      {      {
2092          // pretend to LSCP shell that the following terminal symbols were          // pretend to LSCP shell that the following terminal symbols were
2093          // non-terminal symbols (since they are not human visible for auto          // non-terminal symbols (since they are not human visible for auto

Legend:
Removed from v.2531  
changed lines
  Added in v.2532

  ViewVC Help
Powered by ViewVC