Syntaktická analýza výrazů

Soubory lex.h, lex.cc, decl.h a expr.cc obsahují parser zjednodušeného jazyka C.
http://kmlinux.fjfi.cvut.cz/~culikzde/prekl/Comp11.tgz
nebo http://gitlab.fjfi.cvut.cz/culikzde/c-parser

Budeme zpracovávat výrazy, ktere mohou obsahovat identifikatory, cela cisla, vyrazy v zavorkach, plus a krat :

  simple : identifier | number | '(' expr ')' ;
  mul    : simple ( '*' simple )* ;
  expr   : mul    ( ( '+' | '-' ) mul )* ;

Syntakticke pravidlo zacina jmenem definovaneho neterminalu a dvojteckou :.
Retezce v uvozovkach jsou terminalni symboly.
Obycejne identifikatory predstavuji neterminalni symboly,
Svisla cara | predstavuje nebo
Zavorka s hvezickou ( )* dovoluje opakovani 0, 1, 2, … libovolne krat.
Zavorka s plusem ( )+ dovoluje opakovani 1, 2, … libovolne krat.
Zavorka s otaznikem ( )? dovoluje opakovani 0 nebo 1 krat.
Muzeme pouzivat zavorky bez nasledujici znacky ( ) vetsinou pri zapisu nekolika alternativ odelenych svislou carou.
Syntakticke pravidlo konci strednikem ;

Funkce rozpoznavájící jednoduché výrazy

void simple_expr (void)
{
  if (sy==IDENT ||
  {
     NextSymbol ();
  }
  else if (sy==NUM)
  {
     NextSymbol ();
  }
  else if (sy==LPAR)
  {
     NextSymbol ();
     expression ();
     CheckSymbol (RPAR);
  }
  else Error ("Syntax error in expression");
}
 
void mul_expr (void)
{
  simple_expr ();
  while (sy==ASTERISK ||
         sy==SLASH ||
         sy==MOD)
  {
     NextSymbol ();
     simple_expr ();
  }
}
 
void add_expr (void)
{
  mul_expr ();
  while (sy==PLUS ||
         sy==MINUS)
  {
     NextSymbol ();
     mul_expr ();
  }
}

Funkce vytvářející syntaktické stromy

V souboru expr.cc nalezneme obdobné funkce, které navíc vytvářejí stromy reprezentující rozpoznané výrazy:
http://gitlab.fjfi.cvut.cz/culikzde/c-parser/-/blob/master/expr.cc#L909

ExprPtr simple_expr (void)
{
  ExprPtr t1;
 
  if (sy==IDENT ||
  {
     t1 = NewStr (IdentVal);
     NextSymbol ();
  }
  else if (sy==NUM)
  {
     t1 = NewStr (NumVal);
     NextSymbol ();
  }
  else if (sy==LPAR)
  {
     NextSymbol ();
     t1 = expression ();
     t1 = calc (t1, NULL, LPAR);
     CheckSymbol (RPAR);
  }
  else Error ("Syntax error in expression");
 
  return t1;
}
 
ExprPtr mul_expr (void)
{
  ExprPtr t1, t2;
  SYMBOL op;
 
  t1 = simple_expr ();
  while (sy==ASTERISK ||
         sy==SLASH ||
         sy==MOD)
  {
     op = sy;
     NextSymbol ();
     t2 = simple_expr ();
     t1 = calc (t1, t2, op);
  }
  return t1;
}
 
ExprPtr add_expr (void)
{
  ExprPtr t1, t2;
  SYMBOL op;
 
  t1 = mul_expr ();
  while (sy==PLUS ||
         sy==MINUS)
  {
     op = sy;
     NextSymbol ();
     t2 = mul_expr ();
     t1 = calc (t1, t2, op);
  }
 
  return t1;
}

Pomocna funkce calc vytvari novy uzel stromu. Napriklad

 t3 = calc (t1, t2, op); 

Ulozi do t3 ukazatel na novy uzel, ktery ma podstromy t1 a t2

       op
       |
   .------.
   |      |
   t1     t2

Funkce add_expr postupne vytvari strom z multiplikativnich vyrazu.
Pokud mame na vstupu

 A + B - C 

Funkce add_expr vytvori strom

          "-"
           |
       .------.
       |      |
      "+"      C
       |
   .------.
   |      |
   A      B

Obrazky: 2. kapitola, stranky 9 a 10 http://inf.ethz.ch/personal/wirth/CompilerConstruction/CompilerConstruction1.pdf
Pripadne dalsi informace: kapitoly 4.1 a 4.2

 
prekl/expr.txt · Last modified: 2023/03/02 16:54 by 147.32.8.115
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki