各位编程高手大家好,小弟有件很着急的事情,老师让我们用编译原理学过的词法分析和语法分析写一个计算器(用到自顶向上或者自顶向下),要求把输入的表达式全部显示在计算器上,包括求正余弦,正余切,括号,加减乘除,平方开方,最后还要把等号和结果显示在计算器上,不知道各位编程高手谁会呀,要是会的话,麻烦您把做好的计算器和代码发到

解决方案 »

  1.   

    最简单的办法----
    shellexec('cal.exe')
    呵呵
      

  2.   

    括号,加减乘除,二次方程的例子我有的,别的那些平方开方就没有.Sign.
      

  3.   

    太麻烦了,你不如连接到数据库,然后把表达式作为sql语句拿去执行,不看源程序没人知道地。
      

  4.   

    Forllx(京)大哥,麻烦你把你的例子发到我的邮箱里好吗?
      

  5.   

    import activex control
    ms scripting
      

  6.   

    myfine(myfine)大哥,麻烦你好好找一下好吗,求求你了,找到后发到
      

  7.   

    计算一个加减乘除表达式的例子:unit compute;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Math;type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Button1: TButton;
        Edit2: TEdit;
        procedure Button1Click(Sender: TObject);  private
        { Private declarations }
        s: string;
        function GetNumber(): real;
        function comp(a, b: char): char;
        function cal(a, b: real; p: char): real;
        function expr(): real;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    var r: real;
    begin
      s := edit1.Text; //edit1中为要求值的表达式
      r := expr(); //  调用求值函数
      edit2.Text := floattostr(r); //将求值结果写到eidt2中
    end;function TForm1.cal(a, b: real; p: char): real;
    begin
      case p of
        '+': result := a + b;
        '-': result := a - b;
        '*': result := a * b;
        '/':
          begin
            if b = 0 then
            begin
              showmessage('除数为0');
              result := 0;
            end
            else
              result := a / b;
          end;
      end;
    end;function TForm1.comp(a, b: char): char;
    begin
      if not (a in ['+', '-', '*', '/', '(', ')', '#']) or not (b in ['+', '-', '*', '/', '(', ')', '#']) then result := 'e'
      else
        case a of
          '+', '-': case b of
              '*', '/', '(': result := '<';
            else result := '>';
            end;
          '*', '/': if b = '(' then result := '<' else result := '>';
          '(': if b = ')' then result := '=' else if b = '#' then result := 'e' else result := '<';
          ')': if b = '(' then result := 'e' else result := '>';
          '#': if b = ')' then result := 'e' else if b = '#' then result := 'R' else result := '<';
        end;
    end;
    function TForm1.expr(): real;
    var
      res, ch: char;
      oprTop, numTop: integer;
      opr: array[1..100] of char;
      num: array[1..100] of real;begin  opr[1] := '#';
      s := s + '#';
      oprTop := 1;
      numTop := 0;
      res := ' ';
      repeat
        if s[1] in ['0'..'9'] then
        begin
          inc(numTop);
          num[numTop] := GetNumber();
        end
        else
        begin
          ch := s[1];
          delete(s, 1, 1);
          repeat
            res := comp(opr[oprTop], ch);
            case res of
              '>': begin
                  num[numTop - 1] := cal(num[numTop - 1], num[numtop], opr[oprTop]);
                  dec(numTop);
                  dec(oprTop);
                end;
              '<': begin
                  inc(oprTop);
                  opr[oprTop] := ch;
                end;
              '=': begin
                  dec(oprTop);
                end;
              'e': begin
                  showmessage('表达式出错!');
                  result := 0;
                  exit;
                end;
              'R': begin
                  result := num[numTop];
                end;
            end;
          until res <> '>';
        end;
      until res = 'R';
    end;
    function TForm1.GetNumber(): real;
    var
      i, code: integer;
    begin
      i := 1;
      while (i <= length(s)) and (s[i] in ['0'..'9', '.']) do inc(i);
      val(copy(s, 1, i - 1), result, code);
      delete(s, 1, i - 1);
    end;
    end.
      

  8.   

    你一些思路,希望对你有些帮助:语法分析方法:递归下降分析方法
    语法规则:
    SimpleStatement ->Designator ':=' Expression
    Expression -> SimpleExpression [RelOp SimpleExpression]...
    SimpleExpression -> ['+' | '-'] Term [AddOp Term]...
    Term -> Factor [MulOp Factor]...
    Factor -> Designator ['(' ExprList ')']
           -> '@' Designator
           -> Number
           -> String
           -> NIL
    分析子程序:
             function ExprList:pTreeNode;
             function Exp:pTreeNode;
             function Simple_exp:pTreeNode;
             function Term:pTreeNode;
             function Factor:pTreeNode;
             ....
    function TParserTree.Term:pTreeNode;//term分析子程序
    var t,p:pTreeNode;
    begin
        t:=factor;
        while  (AToken.Token.TokenKind=tkmult) or(AToken.Token.TokenKind=tkdiv) do
        begin
           p:=newExpNode(opk);
           if p<>nil then
           begin
               p.LChild:=t;
               p.operator:=AToken.Token.Data;
               p.IdName:=Atoken.Token.Data;
               t:=p;
               match(AToken.Token.TokenKind);
               t.RChild:=factor;
           end;
        end;
        result:=t;
    end;
      

  9.   

    这个问题其实很简单,有两种思路
    思路(1):
        1。词法分析
        2、语法分析可以采用底归下降底分析方法,在语法分析过程中构造出一颗二叉树
    其节点数据结构定义:
    type
        pTreeNode=^TTreeNode;
        TTreeNode=record
          Val : Double;        // 节点的值
          operator:string[20]; // 操作符
          IdName:string[20];   // 标识符的值
          NodeType:ExpKind;    // 结点类型
          Lchild:pTreeNode;    // 左孩子节点
          Rchild:pTreeNode;    // 右孩子节点
        end;
    3:进行计算,通过后续遍历这颗二叉树进行计算
    我现在做的这个表达式计算,可以支持自定义函数,并且支持不定参数的计算,如sum(a,b...任意多个),而且表达式里面也可以嵌套表达式,如sum(a,sum(a,b,c))+4/5
    这种思路最关键的是要在内存中构造出一颗二叉树,通过递归调用,计算出表达式的值。
    function TParserTree.ComputerTree(Tree:pTreeNode;var ParamList:string):Double;  //后续计算表达式的值;
    var
      ret1,ret2:double;
      arr:mytype;
      i:integer;
      ret:double;
    begin
      if Tree<>nil then
      begin
         ret1:=ComputerTree(Tree^.Lchild,Paramlist);
         ret2:=ComputerTree(Tree^.Rchild,ParamList);
         case Tree.NodeType of
             opk    :    begin
                           if tree.operator='+'      then result:=ret1+ret2
                           else if tree.operator='-' then result:=ret1-ret2
                           else if tree.operator='*' then result:=ret2*ret1
                           else if tree.operator='/' then
                                                         if ret2<>0 then
                                                             result:=ret1/ret2
    ........
      

  10.   

    思路2:
       类似思路1:
      1)词法分析
      2)语法分析,构造语法树(实际为二叉树)
      3)后续遍历语法树,得到表达式的逆波兰表达式
      4)通过一遍扫描,计算后续表达式的值
    付:计算后续表达式的算法:
    function read(Expression:string;var idx:integer):string;
    var
      ret:string;
    begin
      ret:='';
      if idx<=length(Expression) then
      begin
        while (Expression[idx]<>' ' )and (idx<=length(Expression))do
        begin
           ret:=ret+Expression[idx];
           inc(idx);
        end;
      end;
      inc(idx);//使Idx指向非空元素;
      if Expression[idx]=' 'then
        inc(idx); //两个空格表示当前字符是参数之一;
      result:=ret;
    end;
    function sum(a,b:double):double;//自定义函数
    begin
      result:=a+b;
    end;function square(x:double):double;//自定义函数
    begin
      result:=x*x;
    end;function Multy(a,b,c:double):double;
    begin
      result:=a-c+b;
    end;procedure  Computer_Expression(Expression:string);
    var
      idx:integer;
      Op:string;//从字符串中读取的元素;
      op1,op2,op3,ret:Double;
      stk:TStackCls;
      cRet:string;
    begin
      idx:=1;
      stk:=TStackCls.Create;
      while idx<=length(Expression)do
      begin
        op:=read(trim(Expression),idx);
        if trim(op)='+' then
        begin
           op1:=strtofloat(stk.pop);
           op2:=strtofloat(stk.pop);
           ret:=op1+op2;
           stk.push(floattostr(ret));
        end
        else if trim(op)='-' then
        begin
           op1:=strtofloat(stk.pop); // Pop(S)弹出减数
           op2:=strtofloat(stk.pop); //Pop(S)弹出的是被减数
           ret:=op2-op1;
           stk.push(floattostr(ret));
        end
        else if trim(op)='*' then
        begin
           op1:=strtofloat(stk.pop);
           op2:=strtofloat(stk.pop);
           ret:=op1*op2;
           stk.push(floattostr(ret));
        end
        else if trim(op)='/' then
        begin
           op1:=strtofloat(stk.pop);  // Pop(S)弹出除数
           if(op1<>0.0)then
             ret:=strtofloat(stk.pop)/op1 //Pop(S)弹出的是被除数
           else  //除数为0时终止运行
           begin
             showmessage('div by zero');
             exit;
           end;
           stk.push(floattostr(ret));
        end
        else if trim(op)='sum'then
        begin
           op1:=strtofloat(stk.pop);
           op2:=strtofloat(stk.pop);
           ret:=sum(op1,op2);
           stk.push(floattostr(ret));
        end
        else if trim(op)='square'then
        begin
          op1:=strtofloat(stk.pop);
          ret:=square(op1);
          stk.push(floattostr(ret));
        end
        else if trim(op)='multy'then
        begin
          op1:=strtofloat(stk.pop);
          op2:=strtofloat(stk.pop);
          op3:=strtofloat(stk.pop);
          ret:=multy(op3,op2,op1);
          stk.push(floattostr(ret));
        end
        else
        begin
           stk.push(op);
        end;
      end;
      if not stk.IsEmpty then
        cRet:=stk.pop;
      if not stk.IsEmpty then
      begin
        showmessage('参数数目不匹配,请重新输入!!!');
      end
      else
        showmessage('计算结果='+cRet);
      stk.Free;
    end;procedure TForm1.Button2Click(Sender: TObject);
    var pp:TparserTree;
        str:string;
    begin
       pp:=tparserTree.create;
       str:='sum(9,sum(3,4))+(8*9+888)+(9-(4))*3/8+((5-(8)))';
       pp.Atoken.Origin:=pchar(str);
       form2.Memo1.Clear;
       form2.Memo2.Clear;
       form2.Memo3.Clear;
       form2.Memo1.Lines.Add(str);
       pp.SyntaxTreeShow;
       form2.ShowModal;
       Computer_Expression(pp.postExpression);
       pp.Free;
    end;两种思想对比:
      思路一较思路二
         效率高,在后续遍历的过程中就进行计算,
        支持不定数目参数的自定义函数,
        出错处理比较容易
        支持表达式嵌套
    思路二,计算方法比较容易,只能支持固定数目的自定义函数,支持表达式嵌套
    这方面的计算还要一种比较经典的思路:算法优先算法,比较简单就不多说了。
      

  11.   

    ft, 都是强人, 我现在一看到"编译原理"还头大呢. 不过要是以后想发明个什么东东, 比如3ds, 又想设计个Script语言的话就用到它了. huhu