Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Парсер на классах

Автор: Triplet 28.10.2008 1:24

Всем добрый день!
Получила такое сумбурное задание, помогите, пожалуйста, разобраться.
Необходимо реализовать парсер арифметического выражения на классах.
Проблема как раз в этих классах, т.е., как я поняла, они должны быть реализованы таким образом:

type
TCustomToken=class //здесь должны храниться только литералы исходного выражения
private
FText: string;
public
property Text: string read fText; //должно быть св-ом
procedure LoadFromString(const S, Pos): Integer;
end;
TNumberToken=class //только цифры исходного выражения
private
FValue: Integer; //должно быть св-ом
public
property Value: Integer read FValue;
end;
TCustomTokens=class //всё выражение (должно считываться из двух предыдущих классов)
private
FCount: Integer; //должно быть св-ом
FItems: array [0..FCount-1] of Char; //должно быть св-ом
function GetSymbol(Index: Integer): ;
procedure SetSymbol(Index: Integer; Value: Longint);
public
property Count: Integer read FCount;
property Items[index: Integer]: Longint read GetCoord write SetCoord; //не уверена, что правильно оформила
end;


на форуме нашла такой код парсера
http://forum.pascal.net.ru/index.php?showtopic=3786&hl=cmPUSH
http://volvo71.narod.ru/faq_folder/postfix.htm
там есть и ооп, но
подскажите, пожалуйста, как можно парсер оформить в виде именно этих классов. Как я поняла, каждый класс должен выступать в виде стека, и как правильно распорядиться свойствами классов?
Заранее большое спасибоsmile.gif)!

Автор: volvo 28.10.2008 15:53

Откуда взялись эти классы? Тебе что, задано их определение (без реализации), и тебе надо с их помощью реализовать парсер? Или у тебя есть задание, и ты думаешь, что классы TCustomToken/TNumberToken/TCustomTokens должны выглядеть именно так?

Слишком уж много непонятного в этих описаниях. Начнем с определения "парсер". Что делает этот парсер? Если переводит выражение в постфикс - это одно, тогда я еще как-то могу согласиться, что в TCustomTokens организован массив (имитирующий стек), который хранит только Char-ы, большего, чем хранение скобок и знаков арифм. операций от того стека не требуется... Но вот если придется еще и вычислять, то тут без стека, хранящего числа, никак не обойтись, следовательно чего-то в TCustomTokens уже не хватает...

Второе: чего это в TCustomToken есть метод LoadFromString (насколько я понимаю, читающий знак очередного оператора из входной строки с определенной позиции), а в TNumberToken такого метода нет? Что, числа не читаются с той же строки? Тогда откуда они берутся?

Третье: зачем присутствуют 3 разных не связанных друг с другом класса? Я понимаю, если бы TCustomToken и TNumberToken были наследниками какого-то базового класса, тогда можно было бы и стек сделать один, способный хранить и числа и знаки операций. Но у тебя вообще нет наследования.

Есть исходники еще одного парсера, он не выложен на моем сайте, который вычисляет выражения, содержащие +-*/^ и тригонометрические функции (включая обратные: arcsin/arccos/arctan), для FPC, но должно отработать и в Дельфи с небольшой корректировкой, если надо - скажи... Там, правда, тоже нет иерархии классов, все одним классом реализовано...

Автор: Triplet 28.10.2008 19:46

Да, задано именно такое определение классов.
Их надо было реализовать + в классах можно прописывать свои методы, свойства, поля(т.е. с ними можно делать что угодно, как я поняла, даже организовать наследование, надо только, чтобы основная структура сохранилась).
А три класса из-за того, что нас хотят научить работать с классамиsmile.gif)

В условиях только не было прописано, что FItems: array [0..FCount-1] должен иметь тип char, это уже мои домыслы.

А так, по идее, должна быть первоначальная строка, в которую пользователь вводит выражение. Далее бежим по строке, если видим цифру, то её в TNumberToren, если знак, то в TCustomToken. Потом надо из двух классов, всё что получилось занести в третий класс. А далее посчитать выражение.

Была бы очень благодарна за ещё один парсер, тем более на классеsmile.gif)

Автор: volvo 28.10.2008 21:37

Значит, смотри: используются вот такие классы:

  Tok_Type = (_UNDEF, _NUMBER, _OPERATOR, _END);
TokenString = string[16];

tbase = class
tokType: Tok_Type;
constructor create;
end;
topertoken = class(tbase)
private
FValue: char;
public
constructor loadfromstring(const s: string; var p: integer);
constructor stop;
property Value: char read FValue write FValue;
end;
tnumbertoken = class(tbase)
private
FValue: double;
public
constructor loadfromstring(const s: string; var p: integer);
property Value: double read FValue write FValue;
end;


tcalc = object
function proceed(): double;
constructor create(lpszCommand: string);
destructor destroy(); virtual;

private
TokenValue: tbase;

procedure SetFunction(lpszCommand: string);
procedure GetToken(); virtual;
function mul_div(): double;

protected
pCurrPos: integer;
_Function: string;

function add_sub(): double;
function prim(): double; virtual;
end;
Предупреждаю сразу о нескольких вещах:
1) это работает только с арифметическими операциями/скобками/вещественными числами
2) все классы, кроме TCalc были прикручены в программу по принципу "чтобы было, потому что есть в задании", изначально в парсере использовалось только 2 класса, TCalc и TVarCalc (один для вычисления выражений без переменных, второй - для вычислений с участием переменных, второй класс в прикрепленную программу не вошел, из первого было вычищено все, что касается функций)
3) такую программу лично я никогда бы не принял. Еще раз: написано это - только для того, чтобы показать, насколько это бредово получается. Без этих "классов-довесков" программа выглядит намного стройнее и красивее;
4) на некоторых версиях Дельфи (до 2009) потребуется заменить конструкцию Exit(X) на
begin
result := X; Exit;
end;



Прикрепленные файлы
Прикрепленный файл  parser.pas ( 5.69 килобайт ) Кол-во скачиваний: 298

Автор: Triplet 28.10.2008 21:50

Спасибо огромное!!!
Сейчас буду разбираться! Хотя задание и правда, мягко скажем, специфическое, на твоём сайте столько нормальных решений, а приходится что-то выдумыватьsad.gif(
Ещё раз спасибо!
p.s. я только, если что, ещё что-нибудь спрошу?))