Пример #1
0
		/// This method implements the DFA algorithm and returns a token
		/// to the LALR state machine.
		private Token RetrieveToken()
		{
			Token result;
			int currentPos = 0;
			int lastAcceptState = -1;
			int lastAcceptPos = -1;
			FAState currentState = m_DfaStates[m_initDfaState];
			
			try
			{
				while (true)
				{
					// This code searches all the branches of the current DFA state for the next
					// character in the input LookaheadStream. If found the target state is returned.
					// The InStr() function searches the string pCharacterSetTable.Member(CharSetIndex)
					// starting at position 1 for ch.  The pCompareMode variable determines whether
					// the search is case sensitive.
					int	target = -1;
					char ch = FixCase(m_source.LookAhead(currentPos));
					
					foreach (FAEdge edge in currentState.Edges)
					{
						String chars = edge.Characters;
						if (chars.IndexOf(ch) != -1)
						{
							target = edge.TargetIndex;
							break;
						}
					}
					
					// This block-if statement checks whether an edge was found from the current state.
					// If so, the state and current position advance. Otherwise it is time to exit the main loop
					// and report the token found (if there was it fact one). If the LastAcceptState is -1,
					// then we never found a match and the Error Token is created. Otherwise, a new token
					// is created using the Symbol in the Accept State and all the characters that
					// comprise it.
					if (target != -1)
					{
						// This code checks whether the target state accepts a token. If so, it sets the
						// appropiate variables so when the algorithm is done, it can return the proper
						// token and number of characters.
						if (m_DfaStates[target].AcceptSymbol != -1)
						{
							lastAcceptState = target;
							lastAcceptPos = currentPos;
						}
	
						currentState = m_DfaStates[target];
						currentPos++;
					}
					else
					{
						if (lastAcceptState == -1)
						{
							result = new Token(m_errorSymbol);
							result.Data = m_source.Read(1);
						}
						else
						{
							Symbol symbol = m_symbols[m_DfaStates[lastAcceptState].AcceptSymbol];
							result = new Token(symbol);
							result.Data = m_source.Read(lastAcceptPos + 1);
						}
						break;
					}
				}
			}
			catch (EndOfStreamException)
			{
				result = new Token(m_endSymbol);
				result.Data = "";
			}

			UpdateLineNumber((String)result.Data);			

			return result;
		}
Пример #2
0
		/// This function analyzes a token and either:
		///   1. Makes a SINGLE reduction and pushes a complete Reduction object on the stack
		///   2. Accepts the token and shifts
		///   3. Errors and places the expected symbol indexes in the Tokens list
		/// The Token is assumed to be valid and WILL be checked
		private ParseResult ParseToken(Token p_token)
		{
			ParseResult result = ParseResult.InternalError;
			LRActionTable table = m_LalrTables[m_LalrState];
			LRAction action = table.GetActionForSymbol(p_token.TableIndex);
			
			if (action != null)
			{
				m_haveReduction = false;
				m_outputTokens.Clear();
				
				switch (action.Action)
				{
				case Action.Accept:
					m_haveReduction = true;
					result = ParseResult.Accept;
					break;
				case Action.Shift:
					p_token.State = m_LalrState = action.Value;
					m_tempStack.PushToken(p_token);
					result = ParseResult.Shift;
					break;
				case Action.Reduce:
					result = Reduce(m_rules[action.Value]);
					break;
				}
			}
			else
			{
				// syntax error - fill expected tokens.				
				m_outputTokens.Clear();				
				foreach (LRAction a in table.Members)
				{
					SymbolType kind = a.Symbol.Kind;
					
					if (kind == SymbolType.Terminal || kind == SymbolType.End)
						m_outputTokens.PushToken(new Token(a.Symbol));
				}				
				result = ParseResult.SyntaxError;
			}
			
			return result;
		}
Пример #3
0
		/// <summary>Produces a reduction.</summary>
		/// <remarks>Removes as many tokens as members in the rule and pushes a 
		///          non-terminal token.</remarks>
		private ParseResult Reduce(Rule p_rule)
		{
			ParseResult result;
			Token head;
			
			if (m_trimReductions && p_rule.ContainsOneNonTerminal)
			{
				// The current rule only consists of a single nonterminal and can be trimmed from the
				// parse tree. Usually we create a new Reduction, assign it to the Data property
				// of Head and push it on the stack. However, in this case, the Data property of the
				// Head will be assigned the Data property of the reduced token (i.e. the only one
				// on the stack). In this case, to save code, the value popped of the stack is changed 
				// into the head.
				head = m_tempStack.PopToken();
				head.SetParent(p_rule.RuleNonTerminal);
				
				result = ParseResult.ReduceEliminated;
			}
			else
			{
				Reduction reduction = new Reduction();
				reduction.ParentRule = p_rule;
				
				m_tempStack.PopTokensInto(reduction, p_rule.SymbolCount);

				head = new Token();
				head.Data = reduction;
				head.SetParent(p_rule.RuleNonTerminal);
				
				m_haveReduction = true;
				result = ParseResult.ReduceNormal;
			}
			
			int index = m_tempStack.PeekToken().State;
			LRAction action = m_LalrTables[index].GetActionForSymbol(p_rule.RuleNonTerminal.TableIndex);
			
			if (action != null)
			{
				head.State = m_LalrState = action.Value;;
				m_tempStack.PushToken(head);
			}
			else
				throw new ParserException("Action for LALR state is null");
				
			return result;
		}
Пример #4
0
		/// Returns true if the specified token is a CommentLine or CommentStart-symbol.
		private bool CommentToken(Token p_token)
		{
			return (p_token.Kind == SymbolType.CommentLine) 
				|| (p_token.Kind == SymbolType.CommentStart);
		}
Пример #5
0
		private void PrepareToParse()
		{
			Token token = new Token();
			token.State = m_initLalrState;
			token.SetParent(m_symbols[m_startSymbol]);
			m_tempStack.PushToken(token);
		}
Пример #6
0
		/* public methods */
		
		/// Pushes the specified token onto the internal input queue. 
		/// It will be the next token analyzed by the parsing engine.
		public void PushInputToken(Token p_token)
		{
			m_inputTokens.PushToken(p_token);
		}
Пример #7
0
		/// Pushes the specified token on the stack.
		public void PushToken(Token p_token)
		{
			m_items.Add(p_token);
		}
Пример #8
0
		/* internal methods */

		///
		internal void AddToken(Token p_token)
		{
			m_tokens.Add(p_token);
		}