11

Jeśli mamy wyrażenie:lewej asocjacyjne operatorzy vs operatorzy prawym asocjacyjne

a $ b @ c 

$ jest operatorem lewej asocjacyjne, @ jest tuż-asocjacyjne. Mają takie samo pierwszeństwo.

W jaki sposób analizowane jest to wyrażenie? Jako (a $ b) @ c lub jako a $ (b @ c)?

+1

Rzeczywisty przykład C lub C++ prawdopodobnie byłby bardziej przejrzysty. – chris

+1

W jakim języku? Twój własny? Cóż, nie rób tego! Jest to niejednoznaczna gramatyka, która nie ma jednego sposobu rozwiązania. – Pubby

+0

Jest określona przez kompilator, jak analizować drzewo gramatyczne. Reading << Zasady, techniki i narzędzia kompilatorów >> pomogą ci bardzo. – MYMNeo

Odpowiedz

6

Operatory o tym samym priorytecie są albo stowarzyszone, albo wszystkie stowarzyszone, więc problem nie występuje.

+1

Dobra, powinienem był się upić, żeby o to zapytać. Ponieważ każdy język ma różne priorytety, więc nie powinno być żadnych standardów. Decydują o tym twórcy kompilatorów. A sprytny projektant zrobiłby tak, jak powiedział Dipstick. –

+3

@RobertBean, na szczęście decydują o tym projektanci języków i są znormalizowane dla każdego języka. Gdyby to zostało do implementatora kompilatora, nigdy nie można by napisać kodu przenośnego. –

10

To jest doskonałe pytanie. Podczas gdy Dipstick ma rację, że w wielu językach definiuje się priorytety i powiązania operatorów, aby uniknąć takiego problemu, istnieją języki, w których może zaistnieć taka sytuacja.

Haskell jest takim językiem. Pozwala na zdefiniowanie własnych operatorów infiksów i ich priorytetów (liczba całkowita od 0 do 9) i asocjatywności (lewo, prawo, nie). Łatwo jest stworzyć warunki konieczne dla scenariusza opisanego:

infixl 5 $$ 
($$) :: Int -> Int -> Int 
a $$ b = a + b 

infixr 5 @@ 
(@@) :: Int -> Int -> Int 
a @@ b = a * b 

a następnie sytuację sam:

uhoh = 1 $$ 2 @@ 3 

Skutkuje to tym komunikatem o błędzie:

Precedence parsing error 
    cannot mix `$$' [infixl 5] and `@@' [infixr 5] in the same infix expression 

Oczywiście Haskell'a rozwiązanie - przerwanie z błędem analizy - nie jest jedynym sposobem rozwiązania tego problemu, ale z pewnością jest to uzasadnione.

Aby uzyskać więcej informacji o analizie operatorów w Haskell, zobacz punkt 4.4.2 z the Haskell report.