Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
5.3 KiB

  1. /*++
  2. Copyright Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. GENLEX.CPP
  5. Abstract:
  6. Generic lexer framework classes.
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include <genlex.h>
  11. //***************************************************************************
  12. //
  13. //***************************************************************************
  14. CGenLexer::CGenLexer(LexEl *pTbl, CGenLexSource *pSrc)
  15. {
  16. m_nCurBufSize = 256;
  17. m_pTokenBuf = (wchar_t *) HeapAlloc(GetProcessHeap(), 0,
  18. m_nCurBufSize * 2);
  19. m_nCurrentLine = 1;
  20. m_pTable = pTbl;
  21. m_pSrc = pSrc;
  22. }
  23. //***************************************************************************
  24. //
  25. //***************************************************************************
  26. void CGenLexer::Reset()
  27. {
  28. m_pSrc->Reset();
  29. m_nCurrentLine = 1;
  30. }
  31. //***************************************************************************
  32. //
  33. //***************************************************************************
  34. CGenLexer::~CGenLexer()
  35. {
  36. HeapFree(GetProcessHeap(), 0, m_pTokenBuf);
  37. }
  38. //***************************************************************************
  39. //
  40. //***************************************************************************
  41. int CGenLexer::NextToken()
  42. {
  43. int nState = 0;
  44. int nCurBufEnd = 0;
  45. BOOL bRead = TRUE;
  46. wchar_t cCurrent = 0;
  47. BOOL bEOF = FALSE;
  48. if (m_pTokenBuf == 0)
  49. return 0;
  50. *m_pTokenBuf = 0;
  51. // Generic DFA driver based on the table specified
  52. // in the constructor.
  53. // ===============================================
  54. while (1)
  55. {
  56. BOOL bMatch = FALSE;
  57. WORD wInstructions = m_pTable[nState].wInstructions;
  58. if (bRead)
  59. {
  60. if(bEOF)
  61. {
  62. // The lexer table allowed us to go past end of string!!!
  63. return 1;
  64. }
  65. cCurrent = m_pSrc->NextChar();
  66. if(cCurrent == 0)
  67. bEOF = TRUE;
  68. }
  69. bRead = FALSE;
  70. // Check here if only the first character is present.
  71. // ==================================================
  72. if (m_pTable[nState].cFirst == GLEX_ANY)
  73. bMatch = TRUE;
  74. else if (m_pTable[nState].cLast == GLEX_EMPTY)
  75. {
  76. if (cCurrent == m_pTable[nState].cFirst)
  77. bMatch = TRUE;
  78. else if ((wInstructions & GLEX_NOT) &&
  79. !(cCurrent == m_pTable[nState].cFirst))
  80. bMatch = TRUE;
  81. }
  82. // If here, both first/last are present and we
  83. // are testing to see if the input is in between.
  84. // ==============================================
  85. else if (m_pTable[nState].cFirst != GLEX_ANY)
  86. {
  87. if ((wInstructions & GLEX_NOT) &&
  88. !(cCurrent >= m_pTable[nState].cFirst &&
  89. cCurrent <= m_pTable[nState].cLast))
  90. bMatch = TRUE;
  91. else if (cCurrent >= m_pTable[nState].cFirst &&
  92. cCurrent <= m_pTable[nState].cLast)
  93. bMatch = TRUE;
  94. }
  95. // Interpret the instruction field to determine
  96. // whether the character is actually to be included
  97. // in the token text.
  98. // ================================================
  99. if (bMatch)
  100. {
  101. if (wInstructions & GLEX_ACCEPT)
  102. {
  103. // Expand the current buffer, if required.
  104. // =======================================
  105. if (nCurBufEnd == m_nCurBufSize - 1)
  106. {
  107. m_nCurBufSize += 256;
  108. PVOID pTmp = HeapReAlloc(GetProcessHeap(), 0, m_pTokenBuf,m_nCurBufSize * 2);
  109. if (pTmp == 0) return 0; // out of memory
  110. m_pTokenBuf = (wchar_t *)pTmp;
  111. }
  112. m_pTokenBuf[nCurBufEnd] = cCurrent;
  113. m_pTokenBuf[++nCurBufEnd]= 0;
  114. bRead = TRUE;
  115. }
  116. if (wInstructions & GLEX_CONSUME)
  117. bRead = TRUE;
  118. // else GLEX_CONSUME, which means 'skip'
  119. // If the PUSHBACK instruction is present,
  120. // push the char back.
  121. // ======================================
  122. if (wInstructions & GLEX_PUSHBACK)
  123. {
  124. bRead = TRUE;
  125. m_pSrc->Pushback(cCurrent);
  126. }
  127. // If a linefeed instruction.
  128. // ==========================
  129. if (wInstructions & GLEX_LINEFEED)
  130. m_nCurrentLine++;
  131. // If the return field is present and there was
  132. // a match, then return the specified token. Alternately,
  133. // the GLEX_RETURN instruction will force a return
  134. // match, or no match.
  135. // =======================================================
  136. if (m_pTable[nState].wReturnTok ||
  137. (wInstructions & GLEX_RETURN))
  138. return int(m_pTable[nState].wReturnTok);
  139. nState = int(m_pTable[nState].wGotoState);
  140. }
  141. // If here, there was no match.
  142. // ===================================
  143. else
  144. nState++;
  145. }
  146. return 0; // No path to here
  147. }