September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -0,0 +1,78 @@
|
|||
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 #
|
||||
PROC parse = ( STRING s )STRING:
|
||||
BEGIN
|
||||
# add to the output #
|
||||
PROC output element = ( CHAR c )VOID:
|
||||
BEGIN
|
||||
output[ output pos +:= 1 ] := c;
|
||||
output pos +:= 1
|
||||
END # output element # ;
|
||||
PROC stack op = ( CHAR c )VOID: stack[ stack pos +:= 1 ] := c;
|
||||
# unstacks and returns the top operator on the stack - stops the program if the stack is empty #
|
||||
PROC unstack = CHAR:
|
||||
IF stack pos < 1 THEN
|
||||
# empty stack #
|
||||
print( ( "Stack underflow", newline ) );
|
||||
stop
|
||||
ELSE
|
||||
# still something on the stack to unstack #
|
||||
CHAR result = stack[ stack pos ];
|
||||
stack[ stack pos ] := " ";
|
||||
stack pos -:= 1;
|
||||
result
|
||||
FI # unstack # ;
|
||||
# returns the priority of the operator o - which must be one of "(", "^", "*", "/", "+" or "-" #
|
||||
PROC priority of = ( CHAR o )INT: IF o = "(" THEN -1 ELIF o = "^" THEN 4 ELIF o = "*" OR o = "/" THEN 3 ELSE 2 FI;
|
||||
# returns TRUE if o is a right-associative operator, FALSE otherwise #
|
||||
PROC right = ( CHAR c )BOOL: c = "^";
|
||||
PROC lower or equal priority = ( CHAR c )BOOL:
|
||||
IF stack pos < 1 THEN FALSE # empty stack #
|
||||
ELSE priority of( c ) <= priority of( stack[ stack pos ] )
|
||||
FI # lower or equal priority # ;
|
||||
PROC lower priority = ( CHAR c )BOOL:
|
||||
IF stack pos < 1 THEN FALSE # empty stack #
|
||||
ELSE priority of( c ) < priority of( stack[ stack pos ] )
|
||||
FI # lower priority # ;
|
||||
# max stack size and output size #
|
||||
INT max stack = 32;
|
||||
# stack and output queue #
|
||||
[ 1 : max stack ]CHAR stack;
|
||||
[ 1 : max stack ]CHAR output;
|
||||
FOR c pos TO max stack DO stack[ c pos ] := output[ c pos ] := " " OD;
|
||||
# stack pointer and output queue pointer #
|
||||
INT stack pos := 0;
|
||||
INT output pos := 0;
|
||||
print( ( "Parsing: ", s, newline ) );
|
||||
print( ( "token output stack", newline ) );
|
||||
FOR s pos FROM LWB s TO UPB s DO
|
||||
CHAR c = s[ s pos ];
|
||||
IF c /= " " THEN
|
||||
IF c >= "0" AND c <= "9" THEN output element( c )
|
||||
ELIF c = "(" THEN stack op( c )
|
||||
ELIF c = ")" THEN
|
||||
# close bracket - unstack to the matching "(" and unstack the "(" #
|
||||
WHILE CHAR op char = unstack;
|
||||
op char /= "("
|
||||
DO
|
||||
output element( op char )
|
||||
OD
|
||||
ELIF right( c ) THEN
|
||||
# right associative operator #
|
||||
WHILE lower priority( c ) DO output element( unstack ) OD;
|
||||
stack op( c )
|
||||
ELSE
|
||||
# must be left associative #
|
||||
WHILE lower or equal priority( c ) DO output element( unstack ) OD;
|
||||
stack op( c )
|
||||
FI;
|
||||
print( ( c, " ", output, " ", stack, newline ) )
|
||||
FI
|
||||
OD;
|
||||
WHILE stack pos >= 1 DO output element( unstack ) OD;
|
||||
output[ 1 : output pos ]
|
||||
END # parse # ;
|
||||
|
||||
print( ( "result: ", parse( "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3" ), newline ) )
|
||||
END
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static void Main() {
|
||||
string infix = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3";
|
||||
Console.WriteLine(infix.ToPostfix());
|
||||
}
|
||||
}
|
||||
|
||||
public static class ShuntingYard
|
||||
{
|
||||
private static readonly Dictionary<string, (string symbol, int precedence, bool rightAssociative)> operators
|
||||
= new (string symbol, int precedence, bool rightAssociative) [] {
|
||||
("^", 4, true),
|
||||
("*", 3, false),
|
||||
("/", 3, false),
|
||||
("+", 2, false),
|
||||
("-", 2, false)
|
||||
}.ToDictionary(op => op.symbol);
|
||||
|
||||
public static string ToPostfix(this string infix) {
|
||||
string[] tokens = infix.Split(' ');
|
||||
var stack = new Stack<string>();
|
||||
var output = new List<string>();
|
||||
foreach (string token in tokens) {
|
||||
if (int.TryParse(token, out _)) {
|
||||
output.Add(token);
|
||||
Print(token);
|
||||
} else if (operators.TryGetValue(token, out var op1)) {
|
||||
while (stack.Count > 0 && operators.TryGetValue(stack.Peek(), out var op2)) {
|
||||
int c = op1.precedence.CompareTo(op2.precedence);
|
||||
if (c < 0 || !op1.rightAssociative && c <= 0) {
|
||||
output.Add(stack.Pop());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
stack.Push(token);
|
||||
Print(token);
|
||||
} else if (token == "(") {
|
||||
stack.Push(token);
|
||||
Print(token);
|
||||
} else if (token == ")") {
|
||||
string top = "";
|
||||
while (stack.Count > 0 && (top = stack.Pop()) != "(") {
|
||||
output.Add(top);
|
||||
}
|
||||
if (top != "(") throw new ArgumentException("No matching left parenthesis.");
|
||||
Print(token);
|
||||
}
|
||||
}
|
||||
while (stack.Count > 0) {
|
||||
var top = stack.Pop();
|
||||
if (!operators.ContainsKey(top)) throw new ArgumentException("No matching right parenthesis.");
|
||||
output.Add(top);
|
||||
}
|
||||
Print("pop");
|
||||
return string.Join(" ", output);
|
||||
|
||||
//Yikes!
|
||||
void Print(string action) => Console.WriteLine($"{action + ":",-4} {$"stack[ {string.Join(" ", stack.Reverse())} ]",-18} {$"out[ {string.Join(" ", output)} ]"}");
|
||||
//A little more readable?
|
||||
void Print(string action) => Console.WriteLine("{0,-4} {1,-18} {2}", action + ":", $"stack[ {string.Join(" ", stack.Reverse())} ]", $"out[ {string.Join(" ", output)} ]");
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,11 @@ public class ShuntingYard {
|
|||
}
|
||||
|
||||
static String infixToPostfix(String infix) {
|
||||
/* 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 */
|
||||
final String ops = "-+/*^";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Stack<Integer> s = new Stack<>();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
type associativity = Left | Right;;
|
||||
|
||||
|
||||
let prec op =
|
||||
match op with
|
||||
| "^" -> 4
|
||||
| "*" -> 3
|
||||
| "/" -> 3
|
||||
| "+" -> 2
|
||||
| "-" -> 2
|
||||
| _ -> -1;;
|
||||
|
||||
|
||||
let assoc op =
|
||||
match op with
|
||||
| "^" -> Right
|
||||
| _ -> Left;;
|
||||
|
||||
|
||||
let split_while p =
|
||||
let rec go ls xs =
|
||||
match xs with
|
||||
| x::xs' when p x -> go (x::ls) xs'
|
||||
| _ -> List.rev ls, xs
|
||||
in go [];;
|
||||
|
||||
|
||||
let rec intercalate sep xs =
|
||||
match xs with
|
||||
| [] -> ""
|
||||
| [x] -> x
|
||||
| x::xs' -> x ^ sep ^ intercalate sep xs';;
|
||||
|
||||
|
||||
let shunting_yard =
|
||||
let rec pusher stack queue tkns =
|
||||
match tkns with
|
||||
| [] -> List.rev queue @ stack
|
||||
| "("::tkns' -> pusher ("("::stack) queue tkns'
|
||||
| ")"::tkns' ->
|
||||
let mv, "("::stack' = split_while ((<>) "(") stack in
|
||||
pusher stack' (mv @ queue) tkns'
|
||||
| t::tkns' when prec t < 0 -> pusher stack (t::queue) tkns'
|
||||
| op::tkns' ->
|
||||
let mv_to_queue op2 =
|
||||
(match assoc op with
|
||||
| Left -> prec op <= prec op2
|
||||
| Right -> prec op < prec op2)
|
||||
in
|
||||
let mv, stack' = split_while mv_to_queue stack in
|
||||
pusher (op::stack') (mv @ queue) tkns'
|
||||
in pusher [] [];;
|
||||
|
||||
|
||||
let () =
|
||||
let inp = read_line () in
|
||||
let tkns = String.split_on_char ' ' inp in
|
||||
let postfix = shunting_yard tkns in
|
||||
print_endline (intercalate " " postfix);;
|
||||
|
|
@ -6,8 +6,7 @@ constant operators = {"^","*","/","+","-"},
|
|||
procedure shunting_yard(string infix, string rpn)
|
||||
string res = "", sep = "", top
|
||||
sequence stack = {}
|
||||
--sequence ops = split(infix) -- (only works if () properly spaced)
|
||||
sequence ops = split(substitute_all(infix,{"(",")"},{" ( "," ) "}),' ',0,1)
|
||||
sequence ops = split(substitute_all(infix,{"(",")"},{" ( "," ) "}),' ',no_empty:=1,limit:=0)
|
||||
printf(1,"Infix input: %-30s%s", {infix,iff(show_workings?'\n':'\t')})
|
||||
for i=1 to length(ops) do
|
||||
string op = ops[i]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ var prec = Hash(
|
|||
'+' => 2,
|
||||
'-' => 2,
|
||||
'(' => 1,
|
||||
);
|
||||
)
|
||||
|
||||
var assoc = Hash(
|
||||
'^' => 'right',
|
||||
|
|
@ -13,38 +13,46 @@ var assoc = Hash(
|
|||
'/' => 'left',
|
||||
'+' => 'left',
|
||||
'-' => 'left',
|
||||
);
|
||||
)
|
||||
|
||||
func shunting_yard(prog) {
|
||||
var inp = prog.words;
|
||||
var ops = [];
|
||||
var res = [];
|
||||
var inp = prog.words
|
||||
var ops = []
|
||||
var res = []
|
||||
|
||||
func report (op) {
|
||||
printf("%25s %-7s %10s %s\n",
|
||||
res.join(' '), ops.join(' '), op, inp.join(' '))
|
||||
}
|
||||
|
||||
func report (op) { printf("%25s %-7s %10s %s\n", res.join(' '), ops.join(' '), op, inp.join(' ')) }
|
||||
func shift (t) { report( "shift #{t}"); ops << t }
|
||||
func reduce (t) { report("reduce #{t}"); res << t }
|
||||
|
||||
|
||||
while (inp) {
|
||||
given(var t = inp.shift) {
|
||||
when (/\d/) { reduce(t) }
|
||||
when ('(') { shift(t) }
|
||||
when (')') { var x; while (ops && (x = ops.pop) && (x != '(')) { reduce(x) } }
|
||||
when (')') {
|
||||
while (ops) {
|
||||
(var x = ops.pop) == '(' ? break : reduce(x)
|
||||
}
|
||||
}
|
||||
default {
|
||||
var newprec = prec{t};
|
||||
var newprec = prec{t}
|
||||
while (ops) {
|
||||
var oldprec = prec{ops[-1]};
|
||||
|
||||
var oldprec = prec{ops[-1]}
|
||||
|
||||
break if (newprec > oldprec)
|
||||
break if ((newprec == oldprec) && (assoc{t} == 'right'))
|
||||
|
||||
reduce(ops.pop);
|
||||
|
||||
reduce(ops.pop)
|
||||
}
|
||||
shift(t);
|
||||
shift(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
while (ops) { reduce(ops.pop) }
|
||||
return res
|
||||
}
|
||||
|
||||
say shunting_yard('3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3').join(' ');
|
||||
|
||||
say shunting_yard('3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3').join(' ')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
Function ShuntingYard(strInfix As String) As String
|
||||
|
||||
|
||||
Dim i as Integer
|
||||
Dim token, tokenArray() As String
|
||||
Dim stack(), queue() As Variant
|
||||
Dim discard As String
|
||||
Dim op1, op2 As String
|
||||
|
||||
Dim Left_Brackets, Right_Brackets As Integer
|
||||
|
||||
Dim output As String
|
||||
Dim dbl_output As Double
|
||||
|
||||
|
||||
Left_Brackets = CountFields(strInfix, "(")
|
||||
Right_Brackets = CountFields(strInfix, ")")
|
||||
|
||||
If Left_Brackets = Right_Brackets Then
|
||||
|
||||
|
||||
|
||||
'Get tokens
|
||||
tokenArray = Split(strInfix," ")
|
||||
|
||||
|
||||
|
||||
'Initialize array (removed later)
|
||||
ReDim stack(1)
|
||||
ReDim queue(1)
|
||||
|
||||
'Loop over tokens
|
||||
For i = 0 to tokenArray.Ubound
|
||||
|
||||
|
||||
'i = i + 1
|
||||
If i > UBound(tokenArray) Then
|
||||
Exit For
|
||||
Else
|
||||
token = tokenArray(i ) 'i-1 due to Split returning a Base 0
|
||||
End If
|
||||
If token = "" Then
|
||||
Exit For
|
||||
End If
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Dim stackString As String
|
||||
Dim queuString As String
|
||||
|
||||
for m as Integer = 0 to stack.Ubound
|
||||
stackString = stackString + " " + stack(m)
|
||||
Next
|
||||
|
||||
for m as Integer = 0 to queue.Ubound
|
||||
queuString = queuString + " " + queue(m)
|
||||
Next
|
||||
|
||||
MsgBox(Str(i) + " " + token + " " + stackString + " " + queuString)
|
||||
|
||||
'Window1.txtQueu.Text = Window1.txtQueu.Text + Str(i) + " " + token + " " + stackString + " " + queuString + EndOfLIne
|
||||
|
||||
|
||||
|
||||
|
||||
' If-loop over tokens (either brackets, operators, or numbers)
|
||||
If token = "(" Then
|
||||
stack.Append(token)
|
||||
|
||||
ElseIf token = ")" Then
|
||||
While stack(stack.Ubound) <> "("
|
||||
queue.Append(stack.pop)
|
||||
Wend
|
||||
|
||||
discard = stack.Pop 'discard "("
|
||||
ElseIf isOperator(token) Then
|
||||
op1 = token
|
||||
|
||||
|
||||
//Do While (isOperator(Peek(stack)))
|
||||
While isOperator( stack(stack.Ubound) ) = True
|
||||
op2 = stack(stack.Ubound)
|
||||
If op2 <> "^" And precedence(op1) = precedence(op2) Then
|
||||
'"^" is the only right-associative operator
|
||||
|
||||
queue.Append(stack.pop)
|
||||
|
||||
ElseIf precedence(op1) < precedence(op2) Then
|
||||
queue.Append(stack.Pop)
|
||||
Else
|
||||
Exit While
|
||||
End If
|
||||
Wend
|
||||
//Loop
|
||||
|
||||
|
||||
stack.Append(op1)
|
||||
Else 'number
|
||||
'actually, wrong operator could end up here, like say %
|
||||
'If the token is a number, then add it to the output queue.
|
||||
queue.Append(CStr(token))
|
||||
End If
|
||||
|
||||
|
||||
|
||||
|
||||
Next
|
||||
|
||||
|
||||
|
||||
for i = 0 to queue.Ubound
|
||||
output = output +queue(i) + " "
|
||||
next
|
||||
|
||||
for i = stack.Ubound DownTo 0
|
||||
output = output + stack(i)+" "
|
||||
next
|
||||
|
||||
|
||||
|
||||
While InStr(output, " ") <> 0
|
||||
output = ReplaceAll(output," "," ")
|
||||
Wend
|
||||
|
||||
|
||||
output = Trim(output)
|
||||
|
||||
|
||||
Return output
|
||||
|
||||
Else
|
||||
|
||||
MsgBox("Syntax Error!" + EndOfLine + "Count left brackets: " + Str(Left_Brackets) + EndOfLine +"Count right brackets: " + Str(Right_Brackets))
|
||||
|
||||
End If
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
Function isOperator(op As String) As Boolean
|
||||
|
||||
If InStr("+-*/^", op) <> 0 and Len(op) = 1 Then
|
||||
Return True
|
||||
End If
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
Function precedence(op As String) As Integer
|
||||
|
||||
If isOperator(op) = True Then
|
||||
|
||||
|
||||
|
||||
If op = "+" or op = "-" Then
|
||||
Return 2
|
||||
ElseIf op = "/" or op = "*" Then
|
||||
Return 3
|
||||
ElseIf op = "^" Then
|
||||
Return 4
|
||||
End If
|
||||
|
||||
|
||||
End If
|
||||
|
||||
|
||||
End Function
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
var input="3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3";
|
||||
|
||||
var opa=Dictionary("^",T(4,True), "*",T(3,False), // op:(prec,rAssoc)
|
||||
"/",T(3,False), "+",T(2,False), "-",T(2,False),
|
||||
);
|
||||
|
||||
"infix: ".println(input);
|
||||
"postfix:".println(parseInfix(input));
|
||||
|
||||
fcn parseInfix(e){
|
||||
stack:=List(); // holds operators and left parenthesis
|
||||
rpn:="";
|
||||
foreach tok in (e.split(" ")){
|
||||
switch(tok){
|
||||
case("("){ stack.append(tok) } // push "(" to stack
|
||||
case(")"){
|
||||
while(True){ // pop item ("(" or operator) from stack
|
||||
op:=stack.pop();
|
||||
if(op=="(") break; // discard "("
|
||||
rpn+=" " + op; // add operator to result
|
||||
}
|
||||
}
|
||||
else{ // default
|
||||
o1:=opa.find(tok); // op or Void
|
||||
if(o1){ // token is an operator
|
||||
while(stack){
|
||||
// consider top item on stack
|
||||
op:=stack[-1]; o2:=opa.find(op);
|
||||
if(not o2 or o1[0]>o2[0] or
|
||||
(o1[0]==o2[0] and o1[1])) break;
|
||||
// top item is an operator that needs to come off
|
||||
stack.pop();
|
||||
rpn+=" " + op; // add it to result
|
||||
}
|
||||
// push operator (the new one) to stack
|
||||
stack.append(tok);
|
||||
}else // token is an operand
|
||||
rpn+=(rpn and " " or "") + tok; // add operand to result
|
||||
}
|
||||
} // switch
|
||||
display(tok,rpn,stack);
|
||||
} // foreach
|
||||
// drain stack to result
|
||||
rpn + stack.reverse().concat(" ");
|
||||
}
|
||||
fcn display(tok,rpn,stack){
|
||||
"Token|".println(tok);
|
||||
"Stack|".println(stack.concat());
|
||||
"Queue|".println(rpn);
|
||||
println();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue