Создание синтаксического анализатора с помощью программы GPPG — различия между версиями
Материал из Вики ИТ мехмата ЮФУ
Admin (обсуждение | вклад) (→Комментарии к файлу SimpleYacc.y) |
Admin (обсуждение | вклад) (→Комментарии к файлу SimpleYacc.y) |
||
Строка 145: | Строка 145: | ||
===Комментарии к файлу SimpleYacc.y=== | ===Комментарии к файлу SimpleYacc.y=== | ||
* | * | ||
+ | ===Основная программа=== | ||
+ | <source lang="Csharp">using System; | ||
+ | using System.IO; | ||
+ | using System.Collections.Generic; | ||
+ | using SimpleScanner; | ||
+ | using SimpleParser; | ||
+ | |||
+ | namespace SimpleCompiler | ||
+ | { | ||
+ | public class SimpleCompilerMain | ||
+ | { | ||
+ | public static void Main() | ||
+ | { | ||
+ | string FileName = @"..\..\a.txt"; | ||
+ | try | ||
+ | { | ||
+ | string Text = File.ReadAllText(FileName); | ||
+ | |||
+ | Scanner scanner = new Scanner(); | ||
+ | scanner.SetSource(Text, 0); | ||
+ | |||
+ | Parser parser = new Parser(scanner); | ||
+ | |||
+ | var b = parser.Parse(); | ||
+ | if (!b) | ||
+ | Console.WriteLine("Ошибка"); | ||
+ | else Console.WriteLine("Программа распознана"); | ||
+ | } | ||
+ | catch (FileNotFoundException) | ||
+ | { | ||
+ | Console.WriteLine("Файл {0} не найден", FileName); | ||
+ | } | ||
+ | catch (LexException e) | ||
+ | { | ||
+ | Console.WriteLine("Лексическая ошибка. " + e.Message); | ||
+ | } | ||
+ | catch (SyntaxException e) | ||
+ | { | ||
+ | Console.WriteLine("Синтаксическая ошибка. " + e.Message); | ||
+ | } | ||
+ | |||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | ===Комментарии к основной программе=== | ||
+ | * | ||
+ | ===Основные задания=== |
Версия 10:56, 17 августа 2014
Содержание
Общие комментарии
- В данном проекте мы создадим front-end компилятор с помощью генератора парсеров gppg.
- Комплект для практического занятия скачиваем отсюда.
- Для автоматического создания парсера создаются файлы SimpleLex.lex (описание лексического анализатора) и SimpleYacc.y (описание синтаксического анализатора).
- Код лексического и синтаксического анализаторов создаются на C# запуском командного файла generateParserScanner.bat со следующим содержимым:
gplex.exe /unicode SimpleLex.lex gppg.exe /no-lines /gplex SimpleYacc.y
Параметр /gplex здесь означает, что gppg работает в связке с gplex.
Файл лексического анализатора SimpleLex.lex
%using SimpleParser;
%using QUT.Gppg;
%using System.Linq;
%namespace SimpleScanner
Alpha [a-zA-Z_]
Digit [0-9]
AlphaDigit {Alpha}|{Digit}
INTNUM {Digit}+
REALNUM {INTNUM}\.{INTNUM}
ID {Alpha}{AlphaDigit}*
%%
{INTNUM} {
return (int)Tokens.INUM;
}
{REALNUM} {
return (int)Tokens.RNUM;
}
{ID} {
int res = ScannerHelper.GetIDToken(yytext);
return res;
}
":=" { return (int)Tokens.ASSIGN; }
";" { return (int)Tokens.SEMICOLON; }
[^ \r\n] {
LexError();
return (int)Tokens.EOF; // конец разбора
}
%{
yylloc = new LexLocation(tokLin, tokCol, tokELin, tokECol); // позиция символа (терминального или нетерминального), возвращаемая @1 @2 и т.д.
%}
%%
public override void yyerror(string format, params object[] args) // обработка синтаксических ошибок
{
var ww = args.Skip(1).Cast<string>().ToArray();
string errorMsg = string.Format("({0},{1}): Встречено {2}, а ожидалось {3}", yyline, yycol, args[0], string.Join(" или ", ww));
throw new SyntaxException(errorMsg);
}
public void LexError()
{
string errorMsg = string.Format("({0},{1}): Неизвестный символ {2}", yyline, yycol, yytext);
throw new LexException(errorMsg);
}
class ScannerHelper
{
private static Dictionary<string,int> keywords;
static ScannerHelper()
{
keywords = new Dictionary<string,int>();
keywords.Add("begin",(int)Tokens.BEGIN);
keywords.Add("end",(int)Tokens.END);
keywords.Add("cycle",(int)Tokens.CYCLE);
}
public static int GetIDToken(string s)
{
if (keywords.ContainsKey(s.ToLower())) // язык нечувствителен к регистру
return keywords[s];
else
return (int)Tokens.ID;
}
}
Комментарии к файлу SimpleLex.lex
Файл синтаксического анализатора SimpleYacc.y
%{
// Эти объявления добавляются в класс GPPGParser, представляющий собой парсер, генерируемый системой gppg
public Parser(AbstractScanner<int, LexLocation> scanner) : base(scanner) { }
%}
%output = SimpleYacc.cs
%namespace SimpleParser
%token BEGIN END CYCLE INUM RNUM ID ASSIGN SEMICOLON
%%
progr : block
;
stlist : statement
| stlist SEMICOLON statement
;
statement: assign
| block
| cycle
;
ident : ID
;
assign : ident ASSIGN expr
;
expr : ident
| INUM
;
block : BEGIN stlist END
;
cycle : CYCLE expr statement
;
%%
Формат .y-файла
Определения %% Правила %% Пользовательский код
Комментарии к файлу SimpleYacc.y
Основная программа
using System;
using System.IO;
using System.Collections.Generic;
using SimpleScanner;
using SimpleParser;
namespace SimpleCompiler
{
public class SimpleCompilerMain
{
public static void Main()
{
string FileName = @"..\..\a.txt";
try
{
string Text = File.ReadAllText(FileName);
Scanner scanner = new Scanner();
scanner.SetSource(Text, 0);
Parser parser = new Parser(scanner);
var b = parser.Parse();
if (!b)
Console.WriteLine("Ошибка");
else Console.WriteLine("Программа распознана");
}
catch (FileNotFoundException)
{
Console.WriteLine("Файл {0} не найден", FileName);
}
catch (LexException e)
{
Console.WriteLine("Лексическая ошибка. " + e.Message);
}
catch (SyntaxException e)
{
Console.WriteLine("Синтаксическая ошибка. " + e.Message);
}
Console.ReadLine();
}
}
}