
- •Лексический анализатор………………………………………………………….…..11
- •Синтаксический анализатор…………………………………………….……………15
- •Генератор кода………………………………………………………………..………..18
- •Теоретическая часть.
- •Транслятор.
- •Лексический анализатор.
- •Синтаксический анализатор.
- •1.4 Генератор кода.
- •Практическая часть.
- •2.1 Синтаксис языка в бнф. Терминалы, нетерминалы, начальный символ и правила.
- •2.2 Каркас транслятора.
- •2.3 Лексический анализатор.
- •2.3 Синтаксический анализатор.
- •2.4 Генератор кода.
- •Тестирование приложения.
2.3 Лексический анализатор.
Для задания типа лексемы обычно используется перечисление, включающее в себя все возможные в исходном языке типы: ключевые слова, операторы, идентификаторы и числа.
public enum Lexems
{
None, Name, Number, Begin, End, Multiplication, Division,
Plus, Minus, Equal, NotEqual, Less, LessOrEqual, More, MoreOrEqual, Int,
Print, LeftBracket, RightBracket, Semi, Comma, EOF, Determine,
LongInt, Until, Do, EndUntil
}
Далее создаем отдельную структуру, описывающую данный тип лексемы:
/// <summary>
/// Ключевое слово
/// </summary>
internal struct KeyWord
{
public string word;
public Lexems lex;
}
public static void Initialize()
{
keywords = new KeyWord[10];
keywordPointer = 0;
currentLexem = 0;
currentName = null;
AddKeyword("Begin", Lexems.Begin);
AddKeyword("End", Lexems.End);
AddKeyword("Integer", Lexems.Int);
AddKeyword("Long Integer", Lexems.LongInt);
AddKeyword("Print", Lexems.Print);
AddKeyword("UNTIL", Lexems.Until);
AddKeyword("DO", Lexems.Do);
AddKeyword("ENDUNTIL", Lexems.EndUntil);
}
В рамках класса LexicalAnalyzer будем реализовывать методы лексического анализа: хранение ключевых слов языка и их распознавание, разбор текущей лексемы в зависимости от её типа.
/// <summary>
/// Лексический анализатор
/// </summary>
public static class LexicalAnalyzer
{
private static KeyWord[] keywords;
private static int keywordPointer;
private static string currentName;
private static Lexems currentLexem;
/// <summary>
/// Инициализировать
/// </summary>
public static void Initialize()
{
keywords = new KeyWord[10];
keywordPointer = 0;
currentLexem = 0;
currentName = null;
AddKeyword("Begin", Lexems.Begin);
AddKeyword("End", Lexems.End);
AddKeyword("Integer", Lexems.Int);
AddKeyword("Long Integer", Lexems.LongInt);
AddKeyword("Print", Lexems.Print);
AddKeyword("UNTIL", Lexems.Until);
AddKeyword("DO", Lexems.Do);
AddKeyword("ENDUNTIL", Lexems.EndUntil);
}
/// <summary>
/// Текущее имя
/// </summary>
public static string CurrentName
{
get
{
return currentName;
}
}
/// <summary>
/// Текущая лексема
/// </summary>
public static Lexems CurrentLexem
{
get
{
return currentLexem;
}
}
/// <summary>
/// Добавить ключевое слово
/// </summary>
/// <param name="keyword">слово</param>
/// <param name="lex">лексема</param>
/// <returns></returns>
public static bool AddKeyword(string keyword, Lexems lex)
{
if (keywordPointer < keywords.Length)
{
KeyWord kw = new KeyWord();
kw.word = keyword;
kw.lex = lex;
keywords[keywordPointer++] = kw;
return true;
}
return false;
}
/// <summary>
/// Получить ключевое слово
/// </summary>
/// <param name="keyword">слово</param>
/// <returns></returns>
public static Lexems GetKeyword(string keyword)
{
for (int i = keywordPointer - 1; i >= 0; i--)
{
if (keywords[i].word == keyword)
{
return keywords[i].lex;
}
}
return Lexems.Name;
}
/// <summary>
/// Разоьрать следующую лексему
/// </summary>
public static void ParseNextLexem()
{
while (char.IsWhiteSpace(Reader.CurrentChar))
Reader.ReadNextChar();
if (char.IsLetter(Reader.CurrentChar))
ParseIdentificator();
else if (char.IsDigit(Reader.CurrentChar))
ParseNumber();
else if (Reader.CurrentChar == '\n')
{
Reader.ReadNextChar();
currentLexem = Lexems.None;
}
else if (Reader.CurrentChar == '<')
{
Reader.ReadNextChar();
if (Reader.CurrentChar == '=')
{
Reader.ReadNextChar();
currentName = "<=";
currentLexem = Lexems.LessOrEqual;
}
else
{
currentName = "<";
currentLexem = Lexems.Less;
}
}
else if (Reader.CurrentChar == '>')
{
Reader.ReadNextChar();
if (Reader.CurrentChar == '=')
{
Reader.ReadNextChar();
currentName = ">=";
currentLexem = Lexems.MoreOrEqual;
}
else
{
currentName = ">";
currentLexem = Lexems.More;
}
}
else if (Reader.CurrentChar == '=')
{
Reader.ReadNextChar();
if (Reader.CurrentChar == '=')
{
Reader.ReadNextChar();
currentName = "==";
currentLexem = Lexems.Equal;
}
else
{
currentName = "=";
currentLexem = Lexems.Determine;
}
}
else if (Reader.CurrentChar == '!')
{
Reader.ReadNextChar();
if (Reader.CurrentChar == '=')
{
Reader.ReadNextChar();
currentName = "!=";
currentLexem = Lexems.NotEqual;
}
else
Errors.Error("Неизвестный символ");
}
else if (Reader.CurrentChar == '+')
{
Reader.ReadNextChar();
currentName = "+";
currentLexem = Lexems.Plus;
}
else if (Reader.CurrentChar == '*')
{
Reader.ReadNextChar();
currentName = "*";
currentLexem = Lexems.Multiplication;
}
else if (Reader.CurrentChar == '/')
{
Reader.ReadNextChar();
currentName = "/";
currentLexem = Lexems.Division;
}
else if (Reader.CurrentChar == ',')
{
Reader.ReadNextChar();
currentName = ",";
currentLexem = Lexems.Comma;
}
else if (Reader.CurrentChar == ';')
{
Reader.ReadNextChar();
currentName = ";";
currentLexem = Lexems.Semi;
}
else if (Reader.CurrentChar == '(')
{
Reader.ReadNextChar();
currentName = "(";
currentLexem = Lexems.LeftBracket;
}
else if (Reader.CurrentChar == ')')
{
Reader.ReadNextChar();
currentName = ")";
currentLexem = Lexems.RightBracket;
}
else if (Reader.CurrentChar == char.MinValue)
{
currentName = "EOF";
currentLexem = Lexems.EOF;
}
else
Errors.Error("Недопустимый символ!");
}
/// <summary>
/// Разобрать идентификатор
/// </summary>
private static void ParseIdentificator()
{
string identificator = string.Empty;
int count = 0;
do
{
identificator += Reader.CurrentChar;
if (identificator == "Long")
{
Reader.ReadNextChar();
identificator += Reader.CurrentChar;
count++;
}
Reader.ReadNextChar();
if (++count > 20)
Errors.Error("Chars overflow");
}
while (char.IsLetter(Reader.CurrentChar));
currentName = identificator;
currentLexem = GetKeyword(identificator);
}
/// <summary>
/// Разобрать число
/// </summary>
private static void ParseNumber()
{
string number = string.Empty;
do
{
number += Reader.CurrentChar;
Reader.ReadNextChar();
}
while (char.IsDigit(Reader.CurrentChar));
try
{
Int32.Parse(number);
}
catch (OverflowException)
{
Errors.Error("Не является числом");
}
currentName = number;
currentLexem = Lexems.Number;
}
}