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.

198 lines
5.6 KiB

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