티스토리 뷰

728x90

출처 - http://cc.embarcadero.com/Item/26667

DCocoR 예제를 간단하게 수정하여 만들어 보았습니다.


ExprUnit.atg
----------------------------------------
COMPILER ExprUnit

FRAME "delphi.frm"

header = (.
.)

uses = (.SysUtils,Variants,StrUtils.)

private = (.
.)
protected = (.
.)
public = (.
  function Evaluate(const str: String): integer;
.)
publicProps = (.
.)

precreate = (.
.)

implementation =
(.
function TExprUnit.Evaluate(const str: String): integer;
var rez: Variant;
begin
  SetSource(str);
  _expr(rez);
  //Result := Successful and rez;
  Result := rez;
end;
.)

END

IGNORECASE

CHARACTERS
letter="ABCDEFGHIJKLMNOPQRSTUVWXYZ_".
digit="0123456789".
hexdigit = digit + "ABCDEF".
special = "+-*/=<>[].,():;^@{}$#".
ctrl=CHR(1)..CHR(31).
tab=CHR(9).
eol=CHR(13).
lf=CHR(10).
noquote=ANY-"'" -ctrl.

TOKENS
ident = letter{letter|digit}.
number = digit{digit} | digit { digit } CONTEXT ( ".." ).
string = ("'" {noquote}"'"| "#"(digit{digit}|"$"hexdigit{hexdigit}))
         {"'" {noquote}"'"| "#"(digit{digit}|"$"hexdigit{hexdigit})}.
float = digit{digit}
        (  "." {digit}
           [ "E"
            ["+" |"-"]
            digit{digit}
           ]
          |"E"["+"|"-"]digit{digit}
        ).
hexnumber = "$" hexdigit {hexdigit}.
eq    = '='.
gr    = '>'.
les   = '<'.
lesEq = '<='.
grEq  = '>='.
noeq  = '<>'.

add = "+". 
sub = "-". 
or  = "OR".
xor = "XOR".

mult = "*"  .
divd = "/"  .
div  = "DIV".
mod  = "MOD".
and  = "AND".
shl  = "SHL".
shr  = "SHR".

IGNORE tab+lf+eol

PRODUCTIONS

ExprUnit
(. var rez: Variant; .)=
 expr<rez>
.

expr<var Value: Variant>
(. var v2: Variant; sign: Integer; AddOp: Integer; .) =
  (.sign := 1;.)
  ['+' | '-' (.sign := -1;.) ]
  Term<Value> (. if sign<0 then value := -value;.)
  {
   ( "+" | "-" | "OR" | "XOR" )
   (. AddOp := Symbols[0]^.id; .)
    Term<v2>
   (. case AddOp of
      addSym: Value := Value +   v2;
      subSym: Value := Value -   v2;
      orSym : Value := Value or  v2;
      xorSym: Value := Value xor v2;
      end;
   .)
  }
.

Term<var Value: Variant>
(. var v2: Variant; MulOp: Integer; .) =
 Factor<Value>
 {
  ("*" | "/" | "DIV" | "MOD" | "AND" | "SHL" | "SHR" )
  (. MulOp := Symbols[0]^.id; .)
  Factor<v2>
   (. case MulOp of
      multSym: Value := Value *   v2;
      divdSym: Value := Value /   v2;
      divSym:  Value := Value div v2;
      modSym:  Value := Value mod v2;
      andSym:  Value := Value and v2;
      shlSym:  Value := Value shl v2;
      shrSym:  Value := Value shr v2;
      end;
   .)
 }
.

Factor<var Value: Variant> =
 | Number<Value>
.

Number<out Value: Variant> =
   number     (. Value := StrToInt(LexString); .)
 | float      (. Value := StrToFloat(LexString); .)
 | hexnumber  (. Value := StrToInt(LexString); .)
.

END ExprUnit.
----------------------------------------

ExprApp.dpr
----------------------------------------
program ExprApp;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  CocoAncestor,
  FileLoader,
  ExprUnit in 'ExprUnit.pas';

var
  comp: TExprUnit;
  meth: TMethod;
  errProc: TErrorEvent absolute meth;
  int1: String;
  rez: Variant;

procedure ErrorHandler(this: TExprUnit; Sender: TObject; ErrorType,ErrorCode, line,col: Integer; const Msg, data: string);
begin
  WriteLn(Format('Error in "%s"(%d,%d): %s',[int1,Line,Col,Msg,data]));
end;

begin
  try
    if (ParamCount=0) then begin
      WriteLn(Format('Usage: %s "1 + 2"',[ChangeFileExt(ExtractFileName(ParamStr(0)),'')]));
      Exit;
    end;
    comp := TExprUnit.Create(nil);
    try
      meth.Data := comp;
      meth.Code := @ErrorHandler;
      comp.OnError := errProc;

      int1 := ParamStr(1);
      WriteLn(int1);
      rez := comp.Evaluate(int1);
      WriteLn(rez);
    finally
      comp.Free;
    end;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
----------------------------------------

실행결과

댓글
300x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함