![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TParser - как побороть? [D6, D7, WinXP]
Roobee © (2005-01-03 13:34:00)Мастера, подскажите как побороть TParser чтобы он распознавал токен '-'
код ниже.
строку '5 - 6' не обрабатывает, а '-6 + 5' запросто.
как справиться с этим?
-----
unit ExpParse;
interface
uses Classes, Math;
{ Набор парсируемых элементов определяется как подмножество
выражений Delphi Object Pascal, подобно этому:
Expr ::= Term + Expr | Term - Expr | Term
Term ::= Factor * Term | Factor / Term | Factor
Factor ::= + Item | - Item | Item
Item ::= ( Expr ) | Fn( Expr ) | Number
Fn ::= Sin | Cos | другое...
Number ::= floating point literal number (плавающая точка литерала числа)
}
type
TExpressionParser = class(TParser)
protected
function SkipToken(Value: char): boolean;
function EvalItem: double; virtual;
function EvalFactor: double; virtual;
function EvalTerm: double; virtual;
public
function EvalExpr: double;
end;
implementation
uses SysUtils, EvalForm;
function TExpressionParser.SkipToken(Value: char): boolean;
begin
{ возвращаем истину, если текущий признак Value,
и если так, то получаем следующий признак }
Result := Token = Value;
if Result then
NextToken;
end;
function TExpressionParser.EvalItem: double;
var
Expr: double;
Fn: integer;
begin
case Token of
toInteger: Result := TokenInt;
toFloat: Result := TokenFloat;
'(':
begin
NextToken;
Result := EvalExpr;
CheckToken(')');
end;
toSymbol:
begin
if CompareText(TokenString, 'SIN') = 0 then
Fn := 1
else if CompareText(TokenString, 'COS') = 0 then
Fn := 2
else if CompareText(TokenString, 'TRUNC') = 0 then
Fn := 3
else
raise EParserError.CreateFmt('Неизвестный элемент "%s"', [TokenString]
);
NextToken;
CheckToken('(');
NextToken;
Expr := EvalExpr;
CheckToken(')');
case Fn of
1: begin
Result := SIN(Expr);
end;
2: begin
Result := COS(Expr);
end;
3: begin
Result := TRUNC(Expr);
end;
end;
end;
else
raise EParserError.CreateFmt('Неожидаемый символ "%s"', [Token]);
end;
NextToken;
end;
function TExpressionParser.EvalFactor: double;
begin
case Token of
'+':
begin
NextToken;
Result := EvalItem;
end;
'-':
begin
NextToken;
Result := -EvalItem;
end;
else
Result := EvalItem;
end;
end;
function TExpressionParser.EvalTerm: double;
var
AToken: char;
n, m : double;
begin
Result := EvalFactor;
n := Result;
if SkipToken('*') then
begin
m := EvalTerm;
Result := Result * m;
end
else
if SkipToken('/') then
begin
m := EvalTerm;
Result := Result / m;
end;
end;
function TExpressionParser.EvalExpr: double;
var
n, m : double;
begin
Result := EvalTerm;
n := Result;
if SkipToken('+') then
begin
m := EvalExpr;
Result := Result + m;
end;
if SkipToken('-') then
begin
m := EvalExpr;
Result := Result - m;
end;
if SkipToken('^') then
begin
m := EvalExpr;
Result := Power(Result, m);
end;
end;
end.
-----
procedure TForm1.Button1Click(Sender: TObject);
var
s : string;
MemStream: TMemoryStream;
ExpressionParser: TExpressionParser;
begin
{ get the string to evaluate }
s := Edit1.Text;
{ создаем поток для работы с памятью, содержащий текст -
TParser может разбирать выражения из потока}
MemStream := TMemoryStream.Create;
try
MemStream.SetSize(Length(s));
MemStream.WriteBuffer(s[1], Length(s));
MemStream.Position := 0;
{ создаем анализатор выражения, используя поток }
ExpressionParser := TExpressionParser.Create(MemStream);
try
Label2.Caption := Format('Результат=%g', [ExpressionParser.EvalExpr]);
finally
ExpressionParser.Free;
end;
finally
MemStream.Free;
end;
end;
Sandman25 (2005-01-04 08:56:00) [1]a строку '5 - 9.1 6' не понимает.
орет что - не является нормальным целым числом
И правильно делает.
Roobee (2005-01-03 21:41:00) [2]Вот код полностью мой. ни у кого не своровал.
и тем не менее, проблема осталась.
-----
unit EvalForm;
{
Ограничения:
все данные в анализируемой строке должны быть
разделены пробелами
Имеем:
строку '5 sin 9.1 6' понимает (с учетом DecimalSeparator)
строку '5 + 9.1 6' понимает
строку '5 -9.1 6' понимает
a строку '5 - 9.1 6' не понимает.
орет что - не является нормальным целым числом
Вопрос - как побороть?
}
interface
uses
Windows, Messages, SysUtils, Variants, Graphics, Controls, Forms,
Dialogs, StdCtrls, Classes;
type
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
Button1: TButton;
lb1: TListBox;
lb2: TListBox;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
s : string;
MemStream: TMemoryStream;
begin
lb1.Clear; lb2.Clear;
s := Edit1.Text;
MemStream := TMemoryStream.Create;
try
MemStream.SetSize(Length(s));
MemStream.WriteBuffer(s[1], Length(s));
MemStream.Position := 0;
with TParser.Create(MemStream) do
try
while Token <> toEOF do
begin
lb2.Items.Add(IntToStr(Ord(Token)));
if Token = toSymbol then
lb1.Items.Add(TokenString);
if Token = toInteger then
lb1.Items.Add(IntToStr(TokenInt));
if Token = toFloat then
lb1.Items.Add(FloatToStr(TokenFloat));
if Token = toString then
lb1.Items.Add(TokenString);
if Token = toWString then
lb1.Items.Add(TokenWideString);
if (Ord(Token) > 4) then
lb1.Items.Add(Token);
NextToken;
end;
finally
Free;
end;
finally
MemStream.Free;
end;
end;
end.
Anatoly Podgoretsky (2005-01-03 16:23:00) [3]А так ты ленивый или хуже, но тогда ты зря сюда пришел.
Это уже заказ работы.
roobee (2005-01-03 16:12:00) [4]>> такой объем кода...
это объем?!
roobee (2005-01-03 16:11:00) [5]отлично сэр.
но, думаю что после того как я найду место возникновения ошибки, я обнаружу и причину.
В любом сучае Вы получите код с четко указанной строкой вызывающей ошибку.
С Уважением.
roobee
Anatoly Podgoretsky (2005-01-03 16:05:00) [6]В том, что данный код не из Дельфи.
И ты ожидаешь, что кто то будет такой объем кода анализировать и тем более смотреть трассировщиком? Про трассируй сам и укажи неработающую часть.
roobee (2005-01-03 16:02:00) [7]Анатолию Подгорецкому:
с уважением... в чем обман, уважаемый..
я искал парсер.. нашел.. но он не работает как следует. пытался понять, как работает. Зашел в тупик, спрашиваю у Мастеров. В ЧЕМ ОБМАН?
roobee (2005-01-03 15:59:00) [8]да, сэр...
анализатор взят из дельфи-ворлд 6, но судя по справке,он почти не отличается от предложенного...
но все это не суть важно,
главное то, что парсер в стандартной поставке не желает понимать токен '-' любой другой вместо него понимает а минус не хочет.
вот в чем проблема.
если обладаете знаниями - помогите. очень нужно.
Anatoly Podgoretsky (2005-01-03 15:58:00) [9]Roobee © (03.01.05 15:51) [3]
Нехорошо обманывать.
Sandman25 (2005-01-03 15:52:00) [10]это стандартный парсер из поставки борланд...
С комментариями на русском языке? :)
Roobee (2005-01-03 15:51:00) [11]сорри, это не чужой компонент...
это стандартный парсер из поставки борланд...
Sandman25 (2005-01-03 15:22:00) [12]Я думаю, никто не желает разбираться в логике чужого компонента. Отлаживать чужой код не очень интересно, мягко говоря.
Roobee (2005-01-03 15:16:00) [13]уважаемые мастера, все еще надеюсь на ответ. (ГОРИТ проект)
плз. выскажитесь!!!