Показать сообщение отдельно
Старый 25.06.2009, 17:07   #178
Serg153
Нуждающийся
 
Регистрация: 03.01.2009
Сообщений: 93
Написано 8 полезных сообщений
(для 15 пользователей)
Ответ: создание MIDletPascal compiler'a

навскидку...
во первых - чтобы анализировать выражения - нужно знать Типы операндов
- далее разбиваем выражения на "лексемы" -
минимальные выражения ^+-*/ ,(+добавляем Вес к выражению
в виде табл (операнд|тип || Операнд Тип || операция+-* || вес || признак законченности разложения
(щас я не знаю конкретную реализацию асм - куда промежутоные результаты вносить, в стек или промеж переменные - генерируемые транслятором -
---
именно редактор текста(IDE) , совместно с транслятором на АСМ(Java) -
будут подготавливать текст уже для Компилятора
===
например x:=((12+(y/z-33.456)+d[a+b-c]*56) /5 = 44.5);
табличка будет формироваться в несколько интераций
1-
(это относится к компилятору - продолжу попозже...
а вот насчёт анализатора выражений...
...приведу пример из дельфи, выражение которое мы хотим парсировать:
(23.34 + 21.21) * 2.92 - 12.21 * sin (180) * -1
Вот пример синтаксического анализатора выражений, наследника TParser, который может разобрать вышеуказанное выражение. Он использует следующие определения для выражений:

      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 (плавающая точка литерала числа)
Далее идет модуль и форма, показывающие как это можно использовать. Вы должны скопировать текст формы в окно редактора Delphi и сохранить как DFM-файл. Мои расчеты вашего выражения привели к результату 130.086 - это правильно?
Примечание: TParser имеет ошибку в подпрограмме парсирования плавающего числа. Любое сочетание символов с символами '+' или '-' воспринимается как часть плавающего числа, поскольку 1e+3 корректное выражение. Естественно, это должно быть правильным только в совокупности с символом 'e'. Поэтому вы должны убедиться, что перед символами '+' и '-' имеется хотя бы один пробел, как показано в вашем выражении. Вы можете это исправить (если у вас есть исходный код VCL), редактируя функцию TParser.NextToken.

Скопируйте поочередно три приведенных ниже файла и вставьте их в окно редактора Delphi. Самый простой способ - закройте все открытые проекты и создайте новый модуль. Выделите весь текст, сгенерированный Delphi и вставьте текст модуля ExpParse. Сохраните его под именем ExpParse.pas. Затем создайте другой модуль, перенесите в него EvalForm.pas и также сохраните. Снова закройте файл и создайте новый модуль. Вставьте в него EvalForm.dfm и сохраните, выбрав меню "Save as" и отметив в списке тип файла DFM. Затем создайте новый проект, удалите форму, созданную по умолчанию и добавьте файл EvalForm.pas.

-----------------------ExpParse.pas----------------------------
    
unit ExpParse;
interface
uses Classes ;
{ Набор парсируемых элементов определяется как подмножество выражений 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 ;

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
Raise EParserError.CreateFmt( 'Неизвестный элемент "%s"', [ TokenString ]
) ;
NextToken ;
CheckToken( '(' ) ;
NextToken ;
Expr := EvalExpr ;
CheckToken( ')' ) ;
case Fn of
1 : Result := SIN( Expr ) ;
2 : Result := COS( Expr ) ;
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 ;
begin
Result := EvalFactor;
if SkipToken( '*' ) then Result := Result * EvalTerm else
if SkipToken( '/' ) then Result := Result / EvalTerm ;
end ;

function  TExpressionParser.EvalExpr : double ;
begin
Result := EvalTerm ;
if SkipToken( '+' ) then Result := Result + EvalExpr else
if SkipToken( '-' ) then Result := Result - EvalExpr ;
end ;
end.
--------------------------EvalForm.pas---------------------------

unit EvalForm;

interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExpParse;
type
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
Button1: TButton;
Label2: TLabel;
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 ;
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;
end.
-------------------------EvalForm.dfm-----------------------------
    
object Form1: TForm1
Left = 216
Top = 102
Width = 433
Height = 300
Caption = 'Form1'
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'System'
Font.Style = []
PixelsPerInch = 96
TextHeight = 16
object Label1: TLabel
Left = 8
Top = 8
Width = 74
Height = 16
Caption = 'Выражение'
end
object Label2: TLabel
Left = 120
Top = 72
Width = 297
Height = 16
AutoSize = False
Caption = 'Результат='
end
object Edit1: TEdit
Left = 8
Top = 27
Width = 409
Height = 24
TabOrder = 0
Text = '(23.34 + 21.21) * 2.92 - 12.21 * sin (180) * -1'
end
object Button1: TButton
Left = 8
Top = 64
Width = 89
Height = 33
Caption = 'Оценка'
Default = True
TabOrder = 1
OnClick = Button1Click
end
end
(Offline)
 
Ответить с цитированием