Главная страница Выбор входного языка Промежуточное представление Разработка Front-end'а Разработка Back-end'а Пара слов про оптимизацию



Front-end - это транслятор входного языка в промежуточное представрение, т.е. front-end должен из последовательнлости лексем построить синтаксическое дерево разбора.

По своей сути front-end - это простой синтаксический анализатор с командами для создания промежуточного представления. К процедурам, анализирующим выражение (Expression) и слагаемое (Term), просто добавляется вызов процедуры AddToTree. А анализатор множителя (Factor) обязан позаботиться о создании листа. Вот исходный текст front-end'а:

(*Front-end               *)
(*          (C)2004,pm_kas*)
MODULE Parser;
IMPORT 
   Error, Scan, Tree;
TYPE
   pTree = Tree.pTree;
   tLex  = Scan.tLex;
 
   PROCEDURE ^ Expression*(VAR Expr :pTree);

(***Процедура обработки "множителя"********************)
(*   
  Множитель = Переменная | Число | "(" Выражение ")".
*)
   PROCEDURE Factor(VAR Expr :pTree);
   BEGIN
      IF Scan.Lex = Scan.lexName THEN
(*!!*)   NEW(Expr);                         
(*!!*)   Expr^.Left:=NIL;                   
(*!!*)   Expr^.Right:=NIL;                  
(*!!*)   Expr^.Name:=Scan.Name;             
(*!!*)   Expr^.Neg:=FALSE;                  
(*!!*)   Expr^.Regs:=0;                    
(*!!*)   Expr^.Value:=-1;                   
(*!!*)   Expr^.Oper:=Scan.lexName;          

         Scan.NextLex;
      ELSIF Scan.Lex = Scan.lexNum THEN
(*!!*)   NEW(Expr);                       
(*!!*)   Expr^.Left:=NIL;                 
(*!!*)   Expr^.Right:=NIL;                
(*!!*)   Expr^.Neg:=FALSE;                
(*!!*)   Expr^.Regs:=0;                  
(*!!*)   Expr^.Value:=Scan.Num;           
(*!!*)   Expr^.Oper:=Scan.lexNum;         
 
         Scan.NextLex;
      ELSIF Scan.Lex = Scan.lexLPar THEN
         Scan.NextLex;
         Expression(Expr);
         IF Scan.Lex = Scan.lexRPar THEN 
            Scan.NextLex;
         ELSE
            Error.Expected('")"');
         END;   
      ELSE
         Error.Expected('Переменная, число, "("');
      END;
   END Factor;
(**Процедура обработки "слагаемого"********************)
(*   
  Слагаемое = Множитель {ОперацияУмножения Множитель}. 
*)
   PROCEDURE Term(VAR Expr :pTree);
   VAR
      Op    : tLex;
      Right : pTree;
   BEGIN
      Factor(Expr);
      WHILE (Scan.Lex = Scan.lexMult) OR 
            (Scan.Lex = Scan.lexDIV) OR 
            (Scan.Lex = Scan.lexMOD) DO
(*!!*)   Op:=Scan.Lex;                    
         Scan.NextLex;
         Factor(Right);
(*!!*)   Expr:=Tree.AddToTree(Expr,Right);
(*!!*)   Expr.Oper:=Op;
      END;
   END Term;
(**Процедура обработки "Выражения"***********************)
(*   
 Выражение = ["+"|"-"]Слагаемое {ОперацияСложения Слагаемое}.
*)
   PROCEDURE Expression*(VAR Expr :pTree);
   VAR
      Op     : tLex;
      Right  : pTree;
   BEGIN
      IF (Scan.Lex = Scan.lexPlus) OR
         (Scan.Lex = Scan.lexMinus) THEN
(*!!*)   Op:=Scan.Lex; 
         Scan.NextLex;
         Term(Expr);
(*!!*)   IF (Op=Scan.lexMinus)&(Expr#NIL) THEN         
(*!!*)      Expr^.Neg:=~Expr^.Neg;             
(*!!*)   END;                                 
      ELSE
         Term(Expr);
      END;
      WHILE (Scan.Lex = Scan.lexPlus) OR 
            (Scan.Lex = Scan.lexMinus) DO
(*!!*)   Op:=Scan.Lex;                    
         Scan.NextLex;
         Term(Right);
(*!!*)   Expr:=Tree.AddToTree(Expr,Right);
(*!!*)   Expr.Oper:=Op;
      END;
   END Expression;

END Parser.

В приведенном выше листинге коментарием (*!!*) помечены строки, отвечающие за генерацию синтаксического дерева. Если их удалить получится обычнай анализатор арифметического выражения, реализованный методом рекурсивного спуска. Про поле Regs и его инициализацию 0 в листьях будет рассказано в главе "оптимизация"

(C) 2004, PM_KAS