YACC Example Analysis

Source: Internet
Author: User


This example comes from <<lex & YACC >> Second Edition

LEX is responsible for lexical analysis, parsing one token at a time.

First, the type and value of token

Token has a type, in the calculator example, including the following types:

1), number a string of numbers

2), name

3), ' + ', '-', ' * ', '/' and other symbols

At the same time token has a value, different types of tokens, the meaning of the value is not the same, for example,

' 1000 ': type is number, value is 1000

' ABC ': Type is NAME, value is ' abc '

After LEX resolves a token, it saves the token value in the Yylval variable and returns the type to YACC.

To be able to save different types of values, Yylval is defined as a union

%union {
  double dval;
  struct Symtab *symp;
}

Where Dval holds the value of type number, SYMP holds the value of the NAME type.

To save a value of the NAME type, a structure is defined

struct Symtab {
    char *name;
    Double (*funcptr) ();
    Double value;

Where name records the name of the "symbol", and value is used to save the calculation result, which is described later in this article.

The NAME type of token, also known as the "symbol", is the same as the variables defined when we write the program.

Therefore, when Lex encounters a number string, it saves the value of the string to Yylval's Dval and returns the number type. When a string is encountered, a SYMTAB structure is generated based on the string name, the name is saved, and the address of the structure is saved to the symp of Yylval, and the name type is returned. When a symbol such as ' + ', '-' is encountered, the ASCII code value of the symbol is returned.

Second, the calculation in YACC

In the "production" or "Rules" section, through the way of $, $, $ $, the value of the corresponding token can be obtained, access to these variables is actually access to yylval. At this point, YACC already knows the type of token, so for the number type, the token value is Yylval.dval, and for the NAME type, the token value is Yylval.symp

For example:

Statement:  NAME ' = ' expression {$1->value = $ $;  printf ("(%s) = (%g) \ n", $1->name, $1->value); }<br> 

expression:  
|   Number          {$$ = $;   }
|   NAME            

For number, it corresponds to the value

For name, $1->name is the symbol name

Types and values of non-terminating symbols

%type <dval> Expression

Third, Appendix: source Code

Symbol.h

#define NSYMS 1024x768/  * Maximum number of symbols */ 

struct Symtab {
    char *name;
    Double (*funcptr) ();
    Double value;
} SYMTAB[NSYMS];

 
struct Symtab *symlook (char* s);

Symbol.c

#include "symbol.h"
#include <string.h>
#include <unistd.h>
#include <stdio.h>
# Include <stdlib.h>

struct Symtab *symlook (char* s)
{
    char *p;
    struct Symtab *sp;

    for (sp = symtab; SP < &symtab[NSYMS]; sp++) {/
        * is it already here *
        /if (Sp->name &&!strcmp ( Sp->name, s) {
            printf ("Found symbol: (%s) \ n", sp->name);
            return sp;
        }

        /* Is it FREE * *
        if (!sp->name) {
            sp->name = StrDup (s);
            printf ("Add Symbol: (%s) \ n", s);
            return sp;
        }
        /* Otherwise continue to next
    *
    /} yyerror ("Too many Symbols");

    Exit (1);    /* Cannot continue */
}/* Symlook */

Calc.l

%{
#include "y.tab.h"
#include "symbol.h"
#include <math.h>
%}

percent
([0-9]+| ( [0-9]*\. [0-9]+] ([ee][-+]?[ 0-9]+)?) {
        Yylval.dval = atof (yytext);
        return number;
    }

[\ t]   ;        /* Ignore white space */

[a-za-z][a-za-z0-9]*    {/   * return symbol pointer */
        struct Symtab *sp = Symloo K (yytext);
        Yylval.symp = SP;
        return NAME;
    }

" $ "{return 0;}

\ n  |

.   return yytext[0];

%%
Calc.y
%{#include <string.h> #include <math.h> #include "symbol.h"%}%union {double dval;
struct Symtab *symp; }%token <symp> NAME%token <dval> number%left '-' + '%left ' * '/'%nonassoc uminus%type <dval&gt ;   Expression statement_list:statement ' \ n ' |

Statement_list statement ' \ n ';  Statement:name ' = ' expression {$1->value = $ $; printf ("(%s) = (%g) \ n", $1->name, $1->value);   }
    | 
    Expression {printf ("=%g\n", $ $);}

;
    Expression:expression ' + ' expression {$$ = $ + $;}   |
    Expression '-' expression {$$ = $-$;}   |
    Expression ' * ' expression {$$ = $ * $;}   |
                    Expression '/' expression {if ($ = = 0.0) Yyerror ("Divide by Zero");
                else $$ = $/$;   }
    |
    '-' expression%prec uminus {$$ =-$2;}   |
    ' (' expression ') ' {$$ = $;}   |   Number {$$ = $;
}    |
    NAME {$$ = $1->value;}   |
            NAME ' (' expression ') ' {if ($1->funcptr) $$ = ($1-&GT;FUNCPTR) ($ $);
                else {printf ("%s not a function\n", $1->name);
            $$ = 0.0;

}
        }
    ; %%


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.