Instrukcja Laboratoryjna. Instrukcja Laboratoryjna Parser gramatyki bezkontekstowej BISON Część statyczna
|
|
- Janusz Adamski
- 7 lat temu
- Przeglądów:
Transkrypt
1 Instrukcja Laboratoryjna Parser gramatyki bezkontekstowej BISON Część statyczna 1. Wprowadzenie BISON jest parserem konwertującym opis gramatyki bezkontekstowej LALR(1) do programu w języku C, który następnie będzie parsował zadaną gramatykę. Jest on kompatybilny ze wszcześniejszymi implementacjami Yacc a. 2. Podstawowe pojęcia a. Języki i gramatyki bezkontekstowe Parser BISON umożliwia parsowanie tylko gramatyk bezkontekstowych (ang. contex-free grammar). Chociaż jest przystosowany do parsowania prawie wszystkich gramatyk bezkontekstowych, jest on optymalizowany dla gramatyk typu LALR(1). Krótko mówiąc, w tych gramatykach musi być możliwe stwierdzenie, jak należy opisywać każdą porcję danych na wejściu, wykorzystując tylko pojedynczy znak. Dodatkowo parsery te są deterministyczne, co znaczy, że za każdym razem te same dane wejściowe dadzą takie same wyniki działania parsera. W formalnym opisie reguł gramatycznych języka każdy rodzaj syntaktycznych jednostek lub sposobów ich grupowania jest nazywany symbolem. Te,które są budowane poprzez grupowanie mniejszych konstrukcji zgodnie z regułami gramatyki, nazywają się symbolami nieterminalnymi (ang. nonterminal symbols), natomiast te, które nie mogą zostać podzielone, nazywane są symbolami terminalnymi (ang. terminal symbols). W poniższym opracowaniu tokenem (ang. token type) będzie nazywany pojedynczy symbol terminalny, natomiast część odpowiadająca pojedynczemu symbolowi nieterminalnemu będzie nazywana grupowaniem (ang. grouping). Formalnym opisem gramatyki jest konstrukcja matematyczna. Aby zdefiniować język dla BISONa, należy opisać gramatykę zgodnie ze składnią BISONa. b. Parser LL(1). Akcje shift i reduce. Parser jest maszyną stanową (ang. state machine). Jego "program" stanowi wbudowany graf stanów oraz tranzycji pomiędzy nimi. Z każdym stanem skojarzona jest akcja parsera. Po każdej akcji parser podejmuje decyzję o kolejnej tranzycji. Aby wykonać właściwą tranzycję, parser musi rozpoznać zaistniałą sytuację na podstawie dostępnych czynników decyzyjnych. Pierwszym czynnikiem decyzyjnem jest bieżacy stan, w którym znajduje się parser. Drugim czynnikiem jest bieżący stan wejścia (strumienia tokenów). LL(1) oznacza, że parser bierze pod uwagę jedynie pierwszy token będący właśnie na wejściu strumienia gramatyki LL(1) to takie gramatyki, w których graf parsera pozstaje rozstrzygalny przy uwzględnieniu tylko pierwszego tokenu z wejścia. Tak więc parser LL(1) wykorzystuje dwa czynniki decyzyjne, stąd implementacja jego grafu jest 2-wymiarową tablicą. Ze względów technicznych "obserwowany" token w wielu implementacjach znajduje się na szczycie stosu parsera, zamiast fizycznie na wejściu strumienia. Graf parsera jest budowany na podstawie gramatyki, którą parser ma za zadanie analizować. Graf ten nie zmienia się w czasie pracy parsera zapisany jest jako stała typu tablicowego. Podczas analizy parser wykonuje jedynie swój "program" wszystkie decyzje zostały już podjęte na etapie kompilacji gramatyki do postaci grafu (dzięki temu gotowy parser jest bardzo szybki). Centralną stukturą danych parsera jest stos symboli. Na stosie odkładane są symbole terminalne pobierane ze strumienia wejściowego. Po skompletowaniu odpowiedniego ciągu symoli są one redukowane (usuwane ze stosu) do pojedynczego symbolu nieterminalnego (odkładany na stos). Cykl ten jest powtarzany według reguł gramatyki. Celem parsera jest uzyskanie w ostatniej redukcji tylko jednego symbolu na stosie głowy gramatyki. Taki wynik oznacza poprawne zakończenie analizy składniowej zadanego wejścia. (c) Karolina Nurzyńska Page 1
2 W każdym kroku parser może wykonać jedną z dwóch akcji: shift lub reduce. Akcja shift polega na przepisaniu symbolu z wejścia na stos. Akcja reduce oznacza redukcję n symboli z wierzchołka stosu do jednego symbolu nieterminalnego według określonej reguły gramatyki. Aby zilustrować pracę parsera, rozważmy przedstawioną poniżej krótką gramatykę, która opisuje składnię instrukcji przypisania. asgn: lvalue '=' expr '' lvalue: _ID expr: _ID expr '+' expr Na poniższym rysunku zostały przedstawione kolejne kroki parsera dla przykładowego ciągu wejściowego. Pojewienie się na stosie jedynego symbolu będącego głową gramatyki jest przyjmowane za poprawne zakończenie procesu analizy. c. Wartości semantyczne W czasie parsowania najpierw sprawdza się do jakiej reguły gramatycznej pasuje token, od tego też zależy typ tokena, poza tym z każdym tokenem jest związana wartość semantyczna (ang. semantic value), która zawiera wszystkie znaczące informacje o tokenie. d. Akcje semantyczne Aby parser był przydatnym programem musi, poza parsowaniem danych z wejścia, wykonywać akcje i dawać wyniki działania. Podczas definiowania reguł gramatycznych w BISONie można tworzyć akcje (ang. action), które zostaną wykonane przez program. W większości przypadków celem wykonania akcji jest obliczenie wartości semantycznej całej konstrukcji na podstawie poszczególnych wartości semantyczych składników wyrażenia. e. Lokacje Wiele aplikacji, takich jak interpretery czy kompilatory, musi produkować bogaty opis informacji o błędach działania. Aby to osiągnąć należy umożliwić śledzenie lokacji (ang. locations) oraz lokacji tekstowych każdej konstrukcji syntaktycznej. BISON zapewnia mechanizm obsługi lokacji. Tak jak token ma przypisaną semantyczna wartość, tak też jest związany z lokacją. Ponad to wyjściowy parser jest wyposażony w domyślną strukturę danych do składowania informacji o lokacjach. 3. Ogólny wygląd pliku do opisu gramatyki w BISONie Na wejście BISONa jest pobierany plik ze specyfikacją gramatyki bezkontekstowej, a na wyjściu jest produkowana funkcja w języku C, która rozpoznaje poprawne instacje tej gramatyki. Zgodnie z konwencją plik wygenerowany przez BISON ma rozszerzenie *.y. Opis gramatyki w BISONie składa sie z czterech głównych sekcji zaprezetowanych poniżej z odpowiednimi ogranicznikami. Komentarze zamknięte w /*... */ mogą pojawiać się w każdej z sekcji. Jako rozszerzenie GNU można również wprowadzać komentarze jednoliniowe po znakach //. (c) Karolina Nurzyńska Page 2
3 %{ Prolog %} Deklaracje Reguły gramatyczne Epilog (c) Karolina Nurzyńska Page 3
4 a. Prolog Ta część zawiera makro definicje i deklaracje funkcji i zmiennych, które będą wykorzystywane w akcjach lub regułach gramatycznych. Część ta jest kopiowana na początek pliku parsera poprzedzającej definicję yyparse. Można używać tutaj dyrektywy #include, aby dostać się do deklaracji z plików nagłówkowych. Jeżeli takie deklaracje nie są potrzebne, można tę część pominąć wraz z ogranicznikami %{ i %}. Możliwe jest również stworzenie kilku sekcji prologu przeplatających się z sekcją deklaracji. Takie skontruowanie tej części pozwala na tworzenie deklaracji w C i BISONie, które odnoszą się jedna do drugiej. b. Sekcja deklaracji Sekcja deklaracji zawiera deklaracjie, które definiują symbole terminalne i nieterminalne, specyfikują pierwszeństwo itd. W niektórych prostych gramatykach sekcja ta może zostać pominięta. c. Sekcja reguł gramatycznych W tej sekcji zostają wypisane reguły gramatycznie i nic więcej. Zawsze musi być przynajmnniej jedna reguła gramatyczna i na poczatku musi znaleźć się (poprzedzając reguły gramatyczne). d. Epilog Część ta jest bezpośrednio kopiowana do pliku parsera na jego koniec, tak samo jak prolog na początek. Jest to najlepsze miejsce do umieszczania jakichkolwiek dodatkowych rzeczy, ktore powinny znależć się w parserze, a nie powinny wyprzedzać definicji yyparse. Przykładowo można tutaj umieszczać definicjie funkcji yylex lub yyerror. Należy jednak pamiętać o deklaracji tych funkcji w prologu, gdyź jest to wymagane przez składnię języka C. Jeżeli ta sekcja jest pusta, można ominąć separator po sekcji reguł gramatycznych. Należy pamiętać, że parser BISONa definiuje wiele makr i definicji, których nazwy zaczynają się od znaków yy lub YY dlatego należy unikać używania tak rozpoczynających się nazw w części epilogu (chyba, że są to nazwy udokumentowane w instrukcji BISONa). 4. Symbole terminalne i nieterminalne Symbole w gramatyce BISONa reprezentują klasyfikatory gramatyczne języka. Symbol terminalny znany jako token reprezentuje klasę syntaktycznie równoważnych tokenów. Korzysta się z tych symboli do tworzenia reguł gramatycznych, aby stwierdzić, że dana klasa tokenów jest dozwolona w danym miejscu. Symbol w parserze jest reprezentowany przez kod numeryczny i funkcja yylex zwraca kody tokenów, aby wskazać jaki token został odczytany. Użytkownik piszący gramatykę nie musi znać wartości numerycznej tych kodów, wystarczy znać stałe symboliczne. Symbol nieterminalny jest przedstawicielem klasy syntaktycznie równoważnych grup. Nazwa jest wykorzystywana do zapisu reguł gramatycznych. Nazwy symboli mogą składać się z liter i cyfr (ale nie na początku) podkreśleń i kropek. Z tym, że kropki mają tylko sens w przypakdu symboli nieterminalnych. Symbole terminalne można zapisać na trzy sposoby w gramatyce: Nazwany token (ang. named token type) może zostać napisany jako indentyfikator, tak jak to jest robione w języku C. Powinien być on pisany wielką literą. Każda z nazw musi być definiowana wykorzystując deklaracje %token Znakowy token (ang. character token type lub literal character token) jest zapisywany w gramatyce, korzystając z takiej samej składni, jaka jest używana w języku C dla zapisu stałych znakówych, np. +. Taki token nie musi być deklarowany, jeśli nie jest to potrzebne do specyfikowania jego semantycznej wartości, połączeń oraz pierwszeństwa. Zgodnie z konwencją token znakowy jest wykorzystywany tylko do reprezentacji tokena składającego się ze szczególnego znaku. Stąd, token + reprezentuje +. Wszystkie sekwencje ucieczek wykorzystywane w C i zapisane za pomocą literałów znakowych mogą być wykorzystywane (c) Karolina Nurzyńska Page 4
5 w BISONie, ale nie należy korzystać ze znaku null, gdyż jego numeryczny kod zero oznacza koniec pobierania danych. Token ciągu znaków (ang. literal string token) jest również zapisywany jako stały łańcuch (dwu)znakowy w C, np. >=. Nie musi być on deklarowany, jeżeli nie trzeba określać jego typu, powiązań oraz pierwszeństwa. Można połączyć ten token z nazwą symboliczną, korzystając z deklaracji %token. Jeżeli to nie zostanie wykonane, analizator leksykalny będzie musiał pobrać numer tokenu z tabeli yytname. (UWAGA: ten typ tokenów nie jest zgodny ze specyfikacją Yacc) Zgodnie z konwencją, również ten token jest używany do reprezentacji łańcuchów znkowych. Należy pamiętać, że wartości tokenów są dodatnie. Ujemna lub zerowa wartość tokena na wejściu parsera oznacza koniec danych wejściowych zwrócony przez funkcje yylex. Każdy nazwany token staje się makrem w pliku parsera, dlatego też yylex może korzystać z tych samych nazw dla kodów. W przypadku definiowania yylex w oddzielnym pliku należy udostępnić definicje makr tokenów. Wykorzystuje się do tego opcje -d przy wywołaniu programu BISON. W wyniku czego definicje makr zostaną zapisane w osobnym pliku nagłówkowym o nazwie name.tab.h, który można dołączyć do innych plikow źródłowych w razie potrzeby. 5. Składnia reguł gramatycznych Reguły gramatyczne mają następująca formę: wynik: składniki... Gdzie wynik jest symbolem nieterminalnym, który opisuje regułę, natomiast składniki są różnymi symbolami terminalnymi lub nieterminalnymi, które wchodzą w skład reguły.na przykład: wyn: wyn + wyn Oznacza, że dwie grupy typu wyn z tokenem + między nimi mogą być złączone w większą grupę typu wyn. Białe znaki w regule nie są znaczące, służą tylko do oddzielenie symboli. Między komponentami mogą być umieszczone akcje, które determinują reguły semantyczne. Akcja wygląda w następujący sposób: { kod w C} Zazwyczaj jest tylko jedna akcja następująca po składniku. Wielokrotne reguły dla tego samego wyniku mogą być zapisywane oddzielnie lub złączone za pomocą znaku : wynik: składniki_pierwszej_reguly... składniki_drugiej_reguly Jeżeli składnik w regule jest pusty, oznacza to, że wynik może być równoważny pustemu łańcuchowi znaków Poniższy przykład pokazuje, jak zdefiniować sekwencje oddzielone przecinkiem składające się z zerowej lub wielu grup wyn: (c) Karolina Nurzyńska Page 5
6 wynsekw: /*empty*/ wynsekw1 wynsekw1: wyn wynsekw1, wyn a. Reguły rekursywne Reguła jest nazwana rekursywaną, gdy jej wynikowy symbol nieterminalny pojawia się również po prawej stronie. Większość gramatyk wymaga reguł rekursywnych, gdyż jest to jedyny sposób zdefiniowania wyrażeń sekwencyjnych. Można wyróżnić dwa typy definicji rekursywnych: wynsekw1: wyn wynsekw1, wyn wynsekw1: wyn wyn, wynsekw1 W pierwszej sekwencji wynsekw1 jest pierwszym symbolem po lewej stronie w prawej części reguły, dlatego też rekurencję tę nazywa się lewostronną (ang. left recursion). W drugim przypadku mamy rekurencje prawostronną (ang. right recursion). Każdy typ sekwencji może zostać opisany za pomocą zarówno rekurencji prawo- jak i lewostronnej, jednak sugeruje się korzystanie z rekurencji lewostronnej, ponieważ może to sparsować sekwencję składającą się z każdej liczby elementów niezależnie od miejsca na stosie. W przypadku prawostronnej rekurencji wykorzystuje się stos o wiele bardziej, gdyż wszystkie znaki muszą się w nim znaleźć, nim reguła zacznie się redukować. Można również wyróżnić rekurencję pośrednią (ang. indirect recursion) lub wzajemną (ang. mutual recursion), która ma miejsce, gdy wynik jednej z reguł nie pojawia się bezpośrednio po jej prawej stronie, ale pojawia się w regule dla jednego z symboli nieterminalnych po jego prawej stronie: wyr: podst podst + podst podst: stala ( wyr ) b. Definiowanie semantyki języka Reguły gramatycznie określają tylko składnię. Semantyka jest determinowana za pomocą wartości semantycznych związanych z różnymi tokenami i grupowaniami. W wyniku wykonywania akcji zmieniana może być ich wartość. Typy danych wartości semantycznych W prostym programie może być wystarczające użycie jednego typu danych dla wszystkich wartości semantycznych. Domyślnym typem w BISONie jest int. Aby określić jako domyślny inny typ, należy zdefiniować makro YYSTYPE #define YYSTYPE double Definicja makra powinna znaleźć się w części prologu. Więcej typów danych wartości semantycznych W większości programów potrzebnych jest wiele typów danych dla różnych tokenów i grupowań. Na przykład stała numeryczna może być typu int lub long int, podczas gdy łańcuch stałej może wymagać char*. Aby móc korzystać z wjększej ilości typów dla wartości semantycznych w jednym parserze, BISON wymaga określenia dwóch rzeczy: (c) Karolina Nurzyńska Page 6
7 określenia kolekcji potrzebnych typów danych za pomocą deklaracji %union, wybrania jednego z tych typów dla każdego z symboli (terminalnych i nieterminalnych), dla których wartości semantyczne będa wykorzystywane. Można to wykonać za pomocą deklaracji %token lub %type. c. Akcje semantyczne Akcja semantyczna akompaniuje regule syntaktycznej i zawiera kod C, który powinien być wykonany za każdym razem, gdy instancja tej reguły zostanie rozpoznana. Zadaniem większości akcji jest obliczenie wartości semantycznej dla grupy na podstawie wartości semantycznych jej składników. Akcja składa się z kodu w języku C wziętego w nawiasy. Akcja może zostać umieszczona w każdym miejscu reguły. Większość reguł ma tylko jedną akcję na jej końcu po wszystkich składnikach. Ale wystepują również akcje w środku reguł, jednak należy z nich korzystać tylko w szczególnych przypadkach. Wartość semantyczna każdego składnika reguły jest reprezentowana w kodzie C jako $n, gdzie n określa numer na liście składników danej reguły. Semantyczna wartość dla konstruowanej grupy to $$. Na przykład: war:... war + war {$$ = $1 + $3} Ta reguła konstruuje war z dwóch mniejszych grup war połączonych przez znak plus. W tej sekcji $1 i $3 odnoszą się do semantycznych wartości komponentów grup war, które są pierwszym i trzecim symbolem po prawej stronie reguły. Suma jest zapamiętywana w $$ i staje się wartością semantyczną wyrażenia. Jeżeli nie zostanie sprecyzowana akcja dla reguły BISON, przypisze jej domyślną wartość $$ = $1. $n gdzie n jest zerem lub wartością ujemną są dozwolone i odnoszą się do tokenów i grupowań znajdujących się na stosie przed właśnie dopasowywaną regułą. Jednak używanie ich jest bardzo ryzykowne, gdyż trzeba wtedy zapewnić, że taki stos istnieje. Typy danych i wartości w akcjach semantycznych Jeżeli został wybrany jeden typ dla wartości semantycznych, $$ i $n zawsze reprezentują właśnie ten typ. Jeżeli jednak zostało użyte polecenie %union, aby stworzyć różnorodne typy danych, wtedy należy zadeklarować wybór między tymi typami dla wszystkich symboli terminalnych i nieterminalnych, które mają wartość semantyczną. W tym przypadku za każdym razem, gdy korzysta się z $$ lub $n ich typ danych jest zależny od symbolu, do którgo odwołuje się w regule: war:... war + war {$$ = $1 + $3} W powyższym przypadku, jako że korzystamy z tego samego symbolu war, wiadomo, że $$, $1 i $3 są tego samego typu. W innym razie można sprecyzować, o jaki typ danych chodzi podczas odwoływania się do wartości poprzez dodanie <typ> zaraz po znaku $ na początku odniesienia. Na przykład, jeżeli została stwożona unia: %union { int itype double dtype } Należy napisać $<itype>1, aby odwołać się do int lub $<dtype>2, aby odwołać się do double. (c) Karolina Nurzyńska Page 7
8 Akcje semantyczne w środku reguł Czasami może być użytecznym dodanie akcji w środku reguły. Takie akcje tworzy się w ten sam sposób, ale są one wykonywane nim parser rozpozna następne składniki. Mogą one odnosić się do składników poprzedzających wykorzystując $n, ale nie do następujących, bo te nie zostały jeszcze sparsowane. Ważną różnicą między akcją normalną a tą w środku reguły jest problem określenia typu otrzymanego rezultatu. W tym przypadku należy użyć konstrukcji $<...>n do określenia typu danych przy odwoływaniu się do wartości wynikowej akcji. Również w przypadku akcji wewnętrznych nie można określić wartości $$, jest to możliwe tylko w akcji na końcu reguły. 6. Sekcja deklaracji W tej sekcji znajdują się symbole wykorzystane do formułowania reguł gramatyki jak również typy danych dla wartości semantycznych. Wszystkie nazwy tokenów muszą być tutaj zadeklarowane jak również symbole nieterminalne, jeżeli trzeba podać ich typ danych dla wartości semantycznej. Dodatkowo powinna być tutaj zadeklarowana głowa gramatyki po słowie %start. Jeżeli nie zostanie ona określona domyślnie, BISON wybiera pierwsza regułę. a. Nazwy tokenów Podstawowym sposobem określenia nazwy tokena jest: %token name BISON konwertuje tę definicję do makra, z którego można korzystać w funkcji yylex. Dodatkowo można korzystać z %left (łączność lewostronna), %right (łączność prawostronna) oraz %nonassoc zamiast %token do określenia połączeń oraz pierwszeństwa. Można również nadać numeryczne wartości tokenom: %token NUM 30 Nie jest to zalecane, gdyż może wywołać konflikt wartości makr. W przypadku wielu typów najpierw należy określić unie: %union { int itype double dtype } %token <itype> NUM Można również połączyć literał z tokenem: %token arrow => W przypadku deklaracji unii można nadać jej nazwę: %union typ { int itype double dtype } Wtedy unia odpowiada typowi union typ, jeżeli nie jest on zdefiniowany, to przyjmuje wartość domyślną YYSTYPE. Symbole nieterminalne definiuje się tak samo jak terminalne, ale za pomocą: (c) Karolina Nurzyńska Page 8
9 %type <type> name b. Akcje semantyczne przed parsowaniem Czasami może być konieczne wykonanie pewnych akcji inicjalizacyjnych przed rozpoczęciem parsowania. W tym celu korzysta sie z dyrektywy %inicital-action{ kod w C} 7. Konflikty Podczas kompilacji gramatyki do grafu parsera LL(1) bardzo często zdarza się, że dla tej samej sytuacji (kombinacja stanu parsera oraz symbolu na wejściu) możliwych jest więcej niż jedna akcja parsera. Oznacza to, że gramatyka jest niejednoznaczna (ang. ambiguous) w sensie LL(1). Sytuację taką nazywamy konfliktem w gramatyce. Konflikty występują w dwóch rodzajach: konflikty shift/reduce, kiedy możliwa jest zarówno akcja shift jak i reduce, konflikty reduce/reduce, kiedy możliwa jest więcej niż jedna akcja reduce według różnych reguł gramatyki. a. Konflikty shift/reduce Konflikt shift/reduce (s/r) zwykle nie przeszkadza w poprawnej pracy parsera. Na dodatek składnia większości języków wysokiego poziomu z definicji zawiera konstrukcje skutkujące w konfliktach s/r. Sztandarowym przykładem jest tu instrukcja warunkowa, w której człon else jest zwykle opcjonalny. Rozważmy następujący zapis gramatyki: (1)if_stmt : _IF condition _THEN statement (2) _IF condition _THEN statement _ELSE statement condition : operand logical_op operand operand : _ID _INT_LITERAL logical_op : '=' '=' '>' '<' (3) asgn_stmt : _ID '=' _INT_LITERAL '' statement : asgn_stmt (4) if_stmt oraz ciąg wejściowy: if a==1 then if b==2 then c = 1 else c = 2 W momencie napotkania słowa else parser ma do wyboru dwie możliwości: wykonać akcję reduce wg reguły (3) dla ciągu: c = 1 a następnie wg reguły (1) dla ciągu: if b==2 then c = 1 co w konsekwencji wymusi późniejszą redukcję wg reguły (4) dla ciągu: if b==2 then c = 1 oraz redukcję wg reguły (2) dla ciągu: if a==1 then if b==2 then c = 1 else c = 2 W efekcie człon else zostanie dopasowany do zewnętrznej instrukcji if. wykonać akcję shift co w konsekwencji wymusi późniejszą redukcję wg reguły (3) dla ciągów: c = 1 oraz c = 2 a następnie redukcję wg reguły (2) dla ciągu: if b==2 then c = 1 else c = 2 (c) Karolina Nurzyńska Page 9
10 i wreszcie redukcję wg reguły (1) dla ciągu: if a==1 then if b==2 then c = 1 else c = 2 W efekcie człon else zostanie dopasowany do wewnętrznej instrukcji if. Rezultatem oczekiwanym przez użytkownika jest oczywiście dopasowanie członu else do wewnętrznej instrukcji if. Z pomocą przychodzi tutaj reguła zachłanności yacca, zgodnie z którą parser preferuje akcję shift, czyli dlasze gromadzenie tokenów na stosie zamiast akcji reduce. Jedynie w rzadkich przypadkach konflikt s/r zostaje rozstrzygnięty niezgodnie z oczekiwaniami użytkownika. Gramatyki zawierające konfilkty s/r są zjawiskiem normalnym. Dlatego nie będziemy się tutaj zajmować omawianiem sposobów uniknięcia konfliktów s/r. b. Konflikt reduce/reduce O wiele groźniejszy jest konflikt reduce/reduce (r/r). Wystąpienie takiego konfliktu wskazuje na błąd w gramatyce. Jegoskutkiem będą "martwe" tj. nigdy nie redukowane w określonym kontekście reguły. Konflikt r/r zwykle ma ściśle określoną przyczynę, którą należy zlokalizować oraz wyeliminować. Przykład 1. Jedna z najczęstszych przyczyn konfiktów r/r są dublujące się ścieżki możliwych redukcji dla określonych ciągów wejścowych. Rozważmy poniższą gramatykę: %token _ID stmt : fun_call expr fun_call : _ID _ID '(' args ')' args : expr args ',' expr expr : primary expr '+' expr primary '=' expr primary : _ID primary '[' expr ']' Bez reguł dla symbolu stmt nie posiada ona koflików r/r. Jednak dodanie tylko reguł dla stmt powoduje postanie konfliktu r/r. Może się więc wydawać, że te właśnie reguły są bezpośrednią przyczyną konfliku. Prawda jest nieco inna. Konflikt pojawia się, gdyż dla prostego ciągu: a pojawiają się dwie możliwe ścieżki redukcji: oraz Przykład 2. _ID -> primary -> expr -> stmt _ID -> func_call -> stmt Konflikty r/r mogą też pojawiać się w sprawdzonych już gramatykach na skutek dodawania akcji semantycznych. Poniższa gramatyka nie zawiera konfliktu r/r: (c) Karolina Nurzyńska Page 10
11 %token _CONST _ID _INT _DOUBLE decl : type modifier_opt method_decl type data_decl type : _INT _DOUBLE modifier_opt : _CONST method_decl : _ID '(' ')' data_decl : _ID Dodanie akcji semantycznych w regułach dla symbolu decl: decl : type { savetype($1) } modifier_opt method_decl type { savetype($1) } data_decl powoduje pojawienie się konfliktu r/r, którego bezpośrednią przyczyną jest konieczność "redukcji" jednej z reguł-akcji już po odczycie fragmentu odpowiadającego za deklarację typu. Wybierając jedną z akcji, parser wybiera tym samym jedną z reguł dla symbolu decl, a na to jest jeszcze zdecydowanie za wcześnie. Tym sposobem parser w połowie przypadków będzie podejmował błędną decyzję. Usuwanie konfliktów r/r Niestety nie ma jednej uniwersalnej metody na wykrywanie przyczyn oraz usuwanie konfliktów r/r. Każdy konflikt musi być osobno analizowany. Pomocny w tym może plik opisu grafu parsera generowany przez BISON'a w wyniku zastosowania opcji verbose. Wsród najczęściej stosowanych technik wspomagających usuwanie konfliktów r/r można wymienić: ekspansję reguł (ang. rules expanding), przeniesienie elementów analizy z poziomu syntaktycznego na semantyczny (ang. syntax-semantic balance), przeniesienie elementów analizy z poziomu syntaktycznego na leksykalny (ang. lexical-syntax balance). Dalej zostanie przedstawionych kilka przykładowych rozwiązań. (c) Karolina Nurzyńska Page 11
12 Rozwiązanie dla przykładu 1. %token _ID stmt : fun_call expr _ID { if (is_func_id($1)) $$ = func_call($1) else $$ = primary($1) } fun_call : _ID '(' args ')' args : expr args ',' expr expr : primary '+' primary primary '+' expr primary '=' primary primary '=' expr primary : _ID primary '[' expr ']' W celu usunięcia konfliktu dublujące się (na poziomie reguł dla symbolu stmt) reguły: fun_call : _ID oraz expr : primary zostały połączone we wspólną regułę: stmt : _ID Właściwe rostrzygnięcie kontekstu przeniesione zostało z gramatyki do akcji semantycznej, tak więc mamy tu zastosowaną technikę syntax-semantic balance. Usunięcie oryginalnych reguł może pociągać za sobą konieczność ich uzupełnienia w niektórych przypadkach. Taka sytuacja zaistniała w powyższym przykładzie po usunięciu reguły: expr : primary. W założeniu usunięcie reguły miało jedynie zlikwidować ścieżkę produkcji pozwalającą dopasować symbol expr do pojedynczego tokenu _ID. Jednak usunięcie tej reguły powoduje również, iż kolejne reguły: expr : expr '+' expr oraz expr: primary '=' expr tracą swój oryginalny sens. Aby przywrócić im poprzednie działanie, dodane zostały trzy nowe reguły dla symbolu expr. (c) Karolina Nurzyńska Page 12
13 Rozwiązanie dla przykładu 2. %token _CONST _ID _INT _DOUBLE decl : decl_type modifier method_decl decl_type data_decl decl_type : type { savetype($1) } type : _INT _DOUBLE modifier : _CONST method_decl : _ID '(' ')' data_decl : _ID W celu usunięcia konfliktu wykorzystany został fakt, iż obie akcje semantyczne mają dokładnie tą samą treść (co nie jest oczywiste dla yacc'a). To samo dotyczy fragmentów reguł przed akcjami. Wspólne części reguł zostały więc wyłączone pod jeden nowy symbol decl_type. W ten sposób ponownie mamy tylko jedną ścieżkę produkcji aż do momentu, kiedy kontekst pozwala rozróżnić między deklaracją metody a deklaracją danych. Przykład 3. Rozważmy poniższą gramatykę: %token _CONST _STATIC _REG _PUBLIC _PRIVATE _ID decl : scope_opt const_opt id_list memclass_opt scope_opt id_list const_opt : _CONST memclass_opt : _STATIC _REG scope_opt : _PUBLIC _PRIVATE id_list : _ID id_list ',' _ID Zawiera ona konflikt r/r ze względu na dublujące się ścieżki produkcji. Tym razem zamiast analizować dokładnie źródło konfliktu wykonamy ekspansję reguł dla symboli scope_opt, const_opt oraz memclass_opt. W wyniku otrzymamy gramatykę: (c) Karolina Nurzyńska Page 13
14 %token _CONST _STATIC _REG _PUBLIC _PRIVATE _ID decl : id_list _PUBLIC id_list _PRIVATE id_list _CONST id_list _PUBLIC _CONST id_list _PRIVATE _CONST id_list id_list _PUBLIC id_list _PRIVATE id_list _STATIC id_list _STATIC _PUBLIC id_list _STATIC _PRIVATE id_list _REG id_list _REG _PUBLIC id_list _REG _PRIVATE id_list id_list : _ID id_list ',' _ID która oczywiście nadal zawiera konflikty, ale do ich usunięcia wystarczy już tyko eliminacja dublujacych się reguł dla symbolu decl. Po tym kroku otrzymamy już gramatykę bez konfliktów: %token _CONST _STATIC _REG _PUBLIC _PRIVATE _ID decl : id_list _PUBLIC id_list _PRIVATE id_list _CONST id_list _PUBLIC _CONST id_list _PRIVATE _CONST id_list _STATIC id_list _STATIC _PUBLIC id_list _STATIC _PRIVATE id_list _REG id_list _REG _PUBLIC id_list _REG _PRIVATE id_list id_list : _ID id_list ',' _ID Inna metoda usunięcia konfliktu polega na połączeniu obu reguł dla symblu decl. W rezultacie otrzymamy gramatykę dopuszczającą nadzbiór konstrukcji dopuszczanych przez poprzednią wersję. Konstrukcje zabronione, czyli łączenie tokenu _CONST z tokenami _STATIC oraz _REG będą wykrywane w ramach akcji semantycznej. Ponownie zastosowaliśmy więc technikę syntax-semantic balance: (c) Karolina Nurzyńska Page 14
15 Przykład 4. %token _CONST _STATIC _REG _PUBLIC _PRIVATE _ID decl : memclass_opt scope_opt const_opt { check_modifiers($1,$2,$3) } id_list const_opt : _CONST memclass_opt : _STATIC _REG scope_opt : _PUBLIC _PRIVATE id_list : _ID id_list ',' _ID Rozważmy uproszczony fragment gramatyki dla języka C++, a w szczególności dla konstrukcji alokacji pamięci przy pomocy operatora new: ciągu: %token _INT _DOUBLE %token _ID %token _NEW allocation_expr : _NEW '(' new_args ')' expr _NEW expr new_args : expr new_args ',' expr expr : name initializer_opt '(' type_name ')' expr type_name : _INT _DOUBLE _ID name : _ID name '.' _ID initializer_opt : '(' init_args ')' init_args : expr init_args ',' expr Gramatyka zawiera konflikt r/r, którego przyczyną jest istnienie dwóch ścieżek produkcji dla new (a) X() (c) Karolina Nurzyńska Page 15
16 Mianowicie, fragment (a) może zostać dopasowany jako lista argumentów operatora new lub też jako operator rzutu typu (type cast) na obiekcie X. Wszystko zależy od tego, czy identyfikator a jest nazwą obiektu, czy też nazwą typu (zdefiniowana przez typedef). Silniejsza klasyfikacja tokenów w analizatorze leksykalnym pozwoliłaby skutecznie rozstrzygnąć tą sytuację na poziomie gramatyki. Możemy zatem skorzystać z techniki lexical-syntax balance, przez wprowadzenie dodatkowego tokenu _TYPEID i przeniesienie ciężaru rozpoznania pomiędzy nazwą obiektu, a nazwą typu na poziom leksyklany: %token _INT _DOUBLE %token _ID _TYPEID %token _NEW allocation_expr : _NEW '(' new_args ')' expr _NEW expr new_args : expr new_args ',' expr expr : name initializer_opt '(' type_name ')' expr type_name : _INT _DOUBLE _TYPEID name : _ID name '.' _ID initializer_opt : '(' init_args ')' init_args : expr init_args ',' expr Teraz gramatyka nie zawiera konfliktu. Zauważmy jednak, że rozpoznanie identyfikatora, a jako nazwy obiektu lub typu nie jest to możliwe wyłącznie przy pomocy informacji leksykalnej w obu przypadkach mamy do czynienia z takim samym identyfikatorem. Analizator leksykalny będzie więc musiał korzystać z wypracowanych już w trakcie analizy informacji semantycznych (!). Ilustruje to poniższy rysunek. Takie rozwiązanie jest obecnie stosowane w znakomitej większości kompilatorów języka C/C++. Dostępne gramatyki C/C++ w formacie yacc'a zawierają całe grupy tokenów, których rozpoznanie może nastąpić tylko z dodatkowym udziałem informacji semantycznej. Dzięki temu same gramatyki C/C++ zostają uproszczone na tyle, że możliwe jest ich zapisanie w postaci LL(1). (c) Karolina Nurzyńska Page 16
17 Deklaracje: %left %nonassoc %right Pojęcia: akcja semantyczna akcja shift akcja reduce głowa gramatyki gramatyka bezkontekstowa grupowanie konflikty shift/reduce konflikty reduce/reduce Literatura %start %token %type %union $$ $n lokacje token reguły gramatyczne rekurencja lewostronna rekurencja prawostronna symbol nieterminalny symbol terminalny wartośc semantyczna 1. Ch. Donnelly, R. Stallman: BISON, The Yacc-compatible Parser Generator, 16 September 2005, BISON Version M. Forczek: Instrukcja laboratoryjna Yacc, Gliwice, ALDEC-ADT (c) Karolina Nurzyńska Page 17
Generatory analizatorów
Generatory analizatorów Generator analizatora leksykalnego flex ( http://www.gnu.org/software/flex/ ) Generator analizatora składniowego bison ( http://www.gnu.org/software/bison/ ) Idea ogólna Opis atomów
Bardziej szczegółowoAnaliza leksykalna 1. Teoria kompilacji. Dr inż. Janusz Majewski Katedra Informatyki
Analiza leksykalna 1 Teoria kompilacji Dr inż. Janusz Majewski Katedra Informatyki Zadanie analizy leksykalnej Kod źródłowy (ciąg znaków) Analizator leksykalny SKANER Ciąg symboli leksykalnych (tokenów)
Bardziej szczegółowoMetody Kompilacji Wykład 8 Analiza Syntaktyczna cd. Włodzimierz Bielecki WI ZUT
Metody Kompilacji Wykład 8 Analiza Syntaktyczna cd Analiza Syntaktyczna Wstęp Parser dostaje na wejściu ciąg tokenów od analizatora leksykalnego i sprawdza: czy ciąg ten może być generowany przez gramatykę.
Bardziej szczegółowoMetody Kompilacji Wykład 1 Wstęp
Metody Kompilacji Wykład 1 Wstęp Literatura: Alfred V. Aho, Ravi Sethi, Jeffrey D. Ullman: Compilers: Princiles, Techniques, and Tools. Addison-Wesley 1986, ISBN 0-201-10088-6 Literatura: Alfred V. Aho,
Bardziej szczegółowoZadanie analizy leksykalnej
Analiza leksykalna 1 Teoria kompilacji Dr inŝ. Janusz Majewski Katedra Informatyki Zadanie analizy leksykalnej Przykład: We: COST := ( PRICE + TAX ) * 0.98 Wy: id 1 := ( id 2 + id 3 ) * num 4 Tablica symboli:
Bardziej szczegółowoWykład 5. Jan Pustelnik
Wykład 5 Jan Pustelnik Konstruowanie parsera Istnieje kilka podstawowych metod konstrukcji parsera bez nawracania Ze względów wydajnościowych parser bez nawracania jest jedynym sensownym rozwiązaniem (prawo
Bardziej szczegółowo10. Translacja sterowana składnią i YACC
10. Translacja sterowana składnią i YACC 10.1 Charakterystyka problemu translacja sterowana składnią jest metodą generacji przetworników tekstu języków, których składnię opisano za pomocą gramatyki (bezkontekstowej)
Bardziej szczegółowoPodstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1
Podstawy programowania. Wykład Funkcje Krzysztof Banaś Podstawy programowania 1 Programowanie proceduralne Pojęcie procedury (funkcji) programowanie proceduralne realizacja określonego zadania specyfikacja
Bardziej szczegółowoAnaliza leksykalna 1. Języki formalne i automaty. Dr inż. Janusz Majewski Katedra Informatyki
Analiza leksykalna 1 Języki formalne i automaty Dr inż. Janusz Majewski Katedra Informatyki Zadanie analizy leksykalnej Kod źródłowy (ciąg znaków) Analizator leksykalny SKANER Ciąg symboli leksykalnych
Bardziej szczegółowoMetody Kompilacji Wykład 7 Analiza Syntaktyczna
Metody Kompilacji Wykład 7 Analiza Syntaktyczna Parsowanie Parsowanie jest to proces określenia jak ciąg terminali może być generowany przez gramatykę. Włodzimierz Bielecki WI ZUT 2/57 Parsowanie Dla każdej
Bardziej szczegółowoInstrukcja do ćwiczenia P4 Analiza semantyczna i generowanie kodu Język: Ada
Instrukcja do ćwiczenia P4 Analiza semantyczna i generowanie kodu Język: Ada Spis treści 1 Wprowadzenie 1 2 Dane i kod 2 3 Wyrażenia 2 3.1 Operacje arytmetyczne i logiczne.................. 2 3.2 Podstawowe
Bardziej szczegółowoJęzyki formalne i automaty Ćwiczenia 4
Języki formalne i automaty Ćwiczenia 4 Autor: Marcin Orchel Spis treści Spis treści... 1 Wstęp teoretyczny... 2 Sposób tworzenia deterministycznego automatu skończonego... 4 Intuicyjne rozumienie konstrukcji
Bardziej szczegółowoBison - generator analizatorów składniowych
Bison - generator analizatorów składniowych Spis treści: 1. Wprowadzenie 2. Specyfikacja Deklaracje Reguły Procedury pomocnicze 3. Prosty przykład 4. Uruchamianie 5. Rozstrzyganie niejednoznaczności Konflikty
Bardziej szczegółowoRozdział 4 KLASY, OBIEKTY, METODY
Rozdział 4 KLASY, OBIEKTY, METODY Java jest językiem w pełni zorientowanym obiektowo. Wszystkie elementy opisujące dane, za wyjątkiem zmiennych prostych są obiektami. Sam program też jest obiektem pewnej
Bardziej szczegółowoMatematyczne Podstawy Informatyki
Matematyczne Podstawy Informatyki dr inż. Andrzej Grosser Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska Rok akademicki 2013/2014 Gramatyki bezkontekstowe I Gramatyką bezkontekstową
Bardziej szczegółowoPodstawy programowania skrót z wykładów:
Podstawy programowania skrót z wykładów: // komentarz jednowierszowy. /* */ komentarz wielowierszowy. # include dyrektywa preprocesora, załączająca biblioteki (pliki nagłówkowe). using namespace
Bardziej szczegółowoL E X. Generator analizatorów leksykalnych
L E X Generator analizatorów leksykalnych GENERATOR L E X Zadaniem generatora LEX jest wygenerowanie kodu źródłowego analizatora leksykalnego (domyślnie) w języku C; Kod źródłowy generowany jest przez
Bardziej szczegółowo1 Podstawy c++ w pigułce.
1 Podstawy c++ w pigułce. 1.1 Struktura dokumentu. Kod programu c++ jest zwykłym tekstem napisanym w dowolnym edytorze. Plikowi takiemu nadaje się zwykle rozszerzenie.cpp i kompiluje za pomocą kompilatora,
Bardziej szczegółowoTablice (jedno i wielowymiarowe), łańcuchy znaków
Tablice (jedno i wielowymiarowe), łańcuchy znaków wer. 8 z drobnymi modyfikacjami! Wojciech Myszka Katedra Mechaniki i Inżynierii Materiałowej 2017-04-07 09:35:32 +0200 Zmienne Przypomnienie/podsumowanie
Bardziej szczegółowoWybrane narzędzia do tworzenia analizatorów leksykalnych i składniowych w C/C++ by Kapitol Team
Wybrane narzędzia do tworzenia analizatorów leksykalnych i składniowych w C/C++ by Kapitol Team Flex a generatory skanerów C++ 2 sposoby wymuszenia stworzenia skanera w C++ flex -+ flexfile.l użycie %option
Bardziej szczegółowoMETODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02
METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE Wykład 02 NAJPROSTSZY PROGRAM /* (Prawie) najprostszy przykład programu w C */ /*==================*/ /* Między tymi znaczkami można pisać, co się
Bardziej szczegółowoGenerator YACC: gramatyki niejednoznaczne
Plan wykładu Generator YACC: gramatyki niejednoznaczne Wojciech Complak Wojciech.Complak@cs.put.poznan.pl gramatyki jednoznaczne i niejednoznaczne zalety gramatyk niejednoznacznych opisywanie łączności
Bardziej szczegółowoMetody Kompilacji Wykład 3
Metody Kompilacji Wykład 3 odbywa się poprzez dołączenie zasad(reguł) lub fragmentów kodu do produkcji w gramatyce. Włodzimierz Bielecki WI ZUT 2 Na przykład, dla produkcji expr -> expr 1 + term możemy
Bardziej szczegółowoTypy, klasy typów, składnie w funkcji
Typy, klasy typów, składnie w funkcji Typy w Haskell Każde wyrażenie w Haskell posiada zdefiniowany typ. Dzięki temu już na etapie kompilacji kodu następuje sprawdzenie poprawności kodu i zabezpiecza nas
Bardziej szczegółowoSzablony. Szablony funkcji
Szablony Szablony sa mechanizmem ponownego wykorzystania kodu (reuse) W przypadku funkcji ponownie wykorzystany jest algorytm W przypadku klas ponownie wykorzystane sa wszystkie skladowe Deklaracja szablonu
Bardziej szczegółowoWykład 8: klasy cz. 4
Programowanie obiektowe Wykład 8: klasy cz. 4 Dynamiczne tworzenie obiektów klas Składniki statyczne klas Konstruktor i destruktory c.d. 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD
Bardziej szczegółowoWskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.
Część XXII C++ w Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie. Ćwiczenie 1 1. Utwórz nowy projekt w Dev C++ i zapisz go na
Bardziej szczegółowoKONSTRUKCJA KOMPILATORÓW
KONSTRUKCJA KOMPILATORÓW WYKŁAD Robert Plebaniak PLATFORMA PROGRAMOWA LINUX (może nie zawierać LLgen, wówczas instalacja ze strony http://tack.sourceforge.net); WINDOWS (używa się wtedy programu Cygwin,
Bardziej szczegółowoParsery LL(1) Teoria kompilacji. Dr inż. Janusz Majewski Katedra Informatyki
Parsery LL() Teoria kompilacji Dr inż. Janusz Majewski Katedra Informatyki Zadanie analizy generacyjnej (zstępującej, top-down) symbol początkowy już terminale wyprowadzenie lewostronne pierwszy od lewej
Bardziej szczegółowoAnalizator syntaktyczny
Analizator syntaktyczny program źródłowy analizator leksykalny token daj nast. token analizator syntaktyczny drzewo rozbioru syntaktycznego analizator semantyczny kod pośredni tablica symboli Analizator
Bardziej szczegółowo2.2. Gramatyki, wyprowadzenia, hierarchia Chomsky'ego
2.2. Gramatyki, wyprowadzenia, hierarchia Chomsky'ego Gramatyka Gramatyką G nazywamy czwórkę uporządkowaną G = gdzie: N zbiór symboli nieterminalnych, T zbiór symboli terminalnych, P zbiór
Bardziej szczegółowoWskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady
Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4 Dr inż. Dariusz JĘDRZEJCZYK Wskaźniki Dynamiczna alokacja pamięci Przykłady 11/3/2016 AGH, Katedra Informatyki Stosowanej i Modelowania 2 Wskaźnik to
Bardziej szczegółowoMetody Kompilacji Wykład 13
Metody Kompilacji Wykład 13 Prosty Translator Translator dla prostych wyrażeń Schemat translacji sterowanej składnią często służy za specyfikację translatora. Schemat na następnym slajdzie zostanie użyty
Bardziej szczegółowoPodstawy generatora YACC. Bartosz Bogacki.
Podstawy generatora YACC Bartosz Bogacki Bartosz.Bogacki@cs.put.poznan.pl Witam Państwa. Wykład, który za chwilę Państwo wysłuchają dotyczy generatora analizatorów składniowych YACC. Zapraszam serdecznie
Bardziej szczegółowoJak napisać program obliczający pola powierzchni różnych figur płaskich?
Część IX C++ Jak napisać program obliczający pola powierzchni różnych figur płaskich? Na początku, przed stworzeniem właściwego kodu programu zaprojektujemy naszą aplikację i stworzymy schemat blokowy
Bardziej szczegółowoJęzyki programowania zasady ich tworzenia
Strona 1 z 18 Języki programowania zasady ich tworzenia Definicja 5 Językami formalnymi nazywamy każdy system, w którym stosując dobrze określone reguły należące do ustalonego zbioru, możemy uzyskać wszystkie
Bardziej szczegółowoMatematyczne Podstawy Informatyki
Matematyczne Podstawy Informatyki dr inż. Andrzej Grosser Instytut Informatyki Teoretycznej i Stosowanej Politechnika Częstochowska Rok akademicki 2013/2014 Stany równoważne Stany p i q są równoważne,
Bardziej szczegółowoEfektywna analiza składniowa GBK
TEORETYCZNE PODSTAWY INFORMATYKI Efektywna analiza składniowa GBK Rozbiór zdań i struktur zdaniowych jest w wielu przypadkach procesem bardzo skomplikowanym. Jego złożoność zależy od rodzaju reguł produkcji
Bardziej szczegółowoPROE wykład 3 klasa string, przeciążanie funkcji, operatory. dr inż. Jacek Naruniec
PROE wykład 3 klasa string, przeciążanie funkcji, operatory dr inż. Jacek Naruniec Przypomnienie z ostatnich wykładów Konstruktory/destruktory i kolejność ich wywołania w złożonej klasie. Referencja Obiekty
Bardziej szczegółowoWprowadzania liczb. Aby uniknąć wprowadzania ułamka jako daty, należy poprzedzać ułamki cyfrą 0 (zero); np.: wpisać 0 1/2
Wprowadzania liczb Liczby wpisywane w komórce są wartościami stałymi. W Excel'u liczba może zawierać tylko następujące znaki: 0 1 2 3 4 5 6 7 8 9 + - ( ), / $ %. E e Excel ignoruje znaki plus (+) umieszczone
Bardziej szczegółowoGramatyki atrybutywne
Gramatyki atrybutywne, część 1 (gramatyki S-atrybutywne Teoria kompilacji Dr inŝ. Janusz Majewski Katedra Informatyki Gramatyki atrybutywne Do przeprowadzenia poprawnego tłumaczenia, oprócz informacji
Bardziej szczegółowoPo uruchomieniu programu nasza litera zostanie wyświetlona na ekranie
Część X C++ Typ znakowy służy do reprezentacji pojedynczych znaków ASCII, czyli liter, cyfr, znaków przestankowych i innych specjalnych znaków widocznych na naszej klawiaturze (oraz wielu innych, których
Bardziej szczegółowoTranslacja sterowana składnią w generatorze YACC
Translacja sterowana składnią w generatorze YACC Wojciech Complak Wojciech.Complak@cs.put.poznan.pl 1 Plan wykładu zasady implementacji translacji sterowanej składnią w generatorze YACC korzystanie z atrybutów
Bardziej szczegółowoParadygmaty programowania
Paradygmaty programowania Jacek Michałowski, Piotr Latanowicz 15 kwietnia 2014 Jacek Michałowski, Piotr Latanowicz () Paradygmaty programowania 15 kwietnia 2014 1 / 12 Zadanie 1 Zadanie 1 Rachunek predykatów
Bardziej szczegółowo1 Podstawy c++ w pigułce.
1 Podstawy c++ w pigułce. 1.1 Struktura dokumentu. Kod programu c++ jest zwykłym tekstem napisanym w dowolnym edytorze. Plikowi takiemu nadaje się zwykle rozszerzenie.cpp i kompiluje za pomocą kompilatora,
Bardziej szczegółowoJęzyki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.
Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje 1 dr Artur Bartoszewski - Języki C i C++, sem. 1I- WYKŁAD programowania w C++ Typy c.d. 2 Typy zmiennych Instrukcja typedef -
Bardziej szczegółowoInformacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;
Klasy w C++ są bardzo ważnym narzędziem w rękach programisty. Klasy są fundamentem programowania obiektowego. Z pomocą klas będziesz mógł tworzyć lepszy kod, a co najważniejsze będzie on bardzo dobrze
Bardziej szczegółowoPodstawy Kompilatorów
Podstawy Kompilatorów Laboratorium 10 Translacja sterowana składnią w generatorze YACC. Zadanie 1: Proszę napisać program, który dla danej liczby całkowitej j oraz niepustego ciągu liczb naturalnych c
Bardziej szczegółowoInformatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018
Informatyka I Klasy i obiekty. Podstawy programowania obiektowego dr inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2018 Plan wykładu Pojęcie klasy Deklaracja klasy Pola i metody klasy
Bardziej szczegółowoJęzyk C++ zajęcia nr 2
Język C++ zajęcia nr 2 Inicjalizacja Definiowanie obiektu może być połączone z nadaniem mu wartości początkowej za pomocą inicjalizatora, który umieszczany jest po deklaratorze obiektu. W języku C++ inicjalizator
Bardziej szczegółowoWprowadzenie do analizy składniowej. Bartosz Bogacki.
Wprowadzenie do analizy składniowej Bartosz Bogacki Bartosz.Bogacki@cs.put.poznan.pl Witam Państwa. Wykład, który za chwilę Państwo wysłuchają dotyczy wprowadzenia do analizy składniowej. Zapraszam serdecznie
Bardziej szczegółowoUwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)
Uwagi dotyczące notacji kodu! Wyrazy drukiem prostym -- słowami języka VBA. Wyrazy drukiem pochyłym -- inne fragmenty kodu. Wyrazy w [nawiasach kwadratowych] opcjonalne fragmenty kodu (mogą być, ale nie
Bardziej szczegółowoInformatyka I. Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki
Informatyka I Typy danych. Operacje arytmetyczne. Konwersje typów. Zmienne. Wczytywanie danych z klawiatury. dr hab. inż. Andrzej Czerepicki Politechnika Warszawska Wydział Transportu 2019 1 Plan wykładu
Bardziej szczegółowoC++ Przeładowanie operatorów i wzorce w klasach
C++ i wzorce w klasach Andrzej Przybyszewski numer albumu: 89810 14 listopada 2009 Ogólnie Przeładowanie (przeciążanie) operatorów polega na nadaniu im nowych funkcji. Przeładowanie operatora dokonuje
Bardziej szczegółowo29. Poprawność składniowa i strukturalna dokumentu XML
29. i strukturalna dokumentu XML 13 października 2015 1 2 Poprawny składniowo dokument XML powinien być tworzony zgodnie z poniżej przedstawionymi zasadami. Deklaracja XML Powinien zawierać deklarację
Bardziej szczegółowoAlgorytmy i złożoności. Wykład 3. Listy jednokierunkowe
Algorytmy i złożoności Wykład 3. Listy jednokierunkowe Wstęp. Lista jednokierunkowa jest strukturą pozwalającą na pamiętanie danych w postaci uporzadkowanej, a także na bardzo szybkie wstawianie i usuwanie
Bardziej szczegółowoJęzyki formalne i automaty Ćwiczenia 3
Języki formalne i automaty Ćwiczenia 3 Autor: Marcin Orchel Spis treści Spis treści... 1 Wstęp teoretyczny... 2 Algorytm LL(1)... 2 Definicja zbiorów FIRST1 i FOLLOW1... 3 Konstrukcja tabeli parsowania
Bardziej szczegółowo4. Funkcje. Przykłady
4. Funkcje Przykłady 4.1. Napisz funkcję kwadrat, która przyjmuje jeden argument: długość boku kwadratu i zwraca pole jego powierzchni. Używając tej funkcji napisz program, który obliczy pole powierzchni
Bardziej szczegółowoAplikacje w środowisku Java
Aplikacje w środowisku Java Materiały do zajęć laboratoryjnych Klasy i obiekty - wprowadzenie mgr inż. Kamil Zieliński Katolicki Uniwersytet Lubelski Jana Pawła II 2018/2019 Klasa zbiór pól i metod Obiekt
Bardziej szczegółowoStałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane
Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane Stałe Oprócz zmiennych w programie mamy też stałe, które jak sama nazwa mówi, zachowują swoją wartość przez cały czas działania programu. Można
Bardziej szczegółowoC++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów
Operatory są elementami języka C++. Istnieje zasada, że z elementami języka, takimi jak np. słowa kluczowe, nie można dokonywać żadnych zmian, przeciążeń, itp. PRZECIĄŻANIE OPERATORÓW Ale dla operatorów
Bardziej szczegółowoProgram We Kompilator Wy Źródłowy
1. Aho A.V., Ullman J.D. - The Theory of Parsing, Translation and Compiling.1972. 2. Foster J.M. - Automatyczna analiza składniowa. 1976 3. Gries D. - Konstrukcja translatorów dla maszyn cyfrowych, 1984
Bardziej szczegółowoPodstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1
Podstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1 Tablice wielowymiarowe C umożliwia definiowanie tablic wielowymiarowych najczęściej stosowane
Bardziej szczegółowoznajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.
Część XVI C++ Funkcje Jeśli nasz program rozrósł się już do kilkudziesięciu linijek, warto pomyśleć o jego podziale na mniejsze części. Poznajmy więc funkcje. Szybko się przekonamy, że funkcja to bardzo
Bardziej szczegółowoSemantyka i Weryfikacja Programów - Laboratorium 6
Semantyka i Weryfikacja Programów - Laboratorium 6 Analizator leksykalny i składniowy - kalkulator programowalny Cel. Przedstawienie zasad budowy i działania narzędzi do tworzenia kompilatorów języków
Bardziej szczegółowoPodstawy i języki programowania
Podstawy i języki programowania Laboratorium 2 - wprowadzenie do zmiennych mgr inż. Krzysztof Szwarc krzysztof@szwarc.net.pl Sosnowiec, 23 października 2017 1 / 26 mgr inż. Krzysztof Szwarc Podstawy i
Bardziej szczegółowo0.1 Lewostronna rekurencja
0.1 Lewostronna rekurencja Sprawdź czy poniższa gramatyka E jest zgodna z LL(1), tzn. czy umożliwia przeprowadzenie analizy bez powrotu z wyprzedzeniem o jeden symbol. Wyjaśnienie pojęcia LL(1): Pierwsze
Bardziej szczegółowoTechniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.
Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni Wykład 3 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji Abstrakcja funkcyjna Struktury Klasy hermetyzacja
Bardziej szczegółowo7. Pętle for. Przykłady
. Pętle for Przykłady.1. Bez użycia pętli while ani rekurencji, napisz program, który wypisze na ekran kolejne liczby naturalne od 0 do pewnego danego n. 5 int n; 6 cin >> n; 8 for (int i = 0; i
Bardziej szczegółowoWykład 10. Translacja sterowana składnią
Wykład 10 Translacja sterowana składnią Translacja sterowana składnią Z konstrukcjami języków programowania wiąże się pewną informację przez dołączenie atrybutów do symboli gramatyki reprezentujących te
Bardziej szczegółowoPlan wykładu. Kompilatory. Literatura. Translatory. Literatura Translatory. Paweł J. Matuszyk
Plan wykładu (1) Paweł J. Matuszyk AGH Kraków 1 2 tor leksykalny tor syntaktyczny Generator pośredniego Generator wynikowego Hopcroft J. E., Ullman J. D., Wprowadzenie do teorii automatów, języków i obliczeń,
Bardziej szczegółowoZmienne, stałe i operatory
Zmienne, stałe i operatory Przemysław Gawroński D-10, p. 234 Wykład 2 4 marca 2019 (Wykład 2) Zmienne, stałe i operatory 4 marca 2019 1 / 21 Outline 1 Zmienne 2 Stałe 3 Operatory (Wykład 2) Zmienne, stałe
Bardziej szczegółowoUkłady VLSI Bramki 1.0
Spis treści: 1. Wstęp... 2 2. Opis edytora schematów... 2 2.1 Dodawanie bramek do schematu:... 3 2.2 Łączenie bramek... 3 2.3 Usuwanie bramek... 3 2.4 Usuwanie pojedynczych połączeń... 4 2.5 Dodawanie
Bardziej szczegółowoWykład 4: Klasy i Metody
Wykład 4: Klasy i Metody Klasa Podstawa języka. Każde pojęcie które chcemy opisać w języku musi być zawarte w definicji klasy. Klasa definiuje nowy typ danych, których wartościami są obiekty: klasa to
Bardziej szczegółowoSzablony klas, zastosowanie szablonów w programach
Szablony klas, zastosowanie szablonów w programach 1. Szablony klas i funkcji 2. Szablon klasy obsługującej uniwersalną tablicę wskaźników 3. Zastosowanie metody zwracającej przez return referencję do
Bardziej szczegółowoSystemy operacyjne. Laboratorium 9. Perl wyrażenia regularne. Jarosław Rudy Politechnika Wrocławska 28 lutego 2017
Systemy operacyjne Laboratorium 9 Perl wyrażenia regularne Jarosław Rudy Politechnika Wrocławska 28 lutego 2017 Temat obejmuje wykorzystanie wyrażeń regularnych w perlu. Wyrażenia same w sobie są w zasadzie
Bardziej szczegółowoWstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.
Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy Laboratorium 2 Karol Tarnowski karol.tarnowski@pwr.edu.pl A-1 p. 411B Plan prezentacji Komentarze Funkcja printf() Zmienne Łańcuchy
Bardziej szczegółowoZASADY PROGRAMOWANIA KOMPUTERÓW
POLITECHNIKA WARSZAWSKA Instytut Automatyki i i Robotyki ZASADY PROGRAMOWANIA KOMPUTERÓW Język Język programowania: C/C++ Środowisko programistyczne: C++Builder 6 Wykład 9.. Wskaźniki i i zmienne dynamiczne.
Bardziej szczegółowoPakiety i interfejsy. Tomasz Borzyszkowski
Pakiety i interfejsy Tomasz Borzyszkowski Pakiety podstawy W dotychczasowych przykładach nazwy klas musiały pochodzić z jednej przestrzeni nazw, tj. być niepowtarzalne tak, by nie doprowadzić do kolizji
Bardziej szczegółowoCwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR
Cwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR Zadanie polega na napisaniu pierwszego programu w języku C, jego poprawnej kompilacji i wgraniu na mikrokontroler. W tym celu należy zapoznać
Bardziej szczegółowoLABORATORIUM 3 ALGORYTMY OBLICZENIOWE W ELEKTRONICE I TELEKOMUNIKACJI. Wprowadzenie do środowiska Matlab
LABORATORIUM 3 ALGORYTMY OBLICZENIOWE W ELEKTRONICE I TELEKOMUNIKACJI Wprowadzenie do środowiska Matlab 1. Podstawowe informacje Przedstawione poniżej informacje maja wprowadzić i zapoznać ze środowiskiem
Bardziej szczegółowoJava EE produkcja oprogramowania
Java EE produkcja oprogramowania PPJ PODSTAWY PROGRAMOWANIA W JAVIE PODSTAWY JĘZYKA JAVA 1 Warszawa, 2016Z 2 Ogólna charakterystyka języka Java 3 Java 1/2 Język programowania Java został opracowany przez
Bardziej szczegółowoĆwiczenia nr 11. Translatory. Wprowadzenie teoretyczne
J.Nawrocki, M. Antczak, A. Hoffa, S. Wąsik Plik źródłowy: 08cw11-tr.doc; Data: 2009-01-15 09:47:00 Ćwiczenia nr 11 Translatory Wprowadzenie teoretyczne Wiele dokumentów wprowadzających do języków Lex oraz
Bardziej szczegółowoInstytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny Technologiczny Politechnika Śląska
Instytut Mechaniki i Inżynierii Obliczeniowej www.imio.polsl.pl fb.com/imiopolsl @imiopolsl Wydział Mechaniczny Technologiczny Politechnika Śląska Języki programowania z programowaniem obiektowym Laboratorium
Bardziej szczegółowoPARADYGMATY PROGRAMOWANIA Wykład 4
PARADYGMATY PROGRAMOWANIA Wykład 4 Metody wirtualne i polimorfizm Metoda wirualna - metoda używana w identyczny sposób w całej hierarchii klas. Wybór funkcji, którą należy wykonać po wywołaniu metody wirtualnej
Bardziej szczegółowoPodstawy Kompilatorów
Podstawy Kompilatorów Laboratorium 3 Uwaga: Do wykonania poniższych zadań związanych z implementacją niezbędny jest program LEX oraz kompilator. Dla środowiska Linux mogą to być: Darmowa wersja generatora
Bardziej szczegółowoJęzyki i metodyka programowania. Wprowadzenie do języka C
Literatura: Brian W. Kernighan, Dennis M. Ritchie Język Ansi C, Wydawnictwa Naukowo - Techniczne, 2007 http://cm.bell-labs.com/cm/cs/cbook/index.html Scott E. Gimpel, Clovis L. Tondo Język Ansi C. Ćwiczenia
Bardziej szczegółowoDeklaracja struktury w C++
Struktury to złożone typy danych pozwalające przechowywać różne informacje. Za pomocą struktur możliwe jest grupowanie wielu zmiennych o różnych typach w jeden obiekt. Strukturę można nazywać obiektem
Bardziej szczegółowoMake jest programem komputerowym automatyzującym proces kompilacji programów, na które składa się wiele zależnych od siebie plików.
Spis treści 1 Krótkie wprowadzenie do makefile'a 1.1 Typowa reguła programu make 1.2 Zmienne w pliku Makefile 1.3 Zmienne standardowe 1.4 Zmienne automatyczne 1.5 Więcej o regułach 1.5.1 Reguły z wzorcem
Bardziej szczegółowoProgramowanie w języku Python. Grażyna Koba
Programowanie w języku Python Grażyna Koba Kilka definicji Program komputerowy to ciąg instrukcji języka programowania, realizujący dany algorytm. Język programowania to zbiór określonych instrukcji i
Bardziej szczegółowoJĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6
JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM Wykład 6 1 SPECYFIKATOR static Specyfikator static: Specyfikator ten powoduje, że zmienna lokalna definiowana w obrębie danej funkcji nie jest niszczona
Bardziej szczegółowoElżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki
Elżbieta Kula - wprowadzenie do Turbo Pascala i algorytmiki Turbo Pascal jest językiem wysokiego poziomu, czyli nie jest rozumiany bezpośrednio dla komputera, ale jednocześnie jest wygodny dla programisty,
Bardziej szczegółowoUniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania
Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania Celem ćwiczenia jest zapoznanie studentów z najprostszą dynamiczną strukturą
Bardziej szczegółowoKatedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak
Katedra Elektrotechniki Teoretycznej i Informatyki wykład 12 - sem.iii M. Czyżak Język C - preprocesor Preprocesor C i C++ (cpp) jest programem, który przetwarza tekst programu przed przekazaniem go kompilatorowi.
Bardziej szczegółowoProgramowanie obiektowe
Programowanie obiektowe Laboratorium 1. Wstęp do programowania w języku Java. Narzędzia 1. Aby móc tworzyć programy w języku Java, potrzebny jest zestaw narzędzi Java Development Kit, który można ściągnąć
Bardziej szczegółowoPodstawy Kompilatorów
Podstawy Kompilatorów Laboratorium 9 Uwaga: Do wykonania poniższych zadań związanych z implementacją niezbędny jest program LEX, program YACC oraz kompilator języka C. Dla środowiska Linux mogą to być:
Bardziej szczegółowoWykład 5: Klasy cz. 3
Programowanie obiektowe Wykład 5: cz. 3 1 dr Artur Bartoszewski - Programowanie obiektowe, sem. 1I- WYKŁAD - podstawy Konstruktor i destruktor (część I) 2 Konstruktor i destruktor KONSTRUKTOR Dla przykładu
Bardziej szczegółowoWyjątki (exceptions)
Instrukcja laboratoryjna nr 6 Programowanie w języku C 2 (C++ poziom zaawansowany) Wyjątki (exceptions) dr inż. Jacek Wilk-Jakubowski mgr inż. Maciej Lasota dr inż. Tomasz Kaczmarek Wstęp Wyjątki (ang.
Bardziej szczegółowo