#region License /* ********************************************************************************** * Copyright (c) Roman Ivantsov * This source code is subject to terms and conditions of the MIT License * for Irony. A copy of the license can be found in the License.txt file * at the root of this distribution. * By using this source code in any fashion, you are agreeing to be bound by the terms of the * MIT License. * You must not remove this notice from this software. * **********************************************************************************/ #endregion using System; using System.Collections.Generic; using System.Text; namespace Irony.Compiler { public class SymbolTerminalTable : Dictionary { } //Represents a fixed symbol. // Contains static singleton dictionary, so that SymbolTerminal instances are created only once // for any symbol. public class SymbolTerminal : Terminal { private SymbolTerminal(string symbol, string name) : base(name) { _symbol = symbol; //Overwrite the Key assigned by base class (key derived from name): symbols are matched by value (symbol itself), not by element name Key = symbol.Trim(); #region comments // Priority - determines the order in which multiple terminals try to match input for a given current char in the input. // For a given input char the scanner looks up the collection of terminals that may match this input symbol. It is the order // in this collection that is determined by Priority value - the higher the priority, the earlier the terminal gets a chance // to check the input. //Symbols found in grammar by default have lowest priority to allow other terminals (like identifiers)to check the input first. // Additionally, longer symbols have higher priority, so symbols like "+=" should have higher priority value than "+" symbol. // As a result, Scanner would first try to match "+=", longer symbol, and if it fails, it will try "+". #endregion base.Priority = -1000 + symbol.Length; } public string Symbol { [System.Diagnostics.DebuggerStepThrough] get { return _symbol; } } string _symbol; #region overrides: TryMatch, GetPrefixes(), ToString() public override Token TryMatch(CompilerContext context, ISourceStream source) { if (!source.MatchSymbol(_symbol, !Grammar.CaseSensitive)) return null; source.Position += _symbol.Length; Token tkn = Token.Create(this, context, source.TokenStart, Symbol); return tkn; } public override IList GetFirsts() { return new string[] { _symbol }; } public override string ToString() { return _symbol; } #endregion //TODO: move Symbols table to Grammar instance #region static members: _symbols table of all symbol terminals private static SymbolTerminalTable _symbols = new SymbolTerminalTable(); public static void ClearSymbols() { _symbols.Clear(); } public static SymbolTerminal GetSymbol(string symbol) { return GetSymbol(symbol, symbol); } public static SymbolTerminal GetSymbol(string symbol, string name) { SymbolTerminal term; if (_symbols.TryGetValue(symbol, out term)) { //rename symbol if name is provided explicitly (different from symbol itself) if (name != symbol && term.Name != name) term.Name = name; return term; } string.Intern(symbol); term = new SymbolTerminal(symbol, name); term.SetOption(TermOptions.IsGrammarSymbol, true); _symbols[symbol] = term; return term; } #endregion [System.Diagnostics.DebuggerStepThrough] public override bool Equals(object obj) { return base.Equals(obj); } [System.Diagnostics.DebuggerStepThrough] public override int GetHashCode() { return _symbol.GetHashCode(); } }//class }