Parsing/Shunting-yard algorithm: Difference between revisions

Add Scala implementation
m (→‎{{header|Perl}}: Fix link: Perl 6 --> Raku)
(Add Scala implementation)
 
(21 intermediate revisions by 15 users not shown)
Line 39:
* [[Parsing/RPN to infix conversion]].
<br><br>
 
=={{header|11l}}==
{{trans|Java}}
 
<syntaxhighlight lang="11l">F infix_to_postfix(infix)
-V ops = ‘-+/*^’
V sb = ‘’
[Int] s
 
L(token) infix.split(re:‘\s’)
I token.empty
L.continue
 
V c = token[0]
V? idx = ops.find(c)
I idx != N
I s.empty
s.append(idx)
E
L !s.empty
V prec2 = s.last I/ 2
V prec1 = idx I/ 2
I prec2 > prec1 | (prec2 == prec1 & c != ‘^’)
sb ‘’= ops[s.pop()]‘ ’
E
L.break
s.append(idx)
 
E I c == ‘(’
s.append(-2)
 
E I c == ‘)’
L s.last != -2
sb ‘’= ops[s.pop()]‘ ’
s.pop()
 
E
sb ‘’= token‘ ’
 
L !s.empty
sb ‘’= ops[s.pop()]‘ ’
 
R sb
 
V infix = ‘3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3’
print(‘infix: ’infix)
print(‘postfix: ’infix_to_postfix(infix))</syntaxhighlight>
 
{{out}}
<pre>
infix: 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
postfix: 3 4 2 * 1 5 - 2 3 ^ ^ / +
</pre>
 
=={{header|8th}}==
<langsyntaxhighlight lang="forth">\ Convert infix expression to postfix, using 'shunting-yard' algorithm
\ https://en.wikipedia.org/wiki/Shunting-yard_algorithm
 
Line 171 ⟶ 224:
"Expected: \n" . "3 4 2 * 1 5 - 2 3 ^ ^ / +" . cr
bye
</syntaxhighlight>
</lang>
{{out}}
<pre>NUMBER 3
Line 240 ⟶ 293:
=={{header|ALGOL 68}}==
{{works with|ALGOL 68G|Any - tested with release 2.8.3.win32}}
<langsyntaxhighlight lang="algol68">BEGIN
# parses s and returns an RPN expression using Dijkstra's "Shunting Yard" algorithm #
# s is expected to contain a valid infix expression containing single-digit numbers and single-character operators #
Line 317 ⟶ 370:
 
print( ( "result: ", parse( "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3" ), newline ) )
END</langsyntaxhighlight>
{{out}}
<pre>
Line 341 ⟶ 394:
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
<langsyntaxhighlight AHKlang="ahk">SetBatchLines -1
#NoEnv
 
Line 410 ⟶ 463:
Space(n){
return n>0 ? A_Space Space(n-1) : ""
}</langsyntaxhighlight>
;Output
<pre style="height:30ex;overflow:scroll;">Testing string '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3'
Line 440 ⟶ 493:
=={{header|C}}==
Requires a functioning ANSI terminal and Enter key.
<langsyntaxhighlight lang="c">#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
Line 624 ⟶ 677:
 
return 0;
}</langsyntaxhighlight>
 
;Output:
Line 763 ⟶ 816:
=={{header|C sharp}}==
{{works with|C sharp|7.0}}
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 830 ⟶ 883:
void Print(string action) => Console.WriteLine("{0,-4} {1,-18} {2}", action + ":", $"stack[ {string.Join(" ", stack.Reverse())} ]", $"out[ {string.Join(" ", output)} ]");
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 852 ⟶ 905:
 
=={{header|C++}}==
 
== Note 1 ==
Shunting Yard is conceptually very simple, but it requires a whole lot of help to validate
an expression. The best way to handle this, IMO, is as a separate pass to check the tokens
for incorrect patterns and matching parentheses and transform things like unary minus into
a unique token identifier.
 
That said, this Rosetta Code Task specifically obviates validation, though, so we don't do
any of that below. In other words, binary operators only, and garbage in == garbage out.
 
== Note 2 ==
This example leverages some nice C++17 features, so turn them on when you compile.
 
cl /EHsc /W4 /Ox /std:c++17 /utf-8 a.cpp
clang++ -Wall -pedantic-errors -O3 -std=c++17 a.cpp
 
<syntaxhighlight lang="cpp">#include <ciso646>
#include <iostream>
#include <regex>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
 
using std::vector;
using std::string;
 
//-------------------------------------------------------------------------------------------------
// throw error( "You ", profanity, "ed up!" ); // Don't mess up, okay?
//-------------------------------------------------------------------------------------------------
#include <exception>
#include <stdexcept>
template <typename...Args> std::runtime_error error( Args...args )
{
return std::runtime_error( (std::ostringstream{} << ... << args).str() );
};
 
//-------------------------------------------------------------------------------------------------
// Stack
//-------------------------------------------------------------------------------------------------
// Let us co-opt a vector for our stack type.
// C++ pedants: no splicing possible == totally okay to do this.
//
// Note: C++ provides a more appropriate std::stack class, except that the task requires us to
// be able to display its contents, and that kind of access is an expressly non-stack behavior.
 
template <typename T> struct stack : public std::vector <T>
{
using base_type = std::vector <T> ;
T push ( const T& x ) { base_type::push_back( x ); return x; }
const T& top () { return base_type::back(); }
T pop () { T x = std::move( top() ); base_type::pop_back(); return x; }
bool empty() { return base_type::empty(); }
};
 
//-------------------------------------------------------------------------------------------------
using Number = double;
//-------------------------------------------------------------------------------------------------
// Numbers are already too awesome to need extra diddling.
 
//-------------------------------------------------------------------------------------------------
// Operators
//-------------------------------------------------------------------------------------------------
using Operator_Name = string;
using Precedence = int;
enum class Associates { none, left_to_right, right_to_left };
 
struct Operator_Info { Precedence precedence; Associates associativity; };
 
std::unordered_map <Operator_Name, Operator_Info> Operators =
{
{ "^", { 4, Associates::right_to_left } },
{ "*", { 3, Associates::left_to_right } },
{ "/", { 3, Associates::left_to_right } },
{ "+", { 2, Associates::left_to_right } },
{ "-", { 2, Associates::left_to_right } },
};
 
Precedence precedence ( const Operator_Name& op ) { return Operators[ op ].precedence; }
Associates associativity( const Operator_Name& op ) { return Operators[ op ].associativity; }
 
//-------------------------------------------------------------------------------------------------
using Token = string;
//-------------------------------------------------------------------------------------------------
bool is_number ( const Token& t ) { return regex_match( t, std::regex{ R"z((\d+(\.\d*)?|\.\d+)([Ee][\+\-]?\d+)?)z" } ); }
bool is_operator ( const Token& t ) { return Operators.count( t ); }
bool is_open_parenthesis ( const Token& t ) { return t == "("; }
bool is_close_parenthesis( const Token& t ) { return t == ")"; }
bool is_parenthesis ( const Token& t ) { return is_open_parenthesis( t ) or is_close_parenthesis( t ); }
 
//-------------------------------------------------------------------------------------------------
// std::cout << a_vector_of_something;
//-------------------------------------------------------------------------------------------------
// Weird C++ stream operator stuff (for I/O).
// Don't worry if this doesn't look like it makes any sense.
//
template <typename T> std::ostream& operator << ( std::ostream& outs, const std::vector <T> & xs )
{
std::size_t n = 0; for (auto x : xs) outs << (n++ ? " " : "") << x; return outs;
}
 
//-------------------------------------------------------------------------------------------------
// Progressive_Display
//-------------------------------------------------------------------------------------------------
// This implements the required task:
// "use the algorithm to show the changes in the operator
// stack and RPN output as each individual token is processed"
//
#include <iomanip>
 
struct Progressive_Display
{
string token_name;
string token_type;
 
Progressive_Display() // Header for the table we are going to generate
{
std::cout << "\n"
" INPUT │ TYPE │ ACTION │ STACK │ OUTPUT\n"
"────────┼──────┼──────────────────┼──────────────┼─────────────────────────────\n";
}
 
Progressive_Display& operator () ( const Token& token ) // Ready the first two columns
{
token_name = token;
token_type = is_operator ( token ) ? "op"
: is_parenthesis( token ) ? "()"
: is_number ( token ) ? "num"
: "";
return *this;
}
 
Progressive_Display& operator () ( // Display all columns of a row
const string & description,
const stack <Token> & stack,
const vector <Token> & output )
{
std::cout << std::right
<< std::setw( 7 ) << token_name << " │ " << std::left
<< std::setw( 4 ) << token_type << " │ "
<< std::setw( 16 ) << description << " │ "
<< std::setw( 12 ) << (std::ostringstream{} << stack).str() << " │ "
<< output << "\n";
return operator () ( "" ); // Reset the first two columns to empty for next iteration
}
};
 
//-------------------------------------------------------------------------------------------------
vector <Token> parse( const vector <Token> & tokens )
//-------------------------------------------------------------------------------------------------
{
vector <Token> output;
stack <Token> stack;
 
Progressive_Display display;
 
for (auto token : tokens) // Shunting Yard takes a single linear pass through the tokens
 
//.........................................................................
if (is_number( token ))
{
output.push_back( token );
display( token )( "num --> output", stack, output );
}
 
//.........................................................................
else if (is_operator( token ) or is_parenthesis( token ))
{
display( token );
 
if (!is_open_parenthesis( token ))
{
// pop --> output
// : until '(' if token is ')'
// : while prec(token) > prec(top)
// : while prec(token) == prec(top) AND assoc(token) is left-to-right
while (!stack.empty()
and ( (is_close_parenthesis( token ) and !is_open_parenthesis( stack.top() ))
or (precedence( stack.top() ) > precedence( token ))
or ( (precedence( stack.top() ) == precedence( token ))
and (associativity( token ) == Associates::left_to_right))))
{
output.push_back( stack.pop() );
display( "pop --> output", stack, output );
}
 
// If we popped until '(' because token is ')', toss both parens
if (is_close_parenthesis( token ))
{
stack.pop();
display( "pop", stack, output );
}
}
 
// Everything except ')' --> stack
if (!is_close_parenthesis( token ))
{
stack.push( token );
display( "push op", stack, output );
}
}
 
//.........................................................................
else throw error( "unexpected token: ", token );
 
// Anything left on the operator stack just gets moved to the output
 
display( "END" );
while (!stack.empty())
{
output.push_back( stack.pop() );
display( "pop --> output", stack, output );
}
 
return output;
}
 
//-------------------------------------------------------------------------------------------------
int main( int argc, char** argv )
//-------------------------------------------------------------------------------------------------
try
{
auto tokens = vector <Token> ( argv+1, argv+argc );
auto rpn_expr = parse( tokens );
std::cout
<< "\nInfix = " << tokens
<< "\nRPN = " << rpn_expr
<< "\n";
}
catch (std::exception e)
{
std::cerr << "error: " << e.what() << "\n";
return 1;
}</syntaxhighlight>
{{out}}
<pre>C:\Users\JRandom\cpp> a.exe 3 + 4 * 2 / ( 1 - 5 ) ^^ 2 ^^ 3
 
INPUT │ TYPE │ ACTION │ STACK │ OUTPUT
────────┼──────┼──────────────────┼──────────────┼─────────────────────────────
3 │ num │ num --> output │ │ 3
+ │ op │ push op │ + │ 3
4 │ num │ num --> output │ + │ 3 4
* │ op │ push op │ + * │ 3 4
2 │ num │ num --> output │ + * │ 3 4 2
/ │ op │ pop --> output │ + │ 3 4 2 *
│ │ push op │ + / │ 3 4 2 *
( │ () │ push op │ + / ( │ 3 4 2 *
1 │ num │ num --> output │ + / ( │ 3 4 2 * 1
- │ op │ push op │ + / ( - │ 3 4 2 * 1
5 │ num │ num --> output │ + / ( - │ 3 4 2 * 1 5
) │ () │ pop --> output │ + / ( │ 3 4 2 * 1 5 -
│ │ pop │ + / │ 3 4 2 * 1 5 -
^ │ op │ push op │ + / ^ │ 3 4 2 * 1 5 -
2 │ num │ num --> output │ + / ^ │ 3 4 2 * 1 5 - 2
^ │ op │ push op │ + / ^ ^ │ 3 4 2 * 1 5 - 2
3 │ num │ num --> output │ + / ^ ^ │ 3 4 2 * 1 5 - 2 3
END │ │ pop --> output │ + / ^ │ 3 4 2 * 1 5 - 2 3 ^
│ │ pop --> output │ + / │ 3 4 2 * 1 5 - 2 3 ^ ^
│ │ pop --> output │ + │ 3 4 2 * 1 5 - 2 3 ^ ^ /
│ │ pop --> output │ │ 3 4 2 * 1 5 - 2 3 ^ ^ / +
 
Infix = 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
RPN = 3 4 2 * 1 5 - 2 3 ^ ^ / +
 
C:\Users\JRandom\cpp> _
</pre>
(Remember that on Windows you must double the caret symbol at the prompt.)
 
Here is the code originally found under this C++ heading:
{{trans|Java}}
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <sstream>
#include <stack>
Line 911 ⟶ 1,234:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>infix: 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
Line 917 ⟶ 1,240:
 
=={{header|Ceylon}}==
<langsyntaxhighlight lang="ceylon">import ceylon.collection {
 
ArrayList
Line 1,022 ⟶ 1,345:
assert(rpn == "3 4 2 * 1 5 - 2 3 ^ ^ / +");
print("\nthe result is ``rpn``");
}</langsyntaxhighlight>
{{out}}
<pre>input is 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
Line 1,053 ⟶ 1,376:
=={{header|Common Lisp}}==
Implemented as a state machine. The current state is the top of both the input queue and the operator stack. A signal function receives the current state and does a lookup to determine the signal to output. Based on the signal, the state (input queue and/or operator stack) is changed. The process iterates until both queue and stack are empty.
<langsyntaxhighlight lang="lisp">;;;; Parsing/infix to RPN conversion
(defconstant operators "^*/+-")
(defconstant precedence '(-4 3 3 2 2))
Line 1,142 ⟶ 1,465:
(format t "~%INFIX:\"~A\"~%" expr)
(format t "RPN:\"~A\"~%" (rpn expr)))))
</syntaxhighlight>
</lang>
{{out}}
<pre>CL-USER(2): (main)
Line 1,175 ⟶ 1,498:
=={{header|D}}==
{{trans|Java}}
<langsyntaxhighlight Dlang="d">import std.container;
import std.stdio;
 
Line 1,264 ⟶ 1,587:
s.removeFront;
return v;
}</langsyntaxhighlight>
 
{{out}}
Line 1,271 ⟶ 1,594:
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="scheme">
(require 'hash)
(require 'tree)
Line 1,324 ⟶ 1,647:
(writeln 'infix infix)
(writeln 'RPN (queue->list Q)))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,350 ⟶ 1,673:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">open System
 
type action = Shift | ReduceStack | ReduceInput
Line 1,444 ⟶ 1,767:
shunting_yard (State((Array.toList input), [], []))
|> (fun s -> s.report ReduceStack)
0</langsyntaxhighlight>
{{out}}
<pre> reduce [3] + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
Line 1,485 ⟶ 1,808:
 
===Source===
<langsyntaxhighlight Fortranlang="fortran"> MODULE COMPILER !At least of arithmetic expressions.
INTEGER KBD,MSG !I/O units.
 
Line 1,718 ⟶ 2,041:
13 FORMAT (L6," RPN: >",A,"<")
GO TO 10
END</langsyntaxhighlight>
 
===Results===
Line 1,778 ⟶ 2,101:
===A fuller symbol table===
The odd values for the precedences of the operators is driven by the model source being for a compiler able to handle much more complex arithmetic statements involving logical operations, variables, functions (some, like Max(a,b,c,...) with an arbitrary number of parameters), assignment within an expression, and conditionals such as <code>IF ''condition'' THEN ''exp1'' ELSE ''exp2'' OWISE ''exp3'' FI</code> - a three-value logic is employed. Similarly, ? stands for a "not a number" and ! for "Infinity". The fuller symbol table is...
<langsyntaxhighlight Fortranlang="fortran">Caution! The apparent gaps in the sequence of precedence values in this table are *not* unused!
Cunning ploys with precedence allow parameter evaluation, and right-to-left order as in x**y**z.
INTEGER OPSYMBOLS !Recognised operator symbols.
Line 1,825 ⟶ 2,148:
3 SYMB("^ ",14,2,"raise to power: also recognised is **."), !Uses the previous precedence level also!
4 SYMB("**",14,2,"raise to power: also recognised is ^."),
5 SYMB("! ",15,1,"factorial, sortof, just for fun.")/))</langsyntaxhighlight>
The USAGE field is for when there is a request for help, and the response uses the scanner's actual symbol table entries to formulate its assistance, rather than roll forth a separately-prepared wad of text.
 
=={{header|Go}}==
No error checking. No extra credit output, but there are some comments in the code.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,901 ⟶ 2,224:
}
return
}</langsyntaxhighlight>
Output:
<pre>
Line 1,912 ⟶ 2,235:
Simple with zero error handling; some extra credit.
 
<langsyntaxhighlight Haskelllang="haskell">import Text.Printf
 
prec :: String -> Int
prec "^" = 4
prec "*" = 3
Line 1,920 ⟶ 2,244:
prec "-" = 2
 
leftAssoc :: String -> Bool
leftAssoc "^" = False
leftAssoc _ = True
 
isOp (t:[]): =String t `elem` "-+/*^"> Bool
isOp _[t] = t `elem` = False"-+/*^"
isOp _ = False
 
simSYA xs:: =[String] final-> ++[([String], [lastStepString], String)]
simSYA xs where= final =<> scanl f ([lastStep],[],"") xs
where
lastStep = (\(x,y,_) -> (reverse y ++ x, [], "")) $ last final
final = scanl f (out[],st [],_ "") t | isOp t =xs
lastStep =
(reverse (takeWhile testOp st) ++ out
, (t:) $ \(dropWhilex, testOpy, st_), t)->
| t == "("reverse y =<> (outx, [], "(":st, t)
)
| t == ")" = (reverse (takeWhile (/="(") st) ++ out,
$ last final
tail $ dropWhile (/="(") st, t)
| otherwise =f (t:out, st, _) t)
where testOp x =| isOp x && (leftAssoc t && prec t == prec x
( reverse (takeWhile testOp st) <> out,
|| prec t < prec x)
(t :) (dropWhile testOp st),
t
)
| t == "(" = (out, "(" : st, t)
| t == ")" =
( reverse (takeWhile (/= "(") st) <> out,
tail $ dropWhile (/= "(") st,
t
)
| otherwise = (t : out, st, t)
where
testOp x =
isOp x
&& ( leftAssoc t && prec t == prec x
|| prec t < prec x
)
 
main :: IO ()
main = do
a <- getLine
printf "%30s%20s%7s" "Output" "Stack" "Token"
mapM_
mapM_ (\(x,y,z) -> printf "%30s%20s%7s\n"
( \(x, y, z) ->
(unwords $ reverse x) (unwords y) z) $ simSYA $ words a</lang>
printf
"%30s%20s%7s\n"
(unwords $ reverse x)
(unwords y)
z
)
$ simSYA $ words a</syntaxhighlight>
 
Output:
Line 1,969 ⟶ 2,319:
A more complete version with typed input, output and stack; StateT + Control.Lens for stateful actions; Either for both invalid tokens on parsing and unmatched parens when converting; readLine support.
 
<langsyntaxhighlight Haskelllang="haskell">{-# LANGUAGE LambdaCase #-}
import Control.Applicative
import Control.Lens
Line 2,065 ⟶ 2,415:
Left msg -> putStrLn msg >> main
Right ts -> putStrLn (showOutput (toRPN ts)) >> main
</syntaxhighlight>
</lang>
 
<pre>Enter expression: 3 + ( ( 4 + 5 )
Line 2,080 ⟶ 2,430:
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">procedure main()
infix := "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"
printf("Infix = %i\n",infix)
Line 2,143 ⟶ 2,493:
every (s := "[ ") ||:= !L || " "
return s || "]"
end</langsyntaxhighlight>
 
{{libheader|Icon Programming Library}}
Line 2,173 ⟶ 2,523:
=={{header|J}}==
Code
<syntaxhighlight lang="j">
<lang J>
NB. j does not have a verb based precedence.
NB. j evaluates verb noun sequences from right to left.
Line 2,318 ⟶ 2,668:
 
fulfill_requirement=: ;@:(' '&,&.>)@:algebra_to_rpn
</syntaxhighlight>
</lang>
Demonstration
<syntaxhighlight lang="j">
<lang J>
fulfill_requirement '3+4*2/(1-5)^2^3'
3 4 2 * 1 5 - 2 3 ^ ^ / +
Line 2,376 ⟶ 2,726:
OUTPUT queue ^ ^ / +
3 4 2 * 1 5 - 2 3 ^ ^ / +
</syntaxhighlight>
</lang>
 
=={{header|Java}}==
{{works with|Java|7}}
<langsyntaxhighlight lang="java">import java.util.Stack;
 
public class ShuntingYard {
Line 2,438 ⟶ 2,788:
return sb.toString();
}
}</langsyntaxhighlight>
 
Output:
Line 2,446 ⟶ 2,796:
 
=={{header|JavaScript}}==
<langsyntaxhighlight lang="javascript">function Stack() {
this.dataStore = [];
this.top = 0;
Line 2,514 ⟶ 2,864:
}
postfix += s.dataStore.reverse().join(" ");
print(postfix);</langsyntaxhighlight>
 
Output:
Line 2,523 ⟶ 2,873:
=={{header|Julia}}==
Translation from the Wikipedia reference article's pseudocode.
<langsyntaxhighlight lang="julia">
function parseinfix2rpn(s)
outputq = []
Line 2,565 ⟶ 2,915:
teststring = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"
println("\nResult: $teststring becomes $(join(parseinfix2rpn(teststring), ' '))")
</syntaxhighlight>
</lang>
{{output}}
<pre>
Line 2,589 ⟶ 2,939:
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.2.0
 
import java.util.Stack
Line 2,649 ⟶ 2,999:
println("Postfix : ${infixToPostfix(e)}\n")
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,661 ⟶ 3,011:
 
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
<lang lb>
global stack$,queue$
stack$=""
Line 2,777 ⟶ 3,127:
wend
end function
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,803 ⟶ 3,153:
</pre>
 
=={{header|MathematicaLua}}==
<syntaxhighlight lang="lua">
<lang Mathematica>rpn[str_] :=
-- Lua 5.3.5
-- Retrieved from: https://devforum.roblox.com/t/more-efficient-way-to-implement-shunting-yard/1328711
-- Modified slightly to ensure conformity with other code snippets posted here
local OPERATOR_PRECEDENCE = {
-- [operator] = { [precedence], [is left assoc.] }
['-'] = { 2, true };
['+'] = { 2, true };
['/'] = { 3, true };
['*'] = { 3, true };
['^'] = { 4, false };
}
 
local function shuntingYard(expression)
local outputQueue = { }
local operatorStack = { }
local number, operator, parenthesis, fcall
 
while #expression > 0 do
local nStartPos, nEndPos = string.find(expression, '(%-?%d+%.?%d*)')
if nStartPos == 1 and nEndPos > 0 then
number, expression = string.sub(expression, nStartPos, nEndPos), string.sub(expression, nEndPos + 1)
table.insert(outputQueue, tonumber(number))
print('token:', number)
print('queue:', unpack(outputQueue))
print('stack:', unpack(operatorStack))
else
local oStartPos, oEndPos = string.find(expression, '([%-%+%*/%^])')
if oStartPos == 1 and oEndPos > 0 then
operator, expression = string.sub(expression, oStartPos, oEndPos), string.sub(expression, oEndPos + 1)
if #operatorStack > 0 then
while operatorStack[1] ~= '(' do
local operator1Precedence = OPERATOR_PRECEDENCE[operator]
local operator2Precedence = OPERATOR_PRECEDENCE[operatorStack[1]]
if operator2Precedence and ((operator2Precedence[1] > operator1Precedence[1]) or (operator2Precedence[1] == operator1Precedence[1] and operator1Precedence[2])) then
table.insert(outputQueue, table.remove(operatorStack, 1))
else
break
end
end
end
table.insert(operatorStack, 1, operator)
print('token:', operator)
print('queue:', unpack(outputQueue))
print('stack:', unpack(operatorStack))
else
local pStartPos, pEndPos = string.find(expression, '[%(%)]')
if pStartPos == 1 and pEndPos > 0 then
parenthesis, expression = string.sub(expression, pStartPos, pEndPos), string.sub(expression, pEndPos + 1)
if parenthesis == ')' then
while operatorStack[1] ~= '(' do
assert(#operatorStack > 0)
table.insert(outputQueue, table.remove(operatorStack, 1))
end
assert(operatorStack[1] == '(')
table.remove(operatorStack, 1)
else
table.insert(operatorStack, 1, parenthesis)
end
 
print('token:', parenthesis)
print('queue:', unpack(outputQueue))
print('stack:', unpack(operatorStack))
else
local wStartPos, wEndPos = string.find(expression, '%s+')
if wStartPos == 1 and wEndPos > 0 then
expression = string.sub(expression, wEndPos + 1)
else
error('Invalid character set: '.. expression)
end
end
end
end
end
while #operatorStack > 0 do
assert(operatorStack[1] ~= '(')
table.insert(outputQueue, table.remove(operatorStack, 1))
end
return table.concat(outputQueue, ' ')
end
 
 
local goodmath = '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3'
 
print('infix:', goodmath)
print('postfix:', shuntingYard(goodmath))
</syntaxhighlight>
 
{{out}}
<pre>
infix: 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
token: 3
queue: 3
stack:
token: +
queue: 3
stack: +
token: 4
queue: 3 4
stack: +
token: *
queue: 3 4
stack: * +
token: 2
queue: 3 4 2
stack: * +
token: /
queue: 3 4 2 *
stack: / +
token: (
queue: 3 4 2 *
stack: ( / +
token: 1
queue: 3 4 2 * 1
stack: ( / +
token: -
queue: 3 4 2 * 1
stack: - ( / +
token: 5
queue: 3 4 2 * 1 5
stack: - ( / +
token: )
queue: 3 4 2 * 1 5 -
stack: / +
token: ^
queue: 3 4 2 * 1 5 -
stack: ^ / +
token: 2
queue: 3 4 2 * 1 5 - 2
stack: ^ / +
token: ^
queue: 3 4 2 * 1 5 - 2
stack: ^ ^ / +
token: 3
queue: 3 4 2 * 1 5 - 2 3
stack: ^ ^ / +
postfix: 3 4 2 * 1 5 - 2 3 ^ ^ / +
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">rpn[str_] :=
StringRiffle[
ToString /@
Line 2,835 ⟶ 3,339:
While[stack != {}, AppendTo[out, stack[[-1]]];
stack = stack[[;; -2]]]; out]];
Print[rpn["3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"]];</langsyntaxhighlight>
{{out}}
<pre>3 4 2 * 1 5 - / 2 3 ^ ^ +</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang ="nim">import tables, strutils, sequtils, strformat
 
type operator = tuple[prec:int, rassoc:bool]
Line 2,884 ⟶ 3,388:
 
echo &"for infix expression: '{input}' \n", "\nTOKEN OP STACK RPN OUTPUT"
echo "postfix: ", shuntRPN(input.strip.split)</langsyntaxhighlight>
 
{{out}}
Line 2,913 ⟶ 3,417:
=={{header|OCaml}}==
{{works with|ocaml|4.04}}
<langsyntaxhighlight lang="ocaml">
type associativity = Left | Right;;
 
Line 2,973 ⟶ 3,477:
let postfix = shunting_yard tkns in
print_endline (intercalate " " postfix);;
</syntaxhighlight>
</lang>
 
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">my %prec = (
'^' => 4,
'*' => 3,
Line 3,026 ⟶ 3,530:
local $, = " ";
print shunting_yard '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3';
</syntaxhighlight>
</lang>
{{out}}
<pre> reduce 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
Line 3,052 ⟶ 3,556:
=={{header|Phix}}==
{{Trans|Go}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>integer show_workings = 1
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
 
<span style="color: #004080;">bool</span> <span style="color: #000000;">show_workings</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
constant operators = {"^","*","/","+","-"},
precedence = { 4, 3, 3, 2, 2 }
<span style="color: #008080;">constant</span> <span style="color: #000000;">operators</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"^"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"*"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"/"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"+"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"-"</span><span style="color: #0000FF;">},</span>
 
<span style="color: #000000;">precedence</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">}</span>
procedure shunting_yard(string infix, string rpn)
string res = "", sep = "", top
<span style="color: #008080;">procedure</span> <span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">infix</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rpn</span><span style="color: #0000FF;">)</span>
sequence stack = {}
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sep</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">stack_top</span>
sequence ops = split(substitute_all(infix,{"(",")"},{" ( "," ) "}),' ',no_empty:=1,limit:=0)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
printf(1,"Infix input: %-30s%s", {infix,iff(show_workings?'\n':'\t')})
<span style="color: #000000;">ops</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">substitute_all</span><span style="color: #0000FF;">(</span><span style="color: #000000;">infix</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"("</span><span style="color: #0000FF;">,</span><span style="color: #008000;">")"</span><span style="color: #0000FF;">},{</span><span style="color: #008000;">" ( "</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" ) "</span><span style="color: #0000FF;">}),</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">)</span>
for i=1 to length(ops) do
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Infix input: %-32s%s"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">infix</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">show_workings</span><span style="color: #0000FF;">?</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">:</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">)})</span>
string op = ops[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ops</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if op="(" then
<span style="color: #004080;">string</span> <span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ops</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
stack = append(stack,op)
<span style="color: #008080;">if</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"("</span> <span style="color: #008080;">then</span>
elsif op=")" then
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">)</span>
while 1 do
<span style="color: #008080;">elsif</span> <span style="color: #000000;">op</span><span style="color: #0000FF;">=</span><span style="color: #008000;">")"</span> <span style="color: #008080;">then</span>
top = stack[$]
<span style="color: #008080;">while</span> <span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
stack = stack[1..$-1]
<span style="color: #000000;">stack_top</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$]</span>
if top="(" then exit end if
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
res &= sep&top
<span style="color: #008080;">if</span> <span style="color: #000000;">stack_top</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"("</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
sep = " "
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">sep</span><span style="color: #0000FF;">&</span><span style="color: #000000;">stack_top</span>
end while
<span style="color: #000000;">sep</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" "</span>
else
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
integer k = find(op,operators)
<span if k!style=0"color: then#008080;">else</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">operators</span><span style="color: #0000FF;">)</span>
integer prec = precedence[k]
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
while length(stack) do
<span style="color: #004080;">integer</span> <span style="color: #000000;">prec</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">precedence</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
top = stack[$]
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
k = find(top,operators)
<span style="color: #000000;">stack_top</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[$]</span>
if k=0 or prec>precedence[k]
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack_top</span><span style="color: #0000FF;">,</span><span style="color: #000000;">operators</span><span style="color: #0000FF;">)</span>
or (top="^" and prec=precedence[k]) then
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">prec</span><span style="color: #0000FF;">></span><span style="color: #000000;">precedence</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
exit
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">prec</span><span style="color: #0000FF;">=</span><span style="color: #000000;">precedence</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">and</span> <span style="color: #000000;">stack_top</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"^"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
stack <span style="color: stack[1..$-1]#008080;">exit</span>
res &<span style="color: #008080;">end</span> <span style="color: sep&top#008080;">if</span>
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
sep = " "
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">sep</span><span style="color: #0000FF;">&</span><span style="color: #000000;">stack_top</span>
end while
<span style="color: #000000;">sep</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" "</span>
stack = append(stack,op)
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
else
<span style="color: #000000;">stack</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">,</span><span style="color: #000000;">op</span><span style="color: #0000FF;">)</span>
res &= sep&op
<span sep style= "color: #008080;">else</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">sep</span><span style="color: #0000FF;">&</span><span style="color: #000000;">op</span>
end if
<span style="color: #000000;">sep</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" "</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if show_workings then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
?{op,stack,res}
<span style="color: #008080;">if</span> <span style="color: #000000;">show_workings</span> <span style="color: #008080;">then</span>
end if
<span style="color: #0000FF;">?{</span><span style="color: #000000;">op</span><span style="color: #0000FF;">,</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for i=length(stack) to 1 by -1 do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
string op = stack[i]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">stack</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
res &= sep&op
<span style="color: #004080;">string</span> <span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">stack</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
sep = " "
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">sep</span><span style="color: #0000FF;">&</span><span style="color: #000000;">op</span>
end for
<span style="color: #000000;">sep</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" "</span>
printf(1,"result: %-22s [%s]\n", {res,iff(res=rpn?"ok","**ERROR**")})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end procedure
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"result: %-22s [%s]\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">=</span><span style="color: #000000;">rpn</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"ok"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"**ERROR**"</span><span style="color: #0000FF;">)})</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
shunting_yard("3 + 4 * 2 / (1 - 5) ^ 2 ^ 3","3 4 2 * 1 5 - 2 3 ^ ^ / +")
show_workings = 0
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"3 + 4 * 2 / (1 - 5) ^ 2 ^ 3"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"3 4 2 * 1 5 - 2 3 ^ ^ / +"</span><span style="color: #0000FF;">)</span>
shunting_yard("((1 + 2) ^ (3 + 4)) ^ (5 + 6)","1 2 + 3 4 + ^ 5 6 + ^")
<span style="color: #000000;">show_workings</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
shunting_yard("(1 + 2) ^ (3 + 4) ^ (5 + 6)","1 2 + 3 4 + 5 6 + ^ ^")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"((1 + 2) ^ (3 + 4)) ^ (5 + 6)"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 + 3 4 + ^ 5 6 + ^"</span><span style="color: #0000FF;">)</span>
shunting_yard("((3 ^ 4) ^ 2 ^ 9) ^ 2 ^ 5","3 4 ^ 2 9 ^ ^ 2 5 ^ ^")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(1 + 2) ^ (3 + 4) ^ (5 + 6)"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 + 3 4 + 5 6 + ^ ^"</span><span style="color: #0000FF;">)</span>
shunting_yard("(1 + 4) * (5 + 3) * 2 * 3","1 4 + 5 3 + * 2 * 3 *")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"((3 ^ 4) ^ 2 ^ 9) ^ 2 ^ 5"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"3 4 ^ 2 9 ^ ^ 2 5 ^ ^"</span><span style="color: #0000FF;">)</span>
shunting_yard("1 * 2 * 3 * 4","1 2 * 3 * 4 *")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(1 + 4) * (5 + 3) * 2 * 3"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 4 + 5 3 + * 2 * 3 *"</span><span style="color: #0000FF;">)</span>
shunting_yard("1 + 2 + 3 + 4","1 2 + 3 + 4 +")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1 * 2 * 3 * 4"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 * 3 * 4 *"</span><span style="color: #0000FF;">)</span>
shunting_yard("(1 + 2) ^ (3 + 4)","1 2 + 3 4 + ^")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1 + 2 + 3 + 4"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 + 3 + 4 +"</span><span style="color: #0000FF;">)</span>
shunting_yard("(5 ^ 6) ^ 7","5 6 ^ 7 ^")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(1 + 2) ^ (3 + 4)"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 + 3 4 + ^"</span><span style="color: #0000FF;">)</span>
shunting_yard("5 ^ 4 ^ 3 ^ 2","5 4 3 2 ^ ^ ^")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(5 ^ 6) ^ 7"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"5 6 ^ 7 ^"</span><span style="color: #0000FF;">)</span>
shunting_yard("1 + 2 + 3","1 2 + 3 +")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"5 ^ 4 ^ 3 ^ 2"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"5 4 3 2 ^ ^ ^"</span><span style="color: #0000FF;">)</span>
shunting_yard("1 ^ 2 ^ 3","1 2 3 ^ ^")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1 + 2 + 3"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 + 3 +"</span><span style="color: #0000FF;">)</span>
shunting_yard("(1 ^ 2) ^ 3","1 2 ^ 3 ^")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1 ^ 2 ^ 3"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 3 ^ ^"</span><span style="color: #0000FF;">)</span>
shunting_yard("1 - 1 + 3","1 1 - 3 +")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(1 ^ 2) ^ 3"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 ^ 3 ^"</span><span style="color: #0000FF;">)</span>
shunting_yard("3 + 1 - 1","3 1 + 1 -")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1 - 1 + 3"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 1 - 3 +"</span><span style="color: #0000FF;">)</span>
shunting_yard("1 - (2 + 3)","1 2 3 + -")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"3 + 1 - 1"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"3 1 + 1 -"</span><span style="color: #0000FF;">)</span>
shunting_yard("4 + 3 + 2","4 3 + 2 +")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1 - (2 + 3)"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"1 2 3 + -"</span><span style="color: #0000FF;">)</span>
shunting_yard("5 + 4 + 3 + 2","5 4 + 3 + 2 +")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"4 + 3 + 2"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"4 3 + 2 +"</span><span style="color: #0000FF;">)</span>
shunting_yard("5 * 4 * 3 * 2","5 4 * 3 * 2 *")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"5 + 4 + 3 + 2"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"5 4 + 3 + 2 +"</span><span style="color: #0000FF;">)</span>
shunting_yard("5 + 4 - (3 + 2)","5 4 + 3 2 + -")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"5 * 4 * 3 * 2"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"5 4 * 3 * 2 *"</span><span style="color: #0000FF;">)</span>
shunting_yard("3 - 4 * 5","3 4 5 * -")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"5 + 4 - (3 + 2)"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"5 4 + 3 2 + -"</span><span style="color: #0000FF;">)</span>
shunting_yard("3 * (4 - 5)","3 4 5 - *")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"3 - 4 * 5"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"3 4 5 * -"</span><span style="color: #0000FF;">)</span>
shunting_yard("(3 - 4) * 5","3 4 - 5 *")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"3 * (4 - 5)"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"3 4 5 - *"</span><span style="color: #0000FF;">)</span>
shunting_yard("4 * 2 + 1 - 5","4 2 * 1 + 5 -")
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"(3 - 4) * 5"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"3 4 - 5 *"</span><span style="color: #0000FF;">)</span>
shunting_yard("4 * 2 / (1 - 5) ^ 2","4 2 * 1 5 - 2 ^ /")</lang>
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"4 * 2 + 1 - 5"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"4 2 * 1 + 5 -"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">shunting_yard</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"4 * 2 / (1 - 5) ^ 2"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"4 2 * 1 5 - 2 ^ /"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 3,187 ⟶ 3,694:
=={{header|PicoLisp}}==
Note: "^" is a meta-character and must be escaped in strings
<langsyntaxhighlight PicoLisplang="picolisp">(de operator (Op)
(member Op '("\^" "*" "/" "+" "-")) )
 
Line 3,227 ⟶ 3,734:
(quit "Unbalanced Stack") )
(link (pop 'Stack))
(tab Fmt NIL (glue " " (made)) Stack) ) ) ) )</langsyntaxhighlight>
Output:
<langsyntaxhighlight PicoLisplang="picolisp">: (shuntingYard "3 + 4 * 2 / (1 - 5) \^ 2 \^ 3")
Token Output Stack
3 3
Line 3,250 ⟶ 3,757:
3 4 2 * 1 5 - 2 3 ^ ^ / +
3 4 2 * 1 5 - 2 3 ^ ^ / +
-> (3 4 2 "*" 1 5 "-" 2 3 "\^" "\^" "/" "+")</langsyntaxhighlight>
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
cvt: procedure options (main); /* 15 January 2012. */
declare (in, stack, out) character (100) varying;
Line 3,336 ⟶ 3,843:
 
end cvt;
</syntaxhighlight>
</lang>
Output:
<syntaxhighlight lang="text">
INPUT STACK OUTPUT
3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3 ) (
Line 3,371 ⟶ 3,878:
3 4 2 * 1 5 - 2 3 ^ ^ / +
3 4 2 * 1 5 - 2 3 ^ ^ / +
</syntaxhighlight>
</lang>
 
=={{header|Python}}==
Parenthesis are added to the operator table then special-cased in the code.
This solution includes the extra credit.
<langsyntaxhighlight lang="python">from collections import namedtuple
from pprint import pprint as pp
 
Line 3,478 ⟶ 3,985:
print( ' '.join('{cell:<{width}}'.format(width=width, cell=cell) for (width, cell) in zip(maxcolwidths, row)))
 
print('\n The final output RPN is: %r' % rp[-1][2])</langsyntaxhighlight>
 
;Sample output:
Line 3,510 ⟶ 4,017:
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
;print column of width w
Line 3,555 ⟶ 4,062:
((if (lasso? x) <= <) (prec x) (prec y)))))])
(shunt (append (reverse l) out) (cons x r) in (format "out ~a, push ~a" l x)))])])))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,580 ⟶ 4,087:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line> my %prec =
'^' => 4,
'*' => 3,
'/' => 3,
'+' => 2,
'-' => 2,
'(' => 1;
 
my %assoc =
'^' => 'right',
'*' => 'left',
'/' => 'left',
'+' => 'left',
'-' => 'left';
 
sub shunting-yard ($prog) {
my @inp = $prog.words;
my @ops;
my @res;
 
sub report($op) { printf "%25s %-7s %10s %s\n", ~@res, ~@ops, $op, ~@inp }
sub shift($t) { report( "shift $t"); @ops.push: $t }
sub reduce($t) { report("reduce $t"); @res.push: $t }
 
while @inp {
given @inp.shift {
when /\d/ { reduce $_ };
when '(' { shift $_ }
when ')' { while @ops and (my $x = @ops.pop and $x ne '(') { reduce $x } }
default {
my $newprec = %prec{$_};
while @ops {
my $oldprec = %prec{@ops[*-1]};
last if $newprec > $oldprec;
last if $newprec == $oldprec and %assoc{$_} eq 'right';
reduce @ops.pop;
}
}
shift $_;
}
}
}
}
reduce @ops.pop while @ops;
@res;
}
 
say shunting-yard '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3';</langsyntaxhighlight>
{{out}}
<pre> reduce 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
Line 3,652 ⟶ 4,159:
These REXX versions below allow multi-character tokens &nbsp; (both operands and operators).
===assume expression is correct===
<langsyntaxhighlight lang="rexx">/*REXX pgm converts infix arith. expressions to Reverse Polish notation (shunting─yard).*/
parse arg x /*obtain optional argument from the CL.*/
if x='' then x= '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3' /*Not specified? Then use the default.*/
Line 3,703 ⟶ 4,210:
/*──────────────────────────────────────────────────────────────────────────────────────────*/
isOp: return pos(arg(1),rOp) \== 0 /*is the first argument a "real" operator? */
show: if tell then say center(?,5) left(subword(x,k),L) left($,L%2) left(RPN,L) arg(1); return</langsyntaxhighlight>
'''output''' &nbsp; when using the default input:
<pre>
Line 3,743 ⟶ 4,250:
 
The &nbsp; '''select''' &nbsp; group could've been modified to check for mismatched parenthesis, but it would be harder to peruse the source.
<langsyntaxhighlight lang="rexx">/*REXX pgm converts infix arith. expressions to Reverse Polish notation (shunting─yard).*/
parse arg x /*obtain optional argument from the CL.*/
if x='' then x= '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3' /*Not specified? Then use the default.*/
Line 3,799 ⟶ 4,306:
/*──────────────────────────────────────────────────────────────────────────────────────────*/
isOp: return pos(arg(1), Rop) \== 0 /*is the first argument a "real" operator? */
show: if tell then say center(?,5) left(subword(x,k),L) left($,L%2) left(RPN,L) arg(1); return</langsyntaxhighlight>
'''output''' &nbsp; when using the input: <tt> ) &nbsp; ( </tt>
<pre>
input: ) (
RPN──► ─────── error in expression ───────
</pre>
 
=={{header|RPL}}==
≪ "§" + → expression
≪ { }
1 expression SIZE '''FOR''' j
DUP TYPE NOT <span style="color:grey">@ 1 if a number is in top-stack position</span>
expression j DUP SUB
'''IF''' "0123456789" OVER POS '''THEN'''
STR→
'''IF''' SWAP '''THEN''' SWAP 10 * + '''END'''
'''ELSE'''
'''IF''' SWAP '''THEN''' ROT ROT + SWAP '''END'''
'''IF''' "^*/+-()" OVER POS '''THEN''' + '''ELSE''' DROP '''END'''
'''END'''
'''NEXT'''
≫ ≫ ‘<span style="color:blue">LEXER</span>’ STO <span style="color:grey">@ ( "1+(2*3)" → { 1 "+" "(" 2 "*" 3 ")" } )</span>
≪ '''IF''' OVER '''THEN'''
"^*/+-" DUP 5 PICK POS SWAP ROT POS
{ 4 3 3 2 2 } { 1 0 0 0 0 }
→ o2 o1 prec rasso
≪ '''IF''' o2 '''THEN'''
prec o1 GET prec o2 GET
'''IF''' rasso o1 GET '''THEN''' < '''ELSE''' ≤ '''END'''
'''ELSE''' 0 '''END'''
'''ELSE''' DROP 0 '''END'''
≫ ‘<span style="color:blue">POPOP?</span>’ STO <span style="color:grey">@ ( op → Boolean )</span>
≪ <span style="color:blue">LEXER</span> { } "" → infix postfix token
≪ 0
1 infix SIZE '''FOR''' j
infix j GET 'token' STO
1 SF
'''CASE'''
"^*/+-" token →STR POS '''THEN'''
1 CF
'''WHILE''' token <span style="color:blue">POPOP?</span> '''REPEAT'''
'postfix' ROT STO+ 1 - '''END'''
token SWAP 1 + '''END'''
"(" token == '''THEN'''
token SWAP 1 + '''END'''
")" token == '''THEN'''
'''WHILE''' DUP 1 FS? AND '''REPEAT'''
'''IF''' OVER "(" ≠ '''THEN'''
'postfix' ROT STO+
'''ELSE''' SWAP DROP 1 CF '''END'''
1 -
'''END'''
'''END'''
1 FS? '''THEN''' 'postfix' token STO+ '''END'''
'''END'''
'''NEXT'''
'''WHILE''' DUP '''REPEAT'''
'postfix' ROT STO+
1 - '''END'''
DROP ""
1 postfix SIZE '''FOR''' j
postfix j GET + " " + '''NEXT'''
≫ ≫ ‘<span style="color:blue">→RPN<span>’ STO
 
"3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3" <span style="color:blue">→RPN<span>
{{out}}
<pre>
1: "3 4 2 * 1 5 - 2 3 ^ ^ / + "
</pre>
 
Line 3,809 ⟶ 4,382:
See [[Parsing/RPN/Ruby]]
 
<langsyntaxhighlight lang="ruby">rpn = RPNExpression.from_infix("3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3")</langsyntaxhighlight>
outputs
<pre>for Infix expression: 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
Line 3,833 ⟶ 4,406:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">type Number = f64;
 
#[derive(Debug, Copy, Clone, PartialEq)]
Line 3,880 ⟶ 4,453:
return None;
}
self.get(self.lenlast() - 1).mapcloned(|value| value.clone())
}
}
fn lex_token(input: char) -> Result<Token, char> {
let ret = match input {
'0'...'9' => Ok(Token::Digit(input.to_digit(10).unwrap() as Number)),
'+' => Ok(Operator::new_token('+', 1, true, |x, y| x + y)),
'-' => Ok(Operator::new_token('-', 1, true, |x, y| x - y)),
'*' => Ok(Operator::new_token('*', 2, true, |x, y| x * y)),
'/' => Ok(Operator::new_token('/', 2, true, |x, y| x / y)),
'^' => Ok(Operator::new_token('^', 3, false, |x, y| x.powf(y))),
'(' => Ok(Token::LeftParen),
')' => Ok(Token::RightParen),
_ => return Err(input),
};
Ok(ret)
}
 
Line 3,991 ⟶ 4,565:
 
calculate(postfix_tokens)
}</langsyntaxhighlight>
 
 
=={{header|Scala}}==
{{trans|Java}}
<syntaxhighlight lang="Scala">
import scala.util.control.Breaks._
 
object ShuntingYard {
 
def main(args: Array[String]): Unit = {
val infix = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"
println(s"infix: $infix")
println(s"postfix: ${infixToPostfix(infix)}")
}
 
def infixToPostfix(infix: String): String = {
val ops = "-+/*^"
val sb = new StringBuilder
val s = scala.collection.mutable.Stack[Int]()
 
infix.split("\\s").foreach { token =>
if (token.nonEmpty) {
val c = token.head
val idx = ops.indexOf(c)
 
if (idx != -1) {
if (s.isEmpty) s.push(idx)
else {
breakable({
while (s.nonEmpty) {
val prec2 = s.top / 2
val prec1 = idx / 2
if (prec2 > prec1 || (prec2 == prec1 && c != '^')) sb.append(ops(s.pop)).append(' ')
else break
}
});
s.push(idx)
}
} else if (c == '(') {
s.push(-2) // -2 stands for '('
} else if (c == ')') {
// until '(' on stack, pop operators.
while (s.top != -2) sb.append(ops(s.pop)).append(' ')
s.pop()
} else {
sb.append(token).append(' ')
}
}
}
while (s.nonEmpty) sb.append(ops(s.pop)).append(' ')
sb.toString
}
}
</syntaxhighlight>
{{out}}
<pre>
infix: 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
postfix: 3 4 2 * 1 5 - 2 3 ^ ^ / +
 
</pre>
 
=={{header|Sidef}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="ruby">var prec = Hash(
'^' => 4,
'*' => 3,
Line 4,052 ⟶ 4,686:
}
 
say shunting_yard('3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3').join(' ')</langsyntaxhighlight>
{{out}}
<pre>
Line 4,079 ⟶ 4,713:
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang="sml">structure Operator = struct
datatype associativity = LEFT | RIGHT
type operator = { symbol : char, assoc : associativity, precedence : int }
Line 4,188 ⟶ 4,822:
parse' tokens [] []
end
end</langsyntaxhighlight>
 
=={{header|Swift}}==
<syntaxhighlight lang="swift">// Updated to Swift 5.7
<lang Swift>import Foundation
import Foundation
 
// Using arrays for both stack and queue
struct Stack<T> {
private(set) var elements = [T]()
var isEmpty: Bool { return elements.isEmpty }
var isEmpty: Bool {
 
elements.isEmpty
mutating func push(newElement: T) {
}
elements.append(newElement)
}
var top: T? {
 
elements.last
mutating func pop() -> T {
}
return elements.removeLast()
}
mutating func push(_ newElement: T) {
 
elements.append(newElement)
func top() -> T? {
}
return elements.last
}
mutating func pop() -> T? {
self.isEmpty ? nil : elements.removeLast()
}
}
 
struct Queue<T> {
private(set) var elements = [T]()
var isEmpty: Bool { return elements.isEmpty }
var isEmpty: Bool {
 
elements.isEmpty
mutating func enqueue(newElement: T) {
}
elements.append(newElement)
}
mutating func enqueue(_ newElement: T) {
 
elements.append(newElement)
mutating func dequeue() -> T {
}
return elements.removeFirst()
}
mutating func dequeue() -> T {
return elements.removeFirst()
}
}
 
enum Associativity { case Left, Right }
case Left, Right
}
 
// Define abstract interface, whichProtocol can be used to restrict Set extension
protocol OperatorType: Comparable, Hashable {
var name: String { get }
var precedence: Int { get }
var associativity: Associativity { get }
}
 
struct Operator: OperatorType {
let name: String
let precedence: Int
let associativity: Associativity
// same operator names are not allowed
// Duplicate operator names are not allowed
var hashValue: Int { return "\(name)".hashValue }
func hash(into hasher: inout Hasher) {
 
hasher.combine(self.name)
init(_ name: String, _ precedence: Int, _ associativity: Associativity) {
}
self.name = name; self.precedence = precedence; self.associativity = associativity
}
init(_ name: String, _ precedence: Int, _ associativity: Associativity) {
self.name = name; self.precedence = precedence; self.associativity = associativity
}
}
 
func ==(x: Operator, y: Operator) -> Bool {
// Identified by name
// same operator names are not allowed
return x.name == y.name
}
 
func <(x: Operator, y: Operator) -> Bool {
// compare operators by theirTake precedence and associavity into account
return (x.associativity == .Left && x.precedence == y.precedence) || x.precedence < y.precedence
}
 
extension Set where Element: OperatorType {
func contains(op_ operatorName: String?) -> Bool {
contains { $0.name guard let== operatorName = op else { return false }
}
return contains { $0.name == operatorName }
}
subscript (operatorName: String) -> Element? {
 
get {
subscript (operatorName: String) -> Element? {
filter { $0.name == operatorName }.first
get {
}
return filter { $0.name == operatorName }.first
}
}
}
}
 
// Convenience
extension String {
var isNumber: Bool { return Double(self) != nil }
}
 
struct ShuntingYard {
enum ErrorParseError: ErrorTypeError {
case MismatchedParenthesis(parenthesis: String, expression: String)
case MismatchedParenthesis(String)
case UnrecognizedToken(token: String, expression: String)
case UnrecognizedToken(String)
case ExtraneousToken(token: String, expression: String)
}
}
static func parse(_ input: String, operators: Set<Operator>) throws -> String {
var stack = Stack<String>()
var output = Queue<String>()
let tokens = input.components(separatedBy: " ")
for token in tokens {
// Number?
if token.isNumber {
// Add it to the output queue
output.enqueue(token)
continue
}
// Operator?
if operators.contains(token) {
// While there is a operator on top of the stack and has lower precedence than current operator (token)
while let top = stack.top,
operators.contains(top) && Self.hasLowerPrecedence(token, top, operators) {
// Pop it off to the output queue
output.enqueue(stack.pop()!)
}
// Push current operator (token) onto the operator stack
stack.push(token)
continue
}
// Left parenthesis?
if token == "(" {
// Push it onto the stack
stack.push(token)
continue
}
// Right parenthesis?
if token == ")" {
// Until the token at the top of the stack is a left parenthesis
while let top = stack.top, top != "(" {
// Pop operators off the stack onto the output queue.
output.enqueue(stack.pop()!)
}
// Pop the left parenthesis from the stack without putting it onto the output queue
guard let _ = stack.pop() else {
// If the stack runs out, than there is no matching left parenthesis
throw ParseError.MismatchedParenthesis(parenthesis: ")", expression: input)
}
continue
}
// Token not recognized!
throw ParseError.UnrecognizedToken(token: token, expression: token)
}
// No more tokens
// Still operators on the stack?
while let top = stack.top,
operators.contains(top) {
// Put them onto the output queue
output.enqueue(stack.pop()!)
}
// If the top of the stack is a (left) parenthesis, then there is no matching right parenthesis
// Note: Assume that all operators has been popped and put onto the output queue
if let top = stack.pop() {
throw (
top == "("
? ParseError.MismatchedParenthesis(parenthesis: "(", expression: input)
: ParseError.ExtraneousToken(token: top, expression: input)
)
}
return output.elements.joined(separator: " ")
}
static private func hasLowerPrecedence(_ firstToken: String, _ secondToken: String, _ operators: Set<Operator>) -> Bool {
guard let firstOperator = operators[firstToken],
let secondOperator = operators[secondToken] else {
return false
}
return firstOperator < secondOperator
}
}
 
/* Include in tests
static func parse(input: String, operators: Set<Operator>) throws -> String {
func testParse() throws {
var stack = Stack<String>()
let input = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"
var output = Queue<String>()
let operators: Set<Operator> = [
let tokens = input.componentsSeparatedByString(" ")
Operator("^", 4, .Right),
 
Operator("*", 3, .Left),
for token in tokens {
Operator("/", 3, .Left),
// Wikipedia: if token is a number add it to the output queue
Operator("+", 2, .Left),
if token.isNumber {
Operator("-", 2, .Left)
output.enqueue(token)
]
}
let output = try! ShuntingYard.parse(input, operators: operators)
// Wikipedia: else if token is a operator:
XCTAssertEqual(output, "3 4 2 * 1 5 - 2 3 ^ ^ / +")
else if operators.contains(token) {
// Wikipedia: while there is a operator on top of the stack and has lower precedence than current operator (token)
while operators.contains(stack.top()) && hasLowerPrecedence(token, stack.top()!, operators) {
// Wikipedia: pop it off to the output queue
output.enqueue(stack.pop())
}
// Wikipedia: push current operator (token) onto the operator stack
stack.push(token)
}
// Wikipedia: If the token is a left parenthesis, then push it onto the stack.
else if token == "(" {
stack.push(token)
}
// Wikipedia: If the token is a right parenthesis:
else if token == ")" {
// Wikipedia: Until the token at the top of the stack is a left parenthesis
while !stack.isEmpty && stack.top() != "(" {
// Wikipedia: pop operators off the stack onto the output queue.
output.enqueue(stack.pop())
}
 
// If the stack runs out, than there are mismatched parentheses.
if stack.isEmpty {
throw Error.MismatchedParenthesis(input)
}
 
// Wikipedia: Pop the left parenthesis from the stack, but not onto the output queue.
stack.pop()
}
// if token is not number, operator or a parenthesis, then is not recognized
else {
throw Error.UnrecognizedToken(token)
}
}
 
// Wikipedia: When there are no more tokens to read:
 
// Wikipedia: While there are still operator tokens in the stack:
while operators.contains(stack.top()) {
// Wikipedia: Pop the operator onto the output queue.
output.enqueue(stack.pop())
}
 
// Wikipedia: If the operator token on the top of the stack is a parenthesis, then there are mismatched parentheses
// Note: Assume that all operators has been poped onto the output queue.
if stack.isEmpty == false {
throw Error.MismatchedParenthesis(input)
}
 
return output.elements.joinWithSeparator(" ")
}
 
static private func containsOperator(stack: Stack<String>, _ operators: [String: NSDictionary]) -> Bool {
guard stack.isEmpty == false else { return false }
// Is there a matching operator in the operators set?
return operators[stack.top()!] != nil ? true : false
}
 
static private func hasLowerPrecedence(x: String, _ y: String, _ operators: Set<Operator>) -> Bool {
guard let first = operators[x], let second = operators[y] else { return false }
return first < second
}
}
*/
 
</syntaxhighlight>
let input = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"
let operators: Set<Operator> = [
Operator("^", 4, .Right),
Operator("*", 3, .Left),
Operator("/", 3, .Left),
Operator("+", 2, .Left),
Operator("-", 2, .Left)
]
let output = try! ShuntingYard.parse(input, operators: operators)
 
print("input: \(input)")
print("output: \(output)")
</lang>
{{out}}
<pre>
Line 4,374 ⟶ 5,033:
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
 
# Helpers
Line 4,431 ⟶ 5,090:
}
 
puts [shunting "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3"]</langsyntaxhighlight>
Output:
<pre>
Line 4,488 ⟶ 5,147:
=={{header|UNIX Shell}}==
 
<langsyntaxhighlight lang="bash">#!/bin/sh
 
getopprec() {
Line 4,590 ⟶ 5,249:
}
 
infix 3 + 4 \* 2 / \( 1 - 5 \) ^ 2 ^ 3</langsyntaxhighlight>
 
===Output===
<syntaxhighlight lang="text">Token: 3
Output: 3
Operators:
Line 4,640 ⟶ 5,299:
End parsing
Output: 3 4 2 1 5 - 2 3 ^ ^ / * +
Operators:</langsyntaxhighlight>
 
=={{header|VBA}}==
Line 4,646 ⟶ 5,305:
{{trans|Liberty BASIC}}
 
<langsyntaxhighlight VBAlang="vba">Option Explicit
Option Base 1
 
Line 4,755 ⟶ 5,414:
Function Peek(stack)
Peek = stack(UBound(stack))
End Function</langsyntaxhighlight>
 
{{out}}
Line 4,780 ⟶ 5,439:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<langsyntaxhighlight lang="vbnet">Module Module1
Class SymbolType
Public ReadOnly symbol As String
Line 4,862 ⟶ 5,521:
End Sub
 
End Module</langsyntaxhighlight>
{{out}}
<pre>3: stack[ ] out[ 3 ]
Line 4,881 ⟶ 5,540:
pop: stack[ ] out[ 3 4 2 * 1 5 - 2 3 ^ ^ / + ]
3 4 2 * 1 5 - 2 3 ^ ^ / +</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-seq}}
{{libheader|Wren-pattern}}
<syntaxhighlight lang="wren">import "./seq" for Stack
import "./pattern" for Pattern
 
/* To find out the precedence, we take the index of the
token in the OPS string and divide by 2 (rounding down).
This will give us: 0, 0, 1, 1, 2 */
var ops = "-+/*^"
 
var infixToPostfix = Fn.new { |infix|
var sb = ""
var s = Stack.new()
var p = Pattern.new("+1/s")
for (token in p.splitAll(infix)) {
var c = token[0]
var idx = ops.indexOf(c)
 
// check for operator
if (idx != - 1) {
if (s.isEmpty) {
s.push(idx)
} else {
while (!s.isEmpty) {
var prec2 = (s.peek()/2).floor
var prec1 = (idx/2).floor
if (prec2 > prec1 || (prec2 == prec1 && c != "^")) {
sb = sb + ops[s.pop()] + " "
} else break
}
s.push(idx)
}
} else if (c == "(") {
s.push(-2) // -2 stands for "("
} else if (c == ")") {
// until "(" on stack, pop operators.
while (s.peek() != -2) sb = sb + ops[s.pop()] + " "
s.pop()
} else {
sb = sb + token + " "
}
}
while (!s.isEmpty) sb = sb + ops[s.pop()] + " "
return sb
}
 
var es = [
"3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3",
"( ( 1 + 2 ) ^ ( 3 + 4 ) ) ^ ( 5 + 6 )"
]
for (e in es) {
System.print("Infix : %(e)")
System.print("Postfix : %(infixToPostfix.call(e))\n")
}</syntaxhighlight>
 
{{out}}
<pre>
Infix : 3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3
Postfix : 3 4 2 * 1 5 - 2 3 ^ ^ / +
 
Infix : ( ( 1 + 2 ) ^ ( 3 + 4 ) ) ^ ( 5 + 6 )
Postfix : 1 2 + 3 4 + ^ 5 6 + ^
</pre>
 
=={{header|Xojo}}==
Line 4,886 ⟶ 5,611:
{{trans|VBA}}
 
<syntaxhighlight lang="xojo">
<lang Xojo>
 
Function ShuntingYard(strInfix As String) As String
Line 5,057 ⟶ 5,782:
 
End Function</langsyntaxhighlight>
 
 
Line 5,082 ⟶ 5,807:
Output:
3 4 2 * 1 5 - 2 3 ^ ^ / +</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">int Stack(10);
int SP; \stack pointer
 
proc Push(N);
int N;
[Stack(SP):= N; SP:= SP+1];
 
func Pop;
[SP:= SP-1; return Stack(SP)];
 
func Precedence(Op);
int Op;
case Op of
^+, ^-: return 2;
^*, ^/: return 3;
^^: return 4
other [];
 
proc ShowStack;
int I;
[ChOut(0, 9\tab\);
for I:= 0 to SP-1 do
[ChOut(0, Stack(I)); ChOut(0, ^ )];
CrLf(0);
];
 
char Str;
int Token, Op1, Op2;
[Str:= "3 + 4 * 2 / ( 1 - 5 ) ^^ 2 ^^ 3 ";
SP:= 0;
Text(0, "Input Output Stack^m^j");
loop [repeat Token:= Str(0); Str:= Str+1;
until Token # ^ ; \skip space characters
if Token # $A0 \terminating space\ then
[ChOut(0, Token); ChOut(0, 9\tab\)];
case Token of
^+, ^-, ^*, ^/, ^^:
[Op1:= Token;
loop [if SP <= 0 then quit; \empty
Op2:= Stack(SP-1);
if Op2 = ^( then quit;
if Precedence(Op2) < Precedence(Op1) then quit;
if Precedence(Op2) = Precedence(Op1) then
if Op1 = ^^ then quit;
ChOut(0, Pop);
];
Push(Op1);
];
^(: Push(Token);
^): [while SP > 0 and Stack(SP-1) # ^( do
ChOut(0, Pop);
Pop; \discard left parenthesis
];
$A0: quit \terminating space with MSB set
other ChOut(0, Token); \print single digit number
ShowStack;
];
while SP > 0 do \print any remaining operators
[ChOut(0, 9\tab\);
ChOut(0, Pop);
ShowStack;
];
]</syntaxhighlight>
{{out}}
<pre>
Input Output Stack
3 3
+ +
4 4 +
* + *
2 2 + *
/ * + /
( + / (
1 1 + / (
- + / ( -
5 5 + / ( -
) - + /
^ + / ^
2 2 + / ^
^ + / ^ ^
3 3 + / ^ ^
^ + / ^
^ + /
/ +
+
</pre>
 
=={{header|zkl}}==
{{trans|Go}}
<langsyntaxhighlight lang="zkl">var input="3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3";
var opa=Dictionary("^",T(4,True), "*",T(3,False), // op:(prec,rAssoc)
Line 5,135 ⟶ 5,948:
"Queue|".println(rpn);
println();
}</langsyntaxhighlight>
{{out}}
<pre style="height:20ex;overflow:scroll;">
337

edits