Jak Mogę włączyć operatory trójdzielne do algorytmu wspinaczki?

Zastosowałem się do wyjaśnienia podanego w sekcji "prefiks Climbing" na tej stronie, aby zaimplementować ewaluator arytmetyczny przy użyciu algorytmu prefiksu climbing z różnymi uniarnymi prefiksami i binarnymi operatorami infiksu. Chciałbym również włączyć operatorów trójkowych (mianowicie trójkowy operator warunkowy ?:).

Algorytm podany na stronie wykorzystuje następującą gramatykę:

E --> Exp(0) 
Exp(p) --> P {B Exp(q)} 
P --> U Exp(q) | "(" E ")" | v
B --> "+" | "-"  | "*" |"/" | "^" | "||" | "&&" | "="
U --> "-"

Jak mogę włączyć operatory trójdzielne do tej gramatyki?

Author: Alexey Frunze, 2012-12-03

3 answers

Aby być konkretnym, użyję C/C++ / Java ?: jako przykład.

Wydaje się, że w tych językach operator ?: zezwala na dowolne poprawne wyrażenie pomiędzy ? a :, w tym wyrażenia utworzone za pomocą samego ?: oraz wyrażenia utworzone za pomocą operatorów, których pierwszeństwo jest mniejsze niż pierwszeństwo ?:, np. = i , (przykłady: a ? b = c : d, a ? b , c : d, a ? b ? c : d : e).

Sugeruje to, że należy traktować ? i : W dokładnie taki sam sposób jak ( i ) podczas gdy parsowanie wyrażeń. Po przetworzeniu ? expr :, jako całość jest operatorem binarnym. Tak więc, analizujesz ( expr ) i ? expr : w ten sam sposób, ale pierwszy jest wyrażeniem, podczas gdy drugi jest operatorem binarnym (z wyrażeniem w nim osadzonym).

Teraz, gdy ? expr : jest operatorem binarnym (a ?-expr-: b nie różni się od a * b pod względem "binarności"), powinieneś być w stanie go obsługiwać tak jak każdy inny operator binarny, który już obsługujesz.

Osobiście nie Postaraj się podzielić ?: na osobne operatory binarne. W końcu jest operatorem trójdzielnym i musi być połączony z 3 operandami i rozpatrywany jako całość podczas oceny wyrażenia. Jeśli stosujesz podejście opisane w artykule i tworzysz AST, to ?: ma lewy węzeł potomny, prawy węzeł potomny (jak każdy inny operator binarny) i dodatkowo środkowy węzeł potomny.

Pierwszeństwo ?-expr-: jako całość powinna być niska. W C / C++ (a w Javie?) nie jest jednak najniższy. To do ciebie należy decyzja, co chcesz, aby to było.

Do tej pory nie omówiliśmy asocjacji ?:. W C/C++ i Javie, ?-expr-: jest prawostronnie asocjacyjny, podobnie jak operator przypisania =. Ponownie, to do ciebie, aby to lewo-asocjacyjny Lub zachować go prawo-asocjacyjny.

I to:

E --> P {B P}
P --> v | "(" E ")" | U P
B --> "+" | "-" | "*" | "/" | "^"
U --> "-"

Powinno być coś takiego:

E --> P {B P}
P --> v | "(" E ")" | U P
B --> "+" | "-" | "*" | "/" | "^" | "?" E ":"
U --> "-"
 24
Author: Alexey Frunze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-21 03:12:48

Natknąłem się na to pytanie szukając informacji na temat przekształcania operatorów trójkowych w odwrotne notacje Polskie (RPN), więc chociaż nie mam solidnej implementacji do implementacji ?: operatora z pierwszeństwem wspinania się, myślę, że mogę być w stanie dać jakąś wskazówkę do przekształcenia ?: operatora do RPN za pomocą dwóch stosów ... co jest podobne do algorytmu manewrowego na podanej stronie internetowej.

[Edytuj] muszę zaznaczyć, że to, co tu robię, nie jest bardzo wydajny (obie gałęzie operatora trójdzielnego muszą być ocenione), ale aby zademonstrować jak łatwo jest Włączyć Nowy operator (?:) w istniejącym frameworku (kod transformacji RPN) (deklarując ? i : z dwoma najniższymi poziomami pierwszeństwa).

Chcę zacząć od kilku przykładów jak wyrażenia z ?: są przekształcane do RPN na podstawie mojego parsera... Dodaję dwa operatory zamiast tylko jednego, ? i :, ale nie sądzę, aby robi dużą różnicę, ponieważ : i ? będą zawsze połączone razem (jest po prostu wygodniejsze, że RPN i oryginalne wyrażenie mają taką samą liczbę tokenów). W przykładach można zobaczyć, jak to działa.

Przykład 1: 1 + ((0+1) ? 2 : 3 + 8) + 4

RPN: 1 0 1 + 2 3 8 + : ? + 4 +

Teraz Oceń RPN.

1-wpychanie pierwszych elementów do stosu i natkniemy się na pierwszy binarny operator:

1 0 1 i operatorem +, dodajemy 2 górne elementy, zamieniając stos na 1 1

2 - następnie wciśnięcie trzech kolejnych elementów i natkniemy się na drugi operator binarny:

1 1 2 3 8 + ------> 1 1 2 11

3 - Teraz mamy : i ?. To faktycznie mówi nam, aby wybrać albo następczą gałąź (2nd najwyższy element na szczycie stosu, 2) lub alternatywna gałąź (najwyższy element na stosie, 11), oparta na predykacie (trzeci najwyższy element na stosie, 1). Ponieważ predykatem jest 1 (prawda), wybieramy 2 i odrzucamy 11. Parser wyskakuje z 3 elementów (predykat / konsekwencja / alternatywa) i odchyla wybrany (w tym przypadku następująca gałąź), więc stos staje się

1 2

4 - zużywają pozostałe elementy:

1 2 + ------> 3

3 4 + ------> 7


Przykład 2: 1 + ((0+0+0?0:0) ? 2 : (3 + 8)) + 4

RPN: 1 0 0 + 0 + 0 0 : ? 2 3 8 + : ? + 4 +

Ocena:

Początek:

1 0 0 + 0 + 0 0 : ? 2 3 8 + : ? + 4 +

Po dodaniu 0 do 0:

1 0 0 + 0 0 : ? 2 3 8 + : ? + 4 +

Po dodaniu 0 do 0:

1 0 0 0 : ? 2 3 8 + : ? + 4 +

Po pierwszym :? wybiera 0:

1 0 2 3 8 + : ? + 4 +

Po dodaniu 3 i 8:

1 0 2 11 : ? + 4 +

Po ?: wybiera 11:

1 11 + 4 +

Po dodaniu 1 i 11:

12 4 +

Wreszcie:

16


Może to sugerować, że możliwe jest przekształcenie wyrażenia z ?: w odwrotną notację polską. Jak mówi strona RPN i AST są równoważne w tym, że mogą być przekształcane w i od siebie, operator trójdzielny powinien być w podobny sposób zaimplementowany.

Jedną z rzeczy, które należy zrobić, wydaje się być" priorytet " (lub pierwszeństwo) operatora ?:. I rzeczywiście natknąłem się na to podczas próby transformacji RPN. Podałem znaki zapytania i dwukropki najniższy priorytet:

Jak widać z powyższego przykładu, gdy mamy zamiar wykonać ?:, gałąź pierwszeństwa i alternatywna gałąź i predykat powinny być już ocenione, dając w rezultacie pojedynczą liczbę. Jest to gwarantowane przez pierwszeństwo.

Poniżej znajduje się tabela priorytetów (pierwszeństwo).

! ~ > * / % > + - > & > ^ > | > && > || > ? > :

? i : mają najmniejszy priorytet, czyli w wyrażeniach takich jak 1?2+3:4+5, ? and : will never take operandów wokół nich.

? poprzedza :, Aby : pojawiło się przed ? w RPN. W moim rozumieniu jest to tylko wybór projektu, ponieważ : i ? nie muszą nawet dzielić się na dwa operatory w pierwszej kolejności.

Mam nadzieję, że to pomoże..

Numer referencyjny: http://en.cppreference.com/w/cpp/language/operator_precedence

 5
Author: Tommy Chen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-05 03:47:18

Zdefiniuj dwukropek, aby miał niższy priorytet niż znak zapytania. Innymi słowy, a ? b: c będzie parsowane jako (a ? B): c. pozwala to parserowi konstruować (if/then/empty-else) węzeł abstrakcyjnej składni, który następnie byłby obsługiwany przez ": operator" w celu dostarczenia żądanego komponentu else.

Relacje pierwszeństwa również zachowują zmienność operatora. Np. a ? b: c ? D: E parses as (a ? b): (c ? d): e, jak można się spodziewać.

Hope this pomaga.

 3
Author: Samuel A. Falvo II,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-10 08:15:01