pascalabcnet/ParserTools/ParserTools/Keywords/BaseKeywords.cs

124 lines
5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace PascalABCCompiler.Parsers
{
public abstract class BaseKeywords
{
/// <summary>
/// Соотвествие ключевых слов токенам (ключевые слова для парсера)
/// </summary>
public Dictionary<string, int> KeywordsToTokens { get; set; }
/// <summary>
/// Типы ключевых слов
/// </summary>
public Dictionary<string, KeywordKind> KeywordKinds { get; set; }
/// <summary>
/// Ключевые слова в контексте Intellisense (множество)
/// </summary>
public HashSet<string> KeywordsForIntellisenseSet { get; }
/// <summary>
/// Ключевые слова в контексте Intellisense (список)
/// </summary>
public List<string> KeywordsForIntellisenseList { get; set; } = new List<string>();
/// <summary>
/// Ключевые слова, соответствующие типам (array, set), либо классу, функции
/// </summary>
public List<string> TypeKeywords { get; set; } = new List<string>();
/// <summary>
/// Словарь соответствий ключевых слов их эквивалентам (задается пользователем в специальном файле)
/// </summary>
private Dictionary<string, string> keymap = new Dictionary<string, string>();
/// <summary>
/// Название файла с информацией об эквивалентах ключевых слов
/// </summary>
protected abstract string FileName { get; }
/// <summary>
/// Функция загрузки эквивалентов ключевых слов из файла
/// </summary>
private void ReloadKeyMap()
{
try
{
var pathToKeymapFile = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName), FileName);
if (System.IO.File.Exists(pathToKeymapFile))
keymap = System.IO.File.ReadLines(pathToKeymapFile, Encoding.Unicode).Select(s => s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)).ToDictionary(w => w[0], w => w[1]);
}
catch (Exception)
{
//var w = e.Message;
}
}
/// <summary>
/// Возвращает эквивалент ключевого слова, либо его самого, если эквивалента нет
/// </summary>
public string ConvertKeyword(string keyword)
{
if (keymap.Count() == 0 || !keymap.ContainsKey(keyword))
return keyword;
else
return keymap[keyword];
}
public BaseKeywords(bool caseSensitive)
{
ReloadKeyMap();
StringComparer stringComparer = caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
KeywordsToTokens = new Dictionary<string, int>(stringComparer);
KeywordsForIntellisenseSet = new HashSet<string>(stringComparer);
KeywordKinds = new Dictionary<string, KeywordKind>(stringComparer);
}
/// <summary>
/// Возвращает токен, соответствующий идентификатору
/// </summary>
protected abstract int GetIdToken();
/// <summary>
/// Возвращает токен соответствующий ключевому слову, либо токен идентификатора, если такого ключевого слова нет
/// </summary>
public int KeywordOrIDToken(string keyword)
{
if (KeywordsToTokens.TryGetValue(keyword, out int token))
return token;
else
return GetIdToken();
}
public void CreateNewKeyword(string name, Enum token = null, KeywordKind kind = KeywordKind.None, bool isTypeKeyword = false)
{
name = ConvertKeyword(name);
if (kind != KeywordKind.None)
KeywordKinds[name] = kind;
KeywordsForIntellisenseList.Add(name);
KeywordsForIntellisenseSet.Add(name);
// token null может передаваться, если это ключевое слово исключительно для Intellisense (например, break)
if (token != null)
KeywordsToTokens[name] = (int)(object)token;
if (isTypeKeyword)
TypeKeywords.Add(name);
}
}
}