분로 장 알고리즘의 우선 순위


10

나는 통해하고 있어요 차량 기지 알고리즘 위키 피 디아에 의해 설명 된대로.

연산자를 처리 할 때 알고리즘에 대한 설명은 다음과 같습니다.

토큰이 연산자 인 o1이면 다음을 수행하십시오.

운영자 스택 맨 위에 운영자 토큰 o2가 있고

o1 is left-associative and its precedence is less than or equal to
that of o2, or

o1 is right associative, and has precedence less than that of o2,

그런 다음 운영자 스택에서 출력 큐로 o2를 팝하십시오.

o1을 운전자 스택에 밀어 넣습니다.

그러나 다음 예제를 제공합니다.

입력: sin max 2 3 / 3 * 3.1415

알고리즘이 /토큰에 도달 할 때 발생하는 설명은 다음과 같습니다.

Token |        Action       |   Output (in RPN) |   Operator Stack
...
/     | Pop token to output | 2 3 max           | / sin 
...

그들은 기능 토큰을 진열 max오프 stack와에 넣어 queue. 그들의 알고리즘에 따르면, 이것은 함수 토큰이 연산자이고 연산자보다 우선 순위가 낮다는 것을 의미하는 것 같습니다 /.

이것이 사실인지 아닌지에 대한 설명은 없습니다. 따라서 Shunting-yard알고리즘의 경우 함수의 우선 순위는 무엇입니까? 함수가 오른쪽 또는 왼쪽으로 연결되어 있습니까? 아니면 위키 백과가 불완전하거나 정확하지 않습니까?

답변:


5

직접 답변은 단순히 함수가 연산자가 아니라고 생각합니다. 링크 한 페이지에서 :

토큰이 함수 토큰이면 스택으로 푸시하십시오.

함수 사례 (접두사 접두사)가 연산자 사례 (접두사 접두사)보다 훨씬 단순하기 때문에 이것이 전부입니다.

후속 질문 : 우선 순위와 연관성 개념은 여러 개의 중위 연산자가있는 표현식의 상속 모호성 때문에 필요합니다. 함수 토큰은 이미 접두사 표기법을 사용하고 있으므로 문제가 없습니다. 당신은 알 필요가 없습니다 여부 sin또는 max파악하는 방법 "높은 우선 순위"가 max필요 먼저 평가하기를, 토큰 순서에서 이미 명확합니다. 그렇기 때문에 컴퓨터는 시작 / 접두사 표기법을 선호하며, 접두사를 접두사 / 접두사로 변환하는이 알고리즘을 사용합니다.

괄호가 없을 때 함수의 인수가 시작하고 끝나는 위치에 대해 어떤 종류의 규칙이 필요하므로 함수가 연산자보다 "우선 순위를 갖거나"반대로 말할 수 있습니다. 그러나 인 픽스 연산자와 달리 모든 기능에 대해 일관된 단일 규칙만으로도 컴포지션을 완전히 명확하게 만들 수 있습니다.


그들의 알고리즘은 정확하다. 잘못된 예입니다. 접두사 표기법은 함수를 감싸는 괄호를 포함해야합니다.sin( max( 2 3) / 3 * 3.1415)
MirroredFate

내가 그것을 부정확하게 부르는지 확실하지 않지만, 이것은 모든 함수 호출 주위에 괄호와 쉼표가 필요한 언어를 선호하는 강력한 주장입니다.
Ixrec

알고리즘을 사용하여 설명을 구문 분석하는 것이 불가능하므로 잘못되었다고 생각합니다.
MirroredFate

@Ixrec "토큰이 함수 토큰 인 경우 스택에 밀어 넣습니다."라는 줄이 보이지 않습니다. Wikipedia 페이지에서 지금까지 수정되었을 수 있습니다. 그러나 알고리즘에서 숫자와 같은 함수를 처리 할 수 ​​있습니까?
Abhinav

Wikipedia 기사의 알고리즘 설명에 오류가 있다고 생각합니다 (오늘까지). 구문 뒤에 if there is a left parenthesis at the top of the operator stack, then: pop the operator from the operator stack and discard it다른 줄을 추가해야합니다. 스택 맨 위에 함수 이름이 있으면 스택에서 해당 이름을 입력하고 출력으로 밉니다 . 다시 말해서, 왼쪽 '('은 함수 구문이 암시하는대로 함께 배치되는 경우 항상 함수 이름과 함께 팝업되어야합니다 : " name(".
Stan

3

언어 구문에 따라 고려해야 할 두 가지 경우가 있습니다. 언어가 괄호를 사용하여 함수 적용 (예 :)을 나타내는 f(2+1)경우 우선 순위는 관련이 없습니다. 함수는 스택으로 밀고 그 후에 튀어 나와야합니다 (위의 예에서 결과는 2 1 + f). 또는 함수를 값으로 처리하여 즉시 출력하고 닫는 괄호 (다른 괄호와 동일하게 처리해야 함) 후에 함수 호출 조작을 출력 할 수 있습니다 (예 : 함수 호출 조작은 f 2 1 + $어디에 있습니까 $).

그러나 언어가 함수 호출을 나타 내기 위해 괄호를 사용하지 않고 f 2 + 1Wikipedia의 예와 같이 특별한 구두점없이 함수 바로 뒤에 인수를 배치하면 상황이 조금 더 복잡합니다. 방금 예를 든 표현은 모호합니다 .f 가 2에 1을 적용하고 1을 결과에 추가합니까, 아니면 2와 1을 더한 다음 결과와 함께 f 를 호출 합니까?

다시 두 가지 접근 방식이 있습니다. 함수를 발견했을 때 함수를 연산자 스택에 푸시하고 원하는 우선 순위를 지정하면됩니다. 이것은 가장 간단한 접근 방식이며 인용 된 예제가 수행 한 것입니다. 그러나 실질적인 문제가 있습니다. 먼저 함수를 어떻게 식별합니까? 유한 세트가 있으면 쉽지만 사용자 정의 함수가있는 경우 파서는 환경으로 다시 피드백해야하므로 빠르게 지저분해질 수 있습니다. 그리고 여러 개의 인수로 함수를 어떻게 처리합니까?

필자는 이러한 스타일의 구문에서 함수를 함수 응용 프로그램 운영자가보다 편리한 값으로 사용하는 것이 훨씬 더 의미가 있다고 생각합니다. 그런 다음 값을 읽을 때마다 응용 프로그램 연산자를 삽입하면 마지막으로 읽은 값도 값이되므로 어떤 식별자가 함수인지 알려주는 특별한 방법이 필요하지 않습니다. 함수를 리턴하는 표현식으로 작업 할 수도 있습니다 (오퍼레이션 기능으로는 어렵거나 불가능합니다). 이는 카레를 사용하여 여러 인수 함수를 처리 할 수 ​​있다는 것을 의미합니다. 이는 직접 처리하려고 시도하는 것보다 훨씬 간단합니다.

그런 다음 결정해야 할 것은 함수 응용 프로그램의 우선 순위입니다. 선택은 당신에게 달려 있지만, 내가 사용했던 모든 언어에서, 그것은 언어에서 가장 강력하게 구속력이 있고 올바른 연관성이 있습니다. (유일하게 흥미로운 변형은 Haskell이며, 강하게 바인딩 된 버전을 가지고있을뿐만 아니라 $언어에서 가장 약하게 바인딩 된 연산자 인 기호와 동의어 가 있으므로 f 2 + 1f에 2 f $ 2 + 1를 적용 하고 적용 하는 것과 같은 표현을 허용 합니다 나머지 표현 전체에 적용)


3

Dijkstra의 독창적 인 생각 (Algol 60 컴파일러 논문의 7-11 페이지, https://ir.cwi.nl/pub/9251 )을 읽고 강력한 솔루션이 필요한 후에 "분로 장에서의 기능"을 요청했습니다. 다음을 수행했습니다.

파싱 ​​:

  • 함수 설명자를 누릅니다
  • 하위 표현식 괄호 시작과 같이 인수 시작 왼쪽 대괄호 "["를 누르십시오.
  • 입력에서 "("~ ")"밸런스 인수 목록 순서 읽기
  • 이것을 출력 토큰 스트림으로 푸시
  • "보상 마감 브래킷"과 마찬가지로 인수 끝 오른쪽 브래킷 "]"을 누릅니다.

접두사 접미사 (분로 장) :

  • 연산자 스택과 마찬가지로 다른 스택, 함수 스택 추가
  • 기능 이름을 스캔 할 때 기능 정보를 기능 스택으로 푸시
  • 인수 끝 오른쪽 브래킷이 표시되면 함수 스택을 출력으로 팝

강력한 테스트 및 복잡한 시나리오에서 완벽하게 작동합니다. 내 응용 프로그램 (명령 줄 인수 포함 식 확장기)에서 다중 인수 함수와 쉼표 ""토큰을 분리하여 분리하고 전체 프로세스를 통과합니다.

예제는 "sqrt (3 ^ 2 + 4 ^ 2)"처럼 보입니다. "3 2 ^ 4 2 ^ + sqrt"가되고 궁극적으로 "5"는 프로그램이 인수라고 생각합니다. ""이항 (64, 32) / gcd (이항 (64, 32), 이항 (63, 31)) "==> 큰 일 ==>"2 "가 도움이됩니다."123456 ^ 789 " 는 MacBook Pro에서 40,173 자리 숫자이며 타이밍에 "평가 = 0.000390 초"가 표시됩니다.

또한 이것을 사용하여 테이블의 데이터를 확장하고 편리하게 찾을 수 있습니다. 어쨌든, Dijkstra 분로 장 상황에서 함수 호출, 여러 인수 및 딥 네 스팅을 신중하게 처리하는 방법에 대한 나의 팁. 오늘은 독립적 인 사고에서 그랬습니다. 더 좋은 방법이 있는지 모릅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.