BISON (YACC) (Yet Another Compiler Compiler)

Slides:



Advertisements
Benzer bir sunumlar
Bölüm 11 Metin Dosyaları Metin Dosyaları Dosya Açma ve Kapama
Advertisements

Soru1 : Bir borcun faizi, basit olarak aşağıdaki formülle hesaplanır:
STRİNG FONKSİYONLARI.
Soru1: 1’den 4’e kadar olan tamsayıları ekrana tek satırda görülecek şekilde yazdıran bir programı aşağıdaki metotları kullanarak yazınız. Bir printf ifadesi.
Diziler.
Bölüm 8 Diziler Dizi Tanımı Dizi Elemanlarına Değer Atama
Bölüm 12 ÜST DÜZEY KONULAR Dinamik Bellek Ayırma Önişlemci
Nöbetçi Kontrollü Döngü
Göstericiler (Pointers)
Bölüm 7 Fonksiyonlar GÖSTERGELER Gösterge Tanımı
Bölüm 2 C Dilinin Temelleri
String Diziler(Katarlar)
C Programlama Diline Giriş
Değişken Bildirimleri
Atama ve Girdi/Çıktı Komutları
 Print() :  Print() : Ekrana bir değişkenin değerini veya bir metni yazdırmayı sağlar. print (“PHP Programlama”);// ekrana “PHP Programlama” yazdırır.
Elektrik-Elektronik Mühendisliği Bölümü DİZİLER C Programlama Dili Yaz Stajı Cengiz TEPE SAMSUN 2007.
Soru1: kuvvet(taban,us) Şeklinde bir yinelenen fonksiyon yazın
Bölüm 9 Dizgiler Dizgi Tanımı Dizgi Girdi İşlemleri
String Kütüphanesindeki Arama Fonksiyonları
Bölüm 10 Yapılar ve Birleşimler
Bölüm 2 C Dilinin Temelleri Genel Kavramlar
Derleyici Araçları FLEX & BISON
Soru1: Kullanıcıdan iki tam sayı girmesini isteyen ve daha sonra büyük olan sayı ile beraber ‘en büyüktür’ ifadesi yazan, ancak sayılar birbirine eşitse.
Fonksiyonlar.
C++ Temelleri C++ genel amaçlı, nesne tabanlı, yüksek seviye programlama dilidir.
C ile Programlamaya Giriş
FONKSİYONLAR.
Celal Bayar Üniversitesi Hasan Ferdi Turgutlu Teknoloji Fakültesi
DEĞİŞKENLER.
Derleyici Teorisine Giriş
Diziler Adres Kavramı Nesnelerin Adresleri sizeof Operatörü
Diziler Dizi Tanımı Dizi Elemanlarına Değer Atama Diziler ve Göstergeler 2-Boyutlu Diziler.
Fonksiyonlar Fonksiyon Tanımı Değer Döndürmeyen Fonksiyonlar
Fonksiyonlar Fonksiyon Tanımı
Diziler (Arrays).
Temel Giriş/Çıkış Fonksiyonları
Diziler. Dizi Tanımı Dizi Elemanlarına Değer Atama Diziler ve Göstergeler 2-Boyutlu Diziler.
Bilgisayar Programlama. Tek bir değişken tanımlamak için aşağıdaki gibi bir yazım yeterlidir. int i; Hatırlanacağı gibi bu tarz bir tanımlamada.
Bölüm 6 Fonksiyonlar Fonksiyon Tanımı Değer Döndürmeyen Fonksiyonlar
Dizgiler Dizgi Tanımı Dizgi Girdi İşlemleri Dizgi Çıktı İşlemleri Dizgi Fonksiyonları Karakter Fonksiyonları Gösterge Dizgileri.
flex Sözcüksel Analiz İçin Bir Araç
Sözcüksel Çözümleme/Analiz (Lexical Analysis)
2. HAFTA 2. Hafta.
Sentaks (Sözdizim) ve Semantik (Anlam)
Bölüm 3 Atama ve Girdi/Çıktı Komutları Bölüm 3 Atama ve Girdi/Çıktı Komutları Atama Komutu Operatörler İsim Sabitleri Veri Tipi Dönüşümü Çıktı Fonksiyonu.
1 7. HAFTA. 2 Referanslar  Referanslar adres temsilcisidir  İşaretçilerin görevlerini kısmi olarak yapabilirler  Değişken değildirler.  Bellekte yer.
String Diziler(Katarlar)
C Programlamada, benzer tipte tanımlaman değişkenleri kontrol etmede bize en çok yardım eden dostlarımız dizilerdir. Örneğin: 100 Öğrencinin bilgilerini.
BİLGİSAYAR programlama II
BİLGİSAYAR PROGRAMLAMA Ders 6: Diziler Yrd. Doç. Dr. Altan MESUT Trakya Üniversitesi Bilgisayar Mühendisliği.
İbrahim Olgaç PROGRAMLAMA DİLLERİ SUNUMU C#
Bölüm 8 Diziler Dizi Tanımı Dizi Elemanlarına Değer Atama Diziler ve Göstergeler 2-Boyutlu Diziler.
Programlamaya Giriş-I Bölüm-1. Algoritma Algoritma günlük yaşamımızda yaptığımız işler sırasında sıklıkla kullandığımız bir yöntemdir. Algoritma, bir.
Bölüm 3 Atama ve Girdi/Çıktı Komutları
Bölüm 6 Fonksiyonlar Fonksiyon Tanımı Değer Döndürmeyen Fonksiyonlar
BİLGİSAYAR PROGRAMLAMA Ders 6: Diziler
C Programlama Dili Bilgisayar Mühendisliği.
Bilgisayar Programlamasına ve Veri Analizine Giriş - IV
BİLGİSAYAR PROGRAMLAMA Ders 6: Diziler
BÖLÜM 5 POINTER’LER (İŞARETÇİLER)
C Programlama Yrd.Doç.Dr. Ziynet PAMUK BMM211-H11
Bölüm 9 Dizgiler Dizgi Tanımı Dizgi Girdi İşlemleri
Bölüm 2 C Dilinin Temelleri
PROGRAM KONTROL KOMUTLARI 1. if koşulu 2. if else koşulu
YAPISAL PROGRAMLAMA Hafta-6
YAPISAL PROGRAMLAMA Hafta-7
Bölüm 3 Atama ve Girdi/Çıktı Komutları
Bölüm 2 C Dilinin Temelleri
Bir Döngünün Bölümleri (hatırlatıcı)
Sunum transkripti:

BISON (YACC) (Yet Another Compiler Compiler)

Bison Bison, İçerikten/Bağlamdan Bağımsız bir Gramer (Context-Free Grammar, CFG) tanımlaması yapar. CFG ise parser (sözdizimsel analizci) oluşturmaya yarar. CFG’nin elemanları: 1. Terminaller: token’lar ve lexeme’ler 2. Değişkenler (Terminal Olmayanlar): sözdizimsel elemanlar 3. Üretim Kuralları 4. Başlama Kuralı

Bison Bir üretim kuralının formatı: sembol: tanım {aksiyon}; Örnek: <a> → <b>c CFG ifadesi bison da şöyle yazılır: a: b 'c'; (Eğer b bir token değilse) a: B 'c'; (Eğer b bir tokensa)

Bison Dosya Formatı Bison dosyasının formatı: %{ C deklarasyonları Oluşan C programına direkt kopyalanırlar. Örneğin, değişkenler, tipler, makrolar… %} tanımlar %% Üretim kuralları C programları

Tanımlar Tokenları ve onların karakteristik özelliklerini tanımlamak için kullanılırlar: %token: token adları tanımlanır. %left: sol-çağrışımlı operatörler tanımlanır. %right: sağ-çağrışımlı operatörler tanımlanır. %type: değişken tipleri tanımlanır.

Tanımlar %union: semantik değerler için çoklu veri tipleri tanımlanır. %start: başlama sembolü tanımlanır. (verilmemişse kurallardaki ilk değişken, başlama sembolü olarak atanır.) %prec: kurala öncelik atanır. (precedence)

L={ anbn | n>=1} dilini kabul etmek için tasarlanan kolay bir bison programı.

anbn.y %{ #include <stdio.h> /* printf */ %} %token A B %% /* The .y extension is a convention used for Bison input files.*/ %{ #include <stdio.h> /* printf */ %} %token A B %% start: anbn '\n' {printf(" is in anbn\n");return 0;} anbn: A B | A anbn B; int yyerror(char *s) { printf("%s, it is not in anbn\n", s); } int main() yyparse(); return 0; /* The .y extension is a convention used for Bison input files.*/ %{ #include <stdio.h> /* printf */ %} %token A B %% program: start | program start; start: anbn '\n' {printf(" is in anbn\n");} anbn: A B | A anbn B; int yyerror(char *s) { printf("%s, it is not in anbn\n", s); } int main() yyparse(); return 0;

anbn.lex %{ #include "anbn.tab.h" %} %% a return A; b return B; . return yytext[0]; \n return '\n';

flex-bison İkilisini Çalıştırma $ flex anbn.lex (İçinde bulunduğunuz klasörde lex.yy.c dosyası oluşur.) $ bison -d anbn.y (İçinde bulunduğunuz klasörde anbn.tab.h ve anbn.tab.c dosyaları oluşur. anbn.tab.h dosyası TOKEN’lara karşılık gelen tamsayı tanımlamalarını, anbn.tab.c dosyası da yyparse fonksiyonunu içerir.) $ gcc anbn.tab.c lex.yy.c -lfl (İçinde bulunduğunuz klasörde a.out isimli executable dosya oluşur.) $ gcc -o anbn.x anbn.tab.c lex.yy.c -lfl (İçinde bulunduğunuz klasörde anbn.x isimli executable dosya oluşur.) yyparse();

flex-bison İkilisini Çalıştırma $ ./a.out aabb is in anbn $ ./anbn.x acadbefbg syntax error, it is not in anbn yyparse(); Eğer girdi akımı start kuralı ile uyuşmazsa, program klasik “syntax error” mesajı verir ve sonlanır. Ancak, yyerror fonksiyonu içerisinde özel hata mesajları da oluşturulabilir.

Elemanlar İçin Değerlerin Pozisyonel Atamaları $$: Sol taraf $1: Sağ taraftaki ilk eleman $n: Sağ taraftaki n. eleman

Tamsayıları Yazdırma (PrintIntegers.lex) %{ #include "PrintIntegers.tab.h" #include <stdlib.h> /* atoi */ %} %% [0-9]+ {yylval=atoi(yytext);return INTEGER;} \n return NEWLINE; . return yytext[0];

Tamsayıları Yazdırma (PrintIntegers.y) %{ #include <stdio.h> /* printf */ %} %token INTEGER NEWLINE %% lines: /* empty string or epsilon */ | lines NEWLINE | lines line NEWLINE {printf("=%d\n", $2);} | error NEWLINE {yyerror("Tekrar dene:");}; line: INTEGER {$$ = $1;}; int yyerror(char *s) { printf("%s\n", s); } int main() yyparse(); return 0;

Örnek Çıktı $ ./PrintIntegers.x 7 =7 007 zippy syntax error Tekrar dene:

Rekürsif Kurallar Sağ-rekürsif kurallar da kullanılabilir. Ancak, parser verimliliği açısından sol-rekürsif kurallar daha sıklıkla tercih edilir.

yylval yylex() fonksiyonu, okunan token’ın tipini belirten bir sayı döndürür. (token number) Eğer token’la ilişkili bir sayı varsa, dış değişken olan yylval değişkenine atanmalıdır.

yylval Fabrika ayarı olarak yylval ın tipi int dir. Tipi değiştirmek için YYSTYPE makrosunu bison dosyasının deklarasyon kısmında kullanmanız gerekir. %{ #define YYSTYPE double %} Eğer token değerleri için birden fazla veri tipi varsa, yylval “union” olarak tanımlanmalıdır.

yylval yylval için olası 3 tip örneği: %union{ double real; /* real değer */ int integer; /* integer değer */ char str[30]; /* string değer */ } Örnek: yytext = "0012", yylval tipi: int, yylval değeri: 12 yytext = "+1.70", yylval tipi: double, yylval değeri: 1.7

Token Tipleri Token’ların ilişkili değerlerinin (lexeme’lerinin) tipleri şöyle tanımlanır: %token <real> REAL %token <integer> INTEGER %token <str> IDENTIFIER Değişkenlerin tipleri şöyle tanımlanır: %type <real> real-ifade %type <integer> integer-ifade

Sözcüksel Analizci’den Token’ların Değerlerini Geriye Döndürme (LexicalAnalyzer.lex) %{ #include "LexicalAnalyzer.tab.h" #include <string.h> /* strcpy */ %} alphabetic [A-Za-z] digit [0-9] alphanumeric ({alphabetic}|{digit}) %% [+-]?{digit}*(\.)?{digit}+ {sscanf(yytext, "%lf",&yylval.real);return REAL;} {alphabetic}{alphanumeric}* {strcpy(yylval.str,yytext);return IDENTIFIER;}

Operatör Önceliği Aynı satırdaki token’lar aynı öncelik ve ilişki türüne sahiptir. Alt satıra geçtikçe öncelik artar. +, - ile *, / ile aynı önceliğe sahiptir. Ama * ve / daha önceliklidir. Ayrıca 4 operatör de sol-çağrışımlıdır. %left '+' '-' %left '*' '/'

Basit Bir Hesap Makinesi (Calculator.lex) %{ #include "Calculator.tab.h" %} integer [0-9]+ real1 ([0-9]*\.[0-9]+) real2 ([0-9]*\.[0-9]+[Ee][+-]?[0-9]+) real {real1}|{real2} nl \n %% [ \t] ; /* Do nothing for space */ {integer} { sscanf(yytext, "%d", &yylval.integer);return INTEGER;} {real} { sscanf(yytext, "%lf", &yylval.real);return REAL;} \+ { return PLUS;} \- { return MINUS;} \* { return TIMES;} \/ { return DIVIDE;} \( { return LP;} \) { return RP;} {nl} { return NL;} . { return yytext[0];}

Basit Bir Hesap Makinesi (Calculator.y) %{ #include <stdio.h> %} %union{double real;int integer;} %token <real> REAL %token <integer> INTEGER %token PLUS MINUS TIMES DIVIDE LP RP NL %type <real> rexpr %type <integer> iexpr %left PLUS MINUS %left TIMES DIVIDE %% lines: /* nothing */ | lines line; line: NL | iexpr NL { printf("%d\n", $1);} | rexpr NL { printf("%15.8lf\n", $1);}; iexpr: INTEGER | iexpr PLUS iexpr { $$ = $1 + $3;} | iexpr MINUS iexpr { $$ = $1 - $3;} | iexpr TIMES iexpr { $$ = $1 * $3;} | iexpr DIVIDE iexpr { if($3) $$ = $1 / $3; else { yyerror("sıfıra bölme hatası");}} | MINUS iexpr { $$ = - $2;} | LP iexpr RP { $$ = $2;};

Basit Bir Hesap Makinesi (Calculator.y) rexpr: REAL | rexpr PLUS rexpr { $$ = $1 + $3;} | rexpr MINUS rexpr { $$ = $1 - $3;} | rexpr TIMES rexpr { $$ = $1 * $3;} | rexpr DIVIDE rexpr { if($3) $$ = $1 / $3; else { yyerror("sıfıra bölme hatası");}} | MINUS rexpr { $$ = - $2;} | LP rexpr RP { $$ = $2;} | iexpr PLUS rexpr { $$ = (double)$1 + $3;} | iexpr MINUS rexpr { $$ = (double)$1 - $3;} | iexpr TIMES rexpr { $$ = (double)$1 * $3;} | iexpr DIVIDE rexpr { if($3) $$ = (double)$1 / $3; else { yyerror( "sıfıra bölme hatası" );}} | rexpr PLUS iexpr { $$ = $1 + (double)$3;} | rexpr MINUS iexpr { $$ = $1 - (double)$3;} | rexpr TIMES iexpr { $$ = $1 * (double)$3;} | rexpr DIVIDE iexpr { if($3) $$ = $1 / (double)$3; else { yyerror( "sıfıra bölme hatası" );}}; %% int yyerror(char *s) { printf("%s\n", s); } int main() yyparse(); return 0;