Создание синтаксического анализатора простого языка программирования — различия между версиями
Материал из Вики ИТ мехмата ЮФУ
Admin (обсуждение | вклад) (→Модуль синтаксического анализатора (парсера)) |
Admin (обсуждение | вклад) (→Модуль синтаксического анализатора (парсера)) |
||
Строка 7: | Строка 7: | ||
progr -> stlist | progr -> stlist | ||
stlist -> st ; stlist | st | stlist -> st ; stlist | st | ||
− | st -> assign | | + | st -> assign | block | cycl |
assign -> id signa expr | assign -> id signa expr | ||
signa -> := | += | -= | *= | signa -> := | += | -= | *= | ||
expr -> id | num | expr -> id | num | ||
− | + | block -> begin stlist end | |
cycl -> cycle expr st | cycl -> cycle expr st | ||
} | } | ||
− | unit | + | unit SimpleLangParserFun; |
interface | interface | ||
+ | uses ProgramTree; | ||
+ | |||
+ | procedure Progr; | ||
procedure Expr; | procedure Expr; | ||
procedure Assign; | procedure Assign; | ||
− | procedure | + | procedure StatementList; |
− | procedure | + | procedure Statement; |
− | procedure | + | procedure Block; |
procedure Cycle; | procedure Cycle; | ||
− | |||
procedure error(message: string := ''); | procedure error(message: string := ''); | ||
Строка 32: | Строка 34: | ||
System.Collections.Generic, | System.Collections.Generic, | ||
System.IO, | System.IO, | ||
− | + | SimpleLangLexer; | |
procedure Progr; | procedure Progr; | ||
begin | begin | ||
− | + | StatementList | |
end; | end; | ||
− | procedure | + | procedure Statement; |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
begin | begin | ||
case Lex of | case Lex of | ||
− | lexBegin: | + | lexBegin: Block; |
lexCycle: Cycle; | lexCycle: Cycle; | ||
lexId: Assign; | lexId: Assign; | ||
Строка 59: | Строка 51: | ||
end; | end; | ||
− | procedure | + | procedure Block; |
begin | begin | ||
NextLexem; | NextLexem; | ||
− | + | StatementList; | |
if Lex=lexEnd then | if Lex=lexEnd then | ||
NextLexem | NextLexem | ||
Строка 72: | Строка 64: | ||
NextLexem; | NextLexem; | ||
Expr; | Expr; | ||
− | + | Statement; | |
end; | end; | ||
Строка 78: | Строка 70: | ||
begin | begin | ||
NextLexem; | NextLexem; | ||
− | if Lex in [lexAssign | + | if Lex in [lexAssign..lexAssignMult] then |
NextLexem | NextLexem | ||
else error('Ожидалось :='); | else error('Ожидалось :='); | ||
Expr; | Expr; | ||
+ | end; | ||
+ | |||
+ | procedure StatementList; | ||
+ | begin | ||
+ | Statement; | ||
+ | while Lex=lexSemicolon do | ||
+ | begin | ||
+ | NextLexem; | ||
+ | Statement; | ||
+ | end | ||
end; | end; | ||
Строка 103: | Строка 105: | ||
end; | end; | ||
− | end. | + | end.</source> |
− | </source> | ||
Основная программа: | Основная программа: |
Версия 08:18, 29 марта 2012
Модуль синтаксического анализатора (парсера)
// Распознавание программы на простом языке. Распознаватель грамматики (парсер)
{ Грамматика:
progr -> stlist
stlist -> st ; stlist | st
st -> assign | block | cycl
assign -> id signa expr
signa -> := | += | -= | *=
expr -> id | num
block -> begin stlist end
cycl -> cycle expr st
}
unit SimpleLangParserFun;
interface
uses ProgramTree;
procedure Progr;
procedure Expr;
procedure Assign;
procedure StatementList;
procedure Statement;
procedure Block;
procedure Cycle;
procedure error(message: string := '');
implementation
uses
System.Collections.Generic,
System.IO,
SimpleLangLexer;
procedure Progr;
begin
StatementList
end;
procedure Statement;
begin
case Lex of
lexBegin: Block;
lexCycle: Cycle;
lexId: Assign;
else error('Ожидался оператор');
end;
end;
procedure Block;
begin
NextLexem;
StatementList;
if Lex=lexEnd then
NextLexem
else error('Ожидалось end');
end;
procedure Cycle;
begin
NextLexem;
Expr;
Statement;
end;
procedure Assign;
begin
NextLexem;
if Lex in [lexAssign..lexAssignMult] then
NextLexem
else error('Ожидалось :=');
Expr;
end;
procedure StatementList;
begin
Statement;
while Lex=lexSemicolon do
begin
NextLexem;
Statement;
end
end;
procedure Expr;
begin
if lex in [lexId,lexNum] then
NextLexem
else error('Ожидалось выражение');
end;
procedure error(message: string);
begin
var ss := System.IO.File.ReadLines(fname).Skip(LexRow-1).First(); // Строка row файла
writeln('Синтаксическая ошибка в строке ',LexRow,':');
writeln(ss);
writeln('^':LexCol-1);
if message<>'' then
writeln(message);
Done;
halt;
end;
end.
Основная программа:
uses SimpleLangLexer1,SimpleLangParser1;
begin
Init('progr.txt');
Progr;
if Lex=lexEot then
writeln('программа распознана правильно ')
else error('ожидался конец файла');
end.
Задания
- Добавить цикл for
- Добавить простые логические выражения вида x<0 (в лексический анализатор придется добавлять знаки отношений, а в expr - ветку id_or_num relop id_or_num)
- Добавить грамматику выражений
E ::= T A A ::= ε | + T A | - T A T ::= M B B ::= ε | * M B | / M B M ::= id | num | (E)
Грамматика составлена так, что по ней можно составить ручной анализатор методом рекурсивного спуска.
Модуль узлов синтаксического дерева
unit ProgramTree;
uses
System.Collections.Generic,
SimpleLangLexer;
type
Node = class // базовый класс для всех узлов
end;
ExprNode = class(Node) // базовый класс для всех выражений
end;
IdNode = class(ExprNode)
name: string;
constructor (name: string);
begin
Self.name := name;
end;
end;
NumNode = class(ExprNode)
num: integer;
constructor (num: integer);
begin
Self.num := num;
end;
end;
StatementNode = class(Node) // базовый класс для всех операторов
end;
AssignOpType = lexAssign..lexAssignMult;
AssignNode = class(StatementNode)
id: IdNode;
expr: ExprNode;
assop: AssignOpType;
constructor (id: IdNode; expr: ExprNode; assop: AssignOpType);
begin
Self.id := id;
Self.expr := expr;
Self.assop := assop;
end;
end;
CycleNode = class(StatementNode)
ex: ExprNode;
st: StatementNode;
constructor (ex: ExprNode; st: StatementNode);
begin
Self.ex := ex;
Self.st := st;
end;
end;
StatementList = class
stlist: List<StatementNode>;
constructor ();
begin
stlist := new List<StatementNode>();
end;
constructor (st: StatementNode);
begin
stlist := new List<StatementNode>();
stlist.Add(st);
end;
end;
BlockNode = class(StatementNode)
sl: StatementList;
constructor (sl: StatementList);
begin
Self.sl := sl;
end;
end;
ProgrNode = class(Node)
body: BlockNode;
constructor (body: BlockNode);
begin
Self.body := body;
end;
end;
var root: ProgrNode;
end.
5. Добавить семантические действия, строящие дерево программы с корнем root: ProgrNode