Jaka jest różnica między składnią a semantyką?


87

Zawsze uważałem, że odwołanie się do składni języka jest tym samym, co odwołanie się do semantyki języka. Ale zostałem poinformowany, że najwyraźniej tak nie jest. Co za różnica?



6
„Bezbarwne zielone pomysły śpią wściekle” jest składniowe, ale nie ma sensu semantycznego. Zobacz en.wikipedia.org/wiki/Colorless_green_ideas_sleep_furiously
CesarGon

+1 za zadanie tego pytania. Zastanawiałem się tak samo, byłem zbyt leniwy, by przeszukiwać internet, i oczywiście nigdy o to nie prosiłem.
KK.

Mniej więcej powiedziałbym ... Semantyka to rodzaje instancji, ich relacje z innymi instancjami i gwarancje, które istnieją między nimi. Składnia jest sposobem deklarowania tych rzeczy za pomocą ciągów znaków. Mniej więcej.
Dehbop

Odpowiedzi:


106

Semantyka ~ Znaczenie

Składnia ~ Reprezentacja symboliczna

Tak więc dwa programy napisane w różnych językach mogłyby zrobić to samo (semantyka), ale symbole użyte do napisania programu byłyby inne (składnia).

Kompilator sprawdzi Twoją składnię (błędy w czasie kompilacji) i wyprowadzi semantykę z reguł językowych (np. Odwzorowanie składni na instrukcje maszynowe), ale nie znajdzie wszystkich błędów semantycznych (błędów w czasie wykonywania, np. Obliczeń zły wynik, ponieważ kod mówi: dodaj 1 zamiast dodać 2).


2
Sprawdzanie błędów nie jest kryterium rozróżniania składni i semantyki. Kompilator może i musi diagnozować zarówno błędy składniowe (jak brakujący średnik), jak i błędy semantyczne (na przykład, x + ygdy nie ma odpowiedniego +operatora dla tych operandów). Dodanie 1 zamiast 2 jest tym, co nazwałbym błędem logicznym .
Keith Thompson

3
@ Keith - ale logika (jak w „błędzie logicznym”) jest semantyką. Kompilator może wykonać pewne kontrole semantyczne - szczególnie sprawdzanie typu - więc zgadzam się, że kompilatory nie tylko znajdują błędy składniowe, ale Chris powiedział tylko: „ nie znajdzie wszystkich błędów semantycznych”, co nie oznacza, że ​​„nie można znajdź dowolny ”.
Steve314,

1
@ Steve314: Uzgodniony. Ale jeśli chcesz dokonać wyraźnego rozróżnienia między błędami, które kompilator musi wykryć, a błędami, których nie musi wykrywać, to uważam, że „semantyczny” vs. „logiczny” to dobry sposób na wyrażenie tego rozróżnienia.
Keith Thompson

4
@KeithThompson Faktycznie, w teorii, kompilator lub interpreter na język z wystarczająco silnego i potężnego (tj zależnej ) systemu typu można sprawdzić dowolną właściwość kodu (modulo wstrzymaniem problemu, jeśli ma to zastosowanie), a więc łamanie błędy semantyczne w „sprawdzalne” i „nie do sprawdzenia” nie ma w ogóle sensu.
Ptharien's Flame,

@ Ptharien'sFlame Po prostu wyciągnę na chwilę tę dyskusję z chmur, podkreślając „teoretycznie” część twojego oświadczenia. W praktyce wymuszanie semantyki w kodzie wymaga dodatkowej składni, aby dać kompilatorom wskazówki co do funkcjonalności. Dodatkowe sprawdzenie semantyczne stanowi koszt (tj. Złożoność / czytelność). Stwierdzenie, że język może być wystarczająco silny, aby sprawdzić wszystkie błędy semantyczne, jest jak stwierdzenie, że system prawny może być wystarczająco doskonały, aby zapobiec wszelkim przestępstwom. Osobiście wolę wolność od bezpieczeństwa, ale to sprawia, że ​​jest to temat „religijny”.
Evan Plaice,

35

W rzeczywistości nie ma dwóch poziomów, ale trzy:

  • poziom leksykalny: sposób łączenia znaków w celu uzyskania elementów językowych ( ii fprodukuje if)
  • Poziom składniowej: jak elementy językowe są łączone w celu wytworzenia wyrażeń językowych ( if, (, 42, ==, answeri )produkuje warunkową deklarację)
  • poziom semantyczny: w jaki sposób wyrażenia językowe są konwertowane na instrukcje CPU w celu utworzenia znaczenia (instrukcja warunkowa umożliwia wykonanie jednej gałęzi lub drugiej w zależności od wyniku wyrażenia boolowskiego)

10
Rozdzielenie etapów leksykalnego i parsowania jest całkowicie sztuczne, jest jedynie optymalizacją. I jest kilka języków, w których nie zdefiniowano żadnego skończonego płaskiego zestawu leksemów - ale nadal istnieje jasno zdefiniowana składnia. Wolałbym więc zdefiniować leksemy jako część składni, nie jest to osobna jednostka.
SK-logic

@ SK-logic: W wielu językach podano listę autoryzowanych lub zabronionych leksemów tworzących nazwy zmiennych. Tak więc separacja ma sens.
mouviciel

5
@mouviciel, ma to sens tylko jako optymalizacja - w przeciwnym razie będziesz miał tylko ValidIdentifierterminal, który można by zdefiniować jako coś podobnego ![AnyKeyword] [Identifier](używam tutaj notacji podobnej do PEG). Nie potrzebujesz osobnej przepustki leksykalnej dla takiego języka. Zobacz na przykład parsery C ++ oparte na GLR.
SK-logic

2
@EvanPlaice, o czym ty mówisz? Chodzi mi o to, że leksyk nie jest konieczny (i faktycznie ogranicza twój język), a nie parsowanie .
SK-logic

1
@ SK-logic Wydaje mi się, że czytam twój komentarz oznaczający przeciwieństwo tego, co zamierzałeś. Myślałem, że mówisz o przypadkach, w których potrzebny jest tylko leksykon - na przykład w językach „zwykłych” lub „pozbawionych kontekstu”. W językach wyższego poziomu leksykon może nie być konieczny, ale zapewnia szybki sposób na sprawdzenie poprawności składni jednoprzebiegowej. Całkowicie się zgadzam, że w wielu przypadkach korzystne byłoby wyłączenie lub całkowite wyeliminowanie etapu leksykalnego.
Evan Plaice,

18

Wyjaśnię ci to na prostym przykładzie w języku ENGLISH:

The glass drank Ben

Jest stwierdzeniem poprawnym pod względem składniowym. Ma rzeczownik, czasownik itp.

Ale semantycznie jest błędne, ponieważ to stwierdzenie nie ma żadnego możliwego do wyobrażenia ani poprawnego znaczenia.


15

Semantyka opisuje logiczne byty języka programowania i ich interakcje. Składnia określa sposób ich wyrażania w znakach.

Na przykład koncepcja arytmetyki wskaźnika jest częścią semantyki języka C; sposób, w jaki operatory +i -mogą być używane do wyrażania operacji wskaźnika, jest częścią jego składni.

Czasami dwa języki dzielą część semantyki, ale składnia jest bardzo różna (np. C # i VB.NET - oba używają typów wartości i typów referencji, ale znaki, które wpisujesz, aby je zdefiniować, są różne); w innych przypadkach dwa języki są podobne pod względem składniowym, ale semantyka się nie zgadza (rozważmy Java vs. JavaScript, gdzie podobieństwa często mylą początkujących).


Zatem „paradygmaty” są związane z semantyką? Mam na myśli, że paradygmat jest zbiorem powiązanych ze sobą semantyki?
Gulshan,

1
@Gulshan, paradygmat jest znacznie szerszą koncepcją niż tak sformalizowana sprawa jak semantyka. Paradygmat może obejmować semantykę, ale jest to raczej metodologia, a nawet szerzej filozofia.
SK-logic


5

Nie określiłeś, czy odwołujesz się tylko do języków programowania, czy też do ogólnych języków używanych w programowaniu, więc moja odpowiedź dotyczy języków danych (takich jak XML, RDF, systemy typów danych itp.):

Brian L. Meek w swoich siedmiu złotych zasadach tworzenia niezależnych od języka standardów (1995) pisze, że „składnia jednego języka może być semantyką innego” . Odwołuje się do słów „składnia” i „semantyczny” używanych w opisie danych: więc jeśli natkniesz się na te słowa w specyfikacji jakiegoś formatu danych, lepiej zastąp oba słowa słowem „Potrzebie”, aby wyjaśnić, że musisz wypracować znaczenie dla siebie.

Zależność między składnią a semantyczną, przynajmniej w dokładnie określonych danych, można lepiej opisać terminem „kodowanie” . Semantyczny jest zakodowany w składni. Ponieważ nagrania można zagnieżdżać, składnia jednego języka jest semantyką drugiego. Jeśli ktoś wykracza poza sferę danych, zagnieżdżanie może być praktycznie nieskończone, jak opisuje Umberto Eco jako „nieograniczona semioza”.

Aby podać przykład:

  • Składnia XML (z tymi wszystkimi nawiasami) to składnia z XML Infoset (drzewem abstrakcyjnym) jako semantycznym.
  • Infoset XML jako składnia może wyrażać rekord w pewnym formacie danych XML jako semantyczny, na przykład dokument RDF / XML, który koduje wykres RDF.
  • Wykres RDF (materiał z odniesieniami do URI) jako składnia koduje graf zasobów abstrakcyjnych jako semantyczny.
  • Wykres zasobów abstrakcyjnych jako składnia koduje model konceptualny jako semantyczny.

Ludzie zwykle zatrzymują się na pewnym poziomie i traktują to jako semantyczne, ale ostatecznie nie ma ostatecznej semantycznej, chyba że jakaś istota ludzka interpretuje dane w jego umyśle. Gdy tylko spróbujemy wyrazić semantyczny w postaci danych, staje się on składnią.


4

Jeśli można to opisać w BNF (Backus-Naur Form) lub czymś podobnym, to jego składnia. Jeśli nie, to nie jest.

Z drugiej strony semantyka dotyczy znaczenia programu (lub innej części kodu źródłowego).

A czasami linia między nimi może być rozmyta.

Jednym ze sposobów zrozumienia tego rozróżnienia jest przyjrzenie się rodzajom błędów, które występują, gdy składnia lub semantyka programu jest nieprawidłowa.

Błąd składniowy to błąd w dopasowaniu kodu źródłowego do gramatyki języka, na przykład brak średnika, w którym jest wymagany.

Błąd semantyczny to niespełnienie innych wymagań językowych (co na przykład C nazywa „ograniczeniami”); przykładem może być pisanie x + ygdzie xi ysą niezgodnych typów. Gramatyka języka informuje, że dodatek wygląda something + something, ale nie jest wystarczająco potężny, aby wyrazić wymagania dotyczące typów lewego i prawego operandu.

(Błędy logiczne, takie jak użycie 1, gdzie 2 byłoby poprawne, na ogół nie jest wykrywalne przez kompilator - chociaż w niektórych przypadkach kompilator może ostrzec o wątpliwym kodzie).


0

Składnia jest tym, co mówią symbole (leksykalne). Znaczenie semantyki.

Rozważać:

C #: condition ? true_value : false_value
VB.NET: If(condition, true_value, false_value)
- Inna składnia, ta sama semantyka.

C #: left_value / right_value
VB.NET: left_value / right_value
- Ta sama składnia, inna semantyka (dla liczb całkowitych).


0

Składnia to gramatyczne uporządkowanie słów w zdaniu, tj. Kolejność słów.

(Angielski) „ cat dog boy ” i (programowanie) „ hi.5nie są poprawne składniowo.

(Angielski) „ cat hugs boy ” i (programowanie) „* 3.2 * 5 *” jest poprawne pod względem składniowym.

Semantyka statyczna to, czy stwierdzenia poprawne pod względem składniowym mają jakieś znaczenie.

(Angielski) „ I are big ” (programowanie) (python) „ 3 +„ hi ”jest poprawne składniowo, ale ma statyczny błąd semantyczny.

Semantyka jest znaczeniem związanym z poprawnym składniowo ciągiem symboli bez statycznego błędu semantycznego, tzn. Zdanie jest poprawne składniowo i semantycznie, ale jego znaczenie może nie być zgodne z przeznaczeniem.

(Polski) „ Latanie samolotami może być niebezpieczne ” może mieć dwa znaczenia, tzn. Latanie samolotami może być niebezpieczne lub samoloty, które latają, mogą być niebezpieczne.

(Programowanie) ”komputer nie wygeneruje żadnych komunikatów o błędach, ale nie zrobi tego, co mu kazałeś; zrobi coś innego.

Źródło : MIT 6.00.1


-2
  1. Składnia odnosi się do formalnych zasad rządzących konstruowaniem prawidłowych instrukcji w języku. Semantyka odnosi się do zestawu reguł, które nadają sens stwierdzeniu.

  2. Błędy spowodowane składnią występują w programie, gdy ruele języka programowania są naruszane lub niewłaściwie używane. Błędy wynikające z semantyki występują w programie, gdy instrukcje nie mają znaczenia.

  3. Porządek słów jest podstawową zasadą składni, a ci, którzy próbują zrozumieć, co jest napisane, używają składniowych wskazówek porządku słów, aby pomóc nadać strukturę i znaczenie zdaniu. Semantyka to indywidualna interpretacja znaczenia „zdania” na podstawie ich wcześniejszej wiedzy. Dlatego zdanie, które pozornie nie ma sensu składniowego, może mieć znaczenie przy stosowaniu sygnałów semantycznych.

  4. Składnia dotyczy tylko tego, co jest poprawne językowo i gramatycznie. Semantyka wymaga wcześniejszej wiedzy, która wykracza poza wszystko, co jest specyficzne dla języka.

  5. Zdanie „Napoje mleczne dla niemowląt” nie ma znaczenia składniowego, ale przez semantykę większość ludzi interpretuje to jako „Napoje mleczne dla niemowląt”, ponieważ nasza wcześniejsza wiedza mówi nam, że dziecko pije mleko, i dlatego możemy znaleźć znaczenie na podstawie słowa kluczowe.


1
Głosuj za wszystkim oprócz ostatniego (punkt 5)
nawfal

-2

Składnia i semantyka jest jak strategia i taktyka lub lewa i prawa .

Nie są to tak naprawdę niezależne uniwersalne pojęcia, ale pokrewna para słów, które w określonym kontekście wskazują przeciwne kierunki. Ale to samo, co strategia na jedną skalę, to taktyka na innej.

Więc jeśli piszesz kod w języku, składnia jest językiem, którego używasz, a pożądanym zachowaniem jest semantyka. Ale jeśli wdrażasz lub omawiasz kompilator dla tego języka, wówczas składnia to gramatyka i być może system piszący oraz semantyka, wszystko na niej oparte. I tak dalej.


4
Co to za ezoteryczny BS? Jak w lewo i prawo? Lubisz strategię i taktykę? Może nawet jak Yin i Yang, Bóg i diabeł, Harry i Voldemort?
JensG

-3

Komputer rozumie składnię, semantykę rozumie człowiek.

Kompilator / interpreter nie przejmuje się odrobiną twojego projektu, aw każdym kodzie skompilowanym do poziomu maszyny trudno byłoby wydedukować projekt. Deweloperzy dbają o projekt, ponieważ dobry projekt polega na zmniejszaniu złożoności poprzez wyodrębnianie złożonych zachowań i interakcji, a różne rodzaje problemów mogą mieć różną semantykę. Wybór języka zależy w dużej mierze od tego, jak łatwo i wydajnie można użyć semantyki w jego składni.


„Składnia jest tym, co rozumie komputer, semantyka jest tym, co rozumie człowiek” to wielkie uproszczenie. Ludzie też rozumieją składnię, a komputery rozumieją niektóre rodzaje semantyki.
CesarGon,

4
Po prostu źle. Istnieją języki o identycznej składni i zupełnie innej semantyce (np. Chętna i leniwa wersja tego samego języka), są języki praktycznie bez składni i bardzo bogatą i zmienną semantyką (np. Forth i Lisp). Semantyka to sposób, w jaki kompilator interpretuje Twój język. Człowiek może nic o tym nie wiedzieć i nadal być w stanie używać języka.
SK-logic

@ SK-logic, zaprzeczasz sobie. Jeśli różne semantyki można wyrazić za pomocą tej samej składni, to oczywiście semantyka nie jest zawarta w składni, ale raczej w sposobie jej użycia. Jednak kompilator ma tylko składnię do pracy. Nie interpretuje semantyki, interpretuje składnię. Nie kompiluje tej samej składni inaczej w zależności od tego, co chciał powiedzieć deweloper, ale tylko na podstawie tego, co napisał. Semantyka jest dostarczana przez programistę i ma dla niego znaczenie.
kylben

3
@ Kylben, nie przeczę sobie, ponieważ nigdy nie powiedziałem, że składnia i semantyka są nawet powiązane. A kompilator nic nie robi ze składnią zaraz po etapie analizy - kompilator implementuje semantykę . Oczywiście twoja interpretacja terminologii jest błędna. Przeczytaj to na początek: en.wikipedia.org/wiki/Denotational_semantics
SK-logic

3
Mówisz o znaczeniu programu , który jest „semantyką”, tak jak zdefiniowałby to językoznawca. Ale w informatyce semantyka jest znaczeniem języka , a nie konkretnego programu.
SK-logic

-3

Bardzo krótki przykład z „zwykłym c”:

void main()
{
  int a = 10;
  int x = a - 1;
  int y = - 1;

  printf("x = %i", x);
  printf("y = %i", y);
    getch();
}

W tym przykładzie składnia tokenu „-” jest taka sama, ale ma inne znaczenie („semantyczne), w zależności od tego, gdzie jest używane.

W przypisaniu „x” „-” oznacza operację „odejmowania”, w przypisaniu „y” „-” oznacza operację „znaku ujemnego”.


3
Błędny. Oba -operatory są tym samym tokenem , ale różnią się składniowo , ponieważ są używane w różnych kontekstach. 0 - 1dopasowuje regułę składni additive-expression: additive-expression - multiplicative-expression, a - 1dopasowuje regułę składni unary-expression: unary-operator cast-expression(odniesienie: standard C99).
Keith Thompson

@Keith Thompson: Nie trafiłeś w sedno. Jest pytaniem semantycznym lub składniowym, a nie pytaniem o standardy C. Norma jest słuszna, ale moja odpowiedź miała na celu wyjaśnienie pojęcia, a nie dosłownie standardu. To jest jak pytanie „Kapitan Kirk” kontra „Dr Spock”. Pozdrawiam ;-)
umlcat

Nie zgadzam się. Różnica między tymi dwoma -operatorami jest składniowa, a nie tylko semantyczna (chociaż mają one również inną semantykę). Składnia jest zdefiniowana przez gramatykę języka, a dwa operatory są określone w różnych sekcjach gramatyki. Patrz projekt N1570 , sekcja 6.5.3 dla operatorów jednoargumentowych i 6.5.6 dla operatorów addytywnych. (BTW, jeśli zamierzasz użyć przykładu C, prawdopodobnie powinien być poprawny; void main()powinien być int main(void), i brakuje cię, #include <stdio.h>i jakikolwiek nagłówek deklarujegetch
Keith Thompson

Aby wyjaśnić tę kwestię, składnia to nie tylko sekwencja tokenów, ale także sposób, w jaki te tokeny tworzą większe konstrukcje. Kompilator zazwyczaj ma analizator leksykalny (tokenizer) i analizator składni jako odrębne komponenty; oba dotyczą składni.
Keith Thompson
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.