Интерпретатор для подмножества языка разметки гипертекста HTML

Тип работы:
Контрольная
Предмет:
Программирование


Узнать стоимость

Детальная информация о работе

Выдержка из работы

Контрольная работа

Интерпретатор для подмножества языка разметки гипертекста HTML

Содержание

Введение

1. Лексический анализ

2. Синтаксический анализ

3. Визуальное представление

Заключение

Литература

Приложение, А — Листинг программы

Введение

Целью данной работы является написание интерпретатора языка разметки HTML. Данная программа должна проверять входную последовательность на корректность кода. В случае успешного просмотра кода выводится сообщение о корректности и строится абстрактное синтаксическое дерево. В ином случае выводится сообщение об ошибке.

В данной программе входная последовательность — это лексемы, совокупность которых представляют собой язык гипертекстовой разметки HTML.

Теги — это элементы языка разметки гипертекста, в основном для задания того, как будет отображаться текст.

Теги, разбираемые написанной программой:

1. < html></html> - Указывает программе просмотра страниц, что это HTML документ, а также указывает на начало веб-кода.

2. < head></head> - определяет место, где помещается различная информация, не отображаемая в теле документа. Здесь располагается тег названия документа и теги для поисковых машин.

3. < title></title> - помещает название документа в оглавление программы просмотра страниц.

4. < body></body> - определяет видимую часть документа.

5. < table></table> - создает таблицу.

6. < tr></tr> - определяет строку в таблице.

7. < td></td> - определяет отдельную ячейку в таблице.

В программе необходимо использовать как лексический, так и синтаксический анализ.

Для лексического анализа используется Lex — программа для генерации лексических анализаторов.

Для синтаксического анализа должен быть использован метод рекурсивного спуска. Метод рекурсивного спуска или нисходящий разбор -- это один из методов определения принадлежности входной строки к некоторому формальному языку

Актуальность данной работы связана с бурным развитием языков программирования, а в частности языков веб-программирования, к которым в свою очередь относится HTML. Также в данной работе мы познакомимся с лексическим и синтаксическим анализом, улучшим знания азов системного программирования.

1. Лексический анализ

Для описания гипертекстовой разметки языка HTML используются теги. HTML документ начинается с открывающего тега < html> и заканчивается закрывающим — < /html>. Документ должен содержать тело < body>, а голова может отсутствовать < head>.

Голова, как правило, должна содержать тег заголовка — < title></title>. В поле между открывающимся и закрывающимся тегами описывается заголовок.

Тело обязательно должно присутствовать, хотя и может быть пустым. В теле документа описывается вся структура документа, в нашем случае это теги таблицы < table> и всё, что входят в формирование таблицы.

Тег < tr> создает новый ряд (строку) ячеек таблицы. Ячейки в ряду создаются с помощью тега < td>.

В открывающемся теге таблицы или любого тега входящего в формирование таблицы, можно указать атрибуты:

1. align — определяет способ горизонтального выравнивания содержимого всех ячеек данного ряда.

2. valign — определяет способ вертикального выравнивания содержимого всех ячеек данного ряда.

3. bgcolor — определяет цвет фона для всех ячеек данного ряда.

Возможности гипертекстового языка разметки намного шире и больше, но для поставленной цели, этого достаточно.

В начале необходимо описать все вышеперечисленные теги как лексемы в файле с расширением htmllex. l для генератора Lex.

Текст файла:

unit htmllex;

interface

const

html_st=257;

html_en=258;

t_st = 259;

t_en = 260;

h_st=261;

h_en=262;

b_st=263;

b_en=264;

b_tabl_st=265;

b_tabl_en=271;

id=300;

str_ru=301;

param=302;

b_tabl_tr_st=303;

b_tabl_tr_en=304;

b_tabl_td_st=305;

b_tabl_td_en=306;

lex_error=313;

function yylex: integer;

implementation

uses lexlib;

D [0−9]

L [a-zA-Z]

P [а-яА-Я]

%%

«< html>» returni (html_st);

«< /html>» returni (html_en);

«< title>» returni (t_st);

«< /title>» returni (t_en);

«< head>» returni (h_st);

«< /head>» returni (h_en);

«< body>» returni (b_st);

«< /body>» returni (b_en);

«< table» returni (b_tabl_st);

«< /table>» returni (b_tabl_en);

«< tr» returni (b_tabl_tr_st);

«< /tr>» returni (b_tabl_tr_en);

«< td» returni (b_tabl_td_st);

«< /td>» returni (b_tabl_td_en);

{L}({L}|{D})* returni (id);

«'"({L}|{D})+"'» returni (param);

({L}|{D}|{P})* returni (str_ru);

> returnc ('> ');

= returnc ('=');

" «;

. returni (lex_error);

%%

end.

Все параметры описываются в кавычках. В разделе определений формируем строки, необходимые для компиляции полноценного модуля лексического анализатора.

Для этого указываем заголовок модуля и декларируем функцию yylex в интерфейсном разделе, так как данная функция будет использоваться в других модулях.

В разделе правил, если входная последовательность соответствует одному из них, то управление передается основной программе. Раздел правил и пользовательский раздел отделяются строкой процента. Пользовательский раздел программы используем для корректного завершения модуля лексического анализатора. В нашем случае этот раздел состоит из одной строки «end. «, которая должна быть помещена в результат для корректного завершения модуля.

2. Синтаксический анализ

В качестве метода синтаксического анализа задан «метод рекурсивного спуска». Необходимо построить грамматику, описывающую заданные параметры. Текст грамматики приведен ниже:

GOAL> HTML

HTML> <html>HEAD BODY< /html>

HEAD> <head>TITLE</head>

TITLE> <title> HEADLINE < /title>

HEADLINE > str_ru

BODY> <body> CONTENT < /body>

CONTENT > TABLE0 CONTENT

|str_ru CONTENT

|id CONTENT

TABLE0 > < table ATTRIB> TR0 < /table>

TR0 > < tr ATTRIB> TD0 < /tr> TR0

| TR0 > TR0

| е

TD0 > < td ATTRIB> str_ru < /td> TD0

ATTRIB > id=param ATTRIB

3. Визуальное представление

Для визуального представления входной последовательности используем дерево.

Чтобы визуально отобразить дерево использовали стандартный компонент Embarcadero RAD Studio 2010 — TreeView. Так же происходит автоматическое экспортирование дерева из визуального компонента в xml файл и обычный текстовый файл, которые можно найти в директории с программой. Для построения абстрактного синтаксического дерева по ходу работы нам удалось изучить данный компонент.

К узлам дерева крепятся листья, если же листа нет, то узел сам становится листом (например, после тега < body> идет тег < table>, если же таблицы не будет, то узел < body>, станет листом дерева)

Что бы распознать родителя узла завели счетчик, который указывает на родителя того или иного узла.

Внешний вид созданного интерпретатора соответствует изображению на рисунке 1.

Рисунок 1 — Внешний вид

На форме расположены следующие объекты:

1. Кнопка «ОК», которая запускает основную процедуру программы;

2. Кнопка «Отмена», которая завершает работу программы;

3. Кнопка «Очистить», которая очищает исходные данные;

4. Memo1- область, в которой должен быть вписан исходный HTML код;

5. TreeView — область, в которой строится абстрактное дерево.

После завершения процесса анализа кода, программа примет вид соответствующий рисунку 2.

Рисунок 2 — Завершение процесса анализа

Заключение

В ходе данной работы была написана программа, которая анализирует HTML код на правильность, в случае успешного анализа строится абстрактное синтаксическое дерево, в противном случае выводится ошибка. Программа функционирует в соответствии с поставленной задачи.

При написании мы разобрались с алгоритмом рекурсивного спуска, получили навыки построения грамматики и работы с лексическим анализатором Lex. Приобрели практические навыки в области построения трансляторов.

алгоритм грамматика интерпретатор разметка код

Приложение А

Листинг программы

unit Interpreate;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, Lexlib, HTMLLEX, ComCtrls, StdCtrls, ExtCtrls;

type

TPInt = ^integer;

TForm2 = class (TForm)

Button1: TButton;

Memo4: TMemo;

GroupBox1: TGroupBox;

Memo1: TMemo;

GroupBox2: TGroupBox;

TreeView1: TTreeView;

Memo2: TMemo;

Button2: TButton;

Button3: TButton;

StatusBar1: TStatusBar;

Memo3: TMemo;

procedure FormShow (Sender: TObject);

procedure Button1Click (Sender: TObject);

procedure FormCreate (Sender: TObject);

function fglav: boolean;

function fhtml_st: boolean; //начало

function fh_st: boolean; //head start — end

function ft_st: boolean; //title

function ft_en: boolean;

function fh_en: boolean;

function fb_st: boolean; //body

function fb_tabl_st: boolean; //body — table

function fparam: boolean;

function fb_tabl_tr_st: boolean;

function fb_tabl_td_st: boolean;

function fb_tabl_td_en: boolean;

procedure push (i: integer);

procedure pop (var i: integer);

function fb_tabl_tr_en: boolean;

function fb_tabl_en: boolean;

function fb_en: boolean;

function fhtml_en: boolean;

procedure Button2Click (Sender: TObject); //конец

private

stack: TList;

{ Private declarations }

public

{ Public declarations }

end;

var

Form2: TForm2;

token: integer;

tree_i,

tree_t, // используем в title и table

tree_tr,

tree_td,

tree_p: integer;

backup: array [1. 4] of integer;

implementation

{$R *. dfm}

function TForm2. fhtml_en: boolean;

begin

if token = html_en then

begin

token := yylex;

result := true;

end

else

result := false;

end;

procedure TForm2. Button2Click (Sender: TObject);

begin

Memo1. Clear;

end;

function TForm2. fb_en: boolean;

begin

if (token = b_en) then

begin

result := true;

token := yylex;

end

else

if (token = str_ru) or (token = id) then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_t], yytext);

inc (tree_i);

token := yylex;

result := fb_en;

end

else

result := false;

end;

function TForm2. fb_tabl_en: boolean;

begin

if token = b_tabl_en then

begin

result := true;

token := yylex;

end

else

result := false;

end;

function TForm2. fb_tabl_tr_en:boolean;

begin

if (token = b_tabl_tr_en) then

begin

result := true;

token := yylex;

end

else

if token = str_ru then

begin

token := yylex;

result := fb_tabl_tr_en;

end

else

result := false;

end;

procedure TForm2. pop (var i: integer);

var

zn: TPInt;

begin

zn := stack. Items[stack. count-1];

i := zn^;

stack. Delete (stack. count-1);

end;

procedure TForm2. push (i: integer);

var

zn: TPInt;

begin

new (zn);

zn^ := i;

stack. Add (zn);

end;

function TForm2. fb_tabl_td_en:boolean;

begin

result := true;

if token = b_tabl_st then

begin

push (tree_t);

push (tree_tr);

push (tree_td);

push (tree_p);

tree_t := tree_i;

result := fb_tabl_st;

pop (tree_p);

pop (tree_td);

pop (tree_tr);

pop (tree_t);

end;

if token = b_tabl_td_en then

begin

result := true;

token := yylex;

end

else

if (token = str_ru) or (token = b_tabl_st)then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_p], yytext);

inc (tree_i);

token := yylex;

result := result and fb_tabl_td_en;

end

else

result := false;

end;

function TForm2. fb_tabl_td_st:boolean;

begin

result := false;

if token = b_tabl_td_st then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_td], '< td');

inc (tree_i);

token := yylex;

tree_p := tree_i;

result := fparam;

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_td], '> </td>');

inc (tree_i);

tree_p := tree_i;

result := result and fb_tabl_td_en;

if token = b_tabl_td_st then

result := result and fb_tabl_td_st;

end

end;

function TForm2. fb_tabl_tr_st: boolean;

begin

result := false;

if token = b_tabl_tr_st then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_tr], '< tr');

inc (tree_i);

token := yylex;

tree_p := tree_i;

result := fparam;

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_tr], '> </tr>');

inc (tree_i);

tree_td := tree_i;

result := result and fb_tabl_td_st and fb_tabl_tr_en;

if token = b_tabl_tr_st then

result := result and fb_tabl_tr_st;

end

end;

function TForm2. fparam: boolean;

var

pr: string;

begin

pr := '';

if token = ord ('> ') then

begin

result := true;

token := yylex;

end

else

result := false;

if token = id then

begin

pr := yytext;

token := yylex;

if token = ord ('=') then

begin

pr := pr + yytext;

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_p], pr);

inc (tree_i);

token := yylex;

if token = param then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_i], yytext);

inc (tree_i);

token := yylex;

result := fparam;

end;

end;

end;

end;

function TForm2. fb_tabl_st: boolean;

begin

if token = b_tabl_st then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_t], '< table');

inc (tree_i);

token := yylex;

tree_p := tree_i;

result := fparam;

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_t], '> </table>');

inc (tree_i);

tree_tr := tree_i;

result := result and fb_tabl_tr_st and fb_tabl_en;

if token = b_tabl_st then

result := result and fb_tabl_st

else

if (token = str_ru) or (token = id) then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_t], yytext);

inc (tree_i);

token := yylex;

result := fb_tabl_st;

end;

end

else

if (token = str_ru) or (token = id) then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_t], yytext);

inc (tree_i);

token := yylex;

result := fb_tabl_st;

end

else

result := true;

end;

function TForm2. fb_st: boolean;

begin

if token = b_st then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[0], '< body></body>');

inc (tree_i);

tree_t := tree_i;

token := yylex;

result := fb_tabl_st and fb_en;

end

else

result := false;

end;

function TForm2. fh_en: boolean;

begin

if token = h_en then

begin

token := yylex;

result := true;

end

else

result := false;

end;

function TForm2. ft_en: boolean;

begin

if (token = t_en) then

begin

result := true;

token := yylex;

end

else

if token = str_ru then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_t], yytext);

inc (tree_i);

token := yylex;

result := ft_en;

end

else

result := false;

end;

function TForm2. ft_st: boolean;

begin

if token = t_st then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[tree_i], '< title></title>');

inc (tree_i);

tree_t := tree_i;

token := yylex;

result := ft_en;

end

else

result := false;

end;

function TForm2. fh_st: boolean;

begin

if token = h_st then

begin

TreeView1. Items. AddChild (TreeView1. Items. Item[0], '< head></head>');

inc (tree_i);

token := yylex;

result := ft_st and fh_en;

end

else

result := true;

end;

function TForm2. fhtml_st: boolean;

begin

if token = html_st then

begin

TreeView1. Items. Clear;

TreeView1. Items. Add (nil, '< html></html>');

token := yylex;

result := fh_st and fb_st and fhtml_en;

end

else result: =false;

end;

function TForm2. fglav: boolean;

begin

result := fhtml_st;

end;

procedure TForm2. Button1Click (Sender: TObject);

begin

tree_i := 0;

memo2. Clear;

yyclear;

yymemoinit (memo1,memo2,memo3,memo4);

yylineno: =0;

token: =yylex;

if fglav and (token=0) then

begin

StatusBar1. Panels[0]. Text := 'Проверка кода выполнена успешно';

StatusBar1. Panels[1]. Text := 'Дерево построено';

end

else

begin

StatusBar1. Panels[0]. Text := 'Ошибка проверки кода';

StatusBar1. Panels[1]. Text := 'Ошибка при построении дерева';

showmessage ('Ошибка!');

end;

end;

procedure TForm2. FormCreate (Sender: TObject);

begin

stack := TList. Create;

end;

procedure TForm2. FormShow (Sender: TObject);

begin

Button1. SetFocus;

end;

end.

ПоказатьСвернуть
Заполнить форму текущей работой