Libraryless. Click here for Pure Java version (9315L/51K).
// https://en.wikipedia.org/wiki/Shunting-yard_algorithm sclass ShuntingYardParser is Steppable { // input LS tok; int iTok = 1; // output new LS outputQueue; // transitional int iLiteralStart; new LS operatorStack; S lastNonSpacer; *() {} *(S s) { this(noTok(s)); } *(LS *tok) {} run { stepAll(this); } public bool step() { if (iTok >= l(tok)) { finishLiteral(); while (nempty(operatorStack)) { var o = popLast(operatorStack); assertNequals(o, "("); outputQueue.add(o); } false; } S t = tok.get(iTok); bool op = isOperator(t), space = isSpacer(t); if (op && space) warn("Operators should not be spacers"); if (eq(t, "(")) { finishLiteral(); operatorStack.add(t); } else if (eq(t, ")")) { finishLiteral(); while (!eq(last(operatorStack), "(")) { assertNempty(operatorStack); outputQueue.add(popLast(operatorStack)); } popLast(operatorStack); } else if (op) { finishLiteral(); S o1 = t, o2; ifdef ShuntingYardParser_debug printVars(+o1, +operatorStack); endifdef while (!eqOneOf(o2 = last(operatorStack), "(", null) && (precedence(o2) > precedence(o1) || precedence(o2) == precedence(o1) && isLeftAssociative(o1))) { ifdef ShuntingYardParser_debug print("popLast"); endifdef outputQueue.add(popLast(operatorStack)); } S lastTokenProcessed = lastNonSpacer; bool unary; if (lastTokenProcessed == null) unary = true; // operator is first token in stream - unary else if (eq(lastTokenProcessed, "(")) unary = true; // directly after opening bracket - unary else if (eq(lastTokenProcessed, ")")) unary = false; // directly after closing bracket - binary else if (!isOperator(lastTokenProcessed)) unary = false; // directly after literal - binary else unary = true; // directly after another operator - unary operatorStack.add(unary ? "u" + o1 : o1); } else if (iLiteralStart == 0) iLiteralStart = iTok; iTok += 2; if (!space) lastNonSpacer = t; true; } // return 0 for non-operator int precedence(S op) { if (eqOneOf(op, "*", "/")) ret 2; if (eqOneOf(op, "+", "-")) ret 1; ret 0; } bool isLeftAssociative(S op) { true; } bool isSpacer(S t) { ret emptyAfterTrim(t); } bool isOperator(S t) { ret !isSpacer(t) && !startsWithLetterOrDigit(t) && !eq(t, "."); } void finishLiteral { if (iLiteralStart == 0) ret; S s = joinSubList(tok, iLiteralStart, iTok-1); if (!isSpacer(s)) outputQueue.add(s); iLiteralStart = 0; } // returns list that can be processed with CalcRPN LS get() { run(); ret outputQueue; } }
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1032659 |
Snippet name: | ShuntingYardParser [parses things like "1+2*(3-4)"] - simple parser with priorities |
Eternal ID of this version: | #1032659/27 |
Text MD5: | 4b3e4c4d7297f457ef437ceed16b70df |
Transpilation MD5: | 124601defb683163c84c37fe87651bdd |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-04-08 18:36:06 |
Source code size: | 3038 bytes / 116 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 228 / 446 |
Version history: | 26 change(s) |
Referenced in: | #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674) #1034914 - ShuntingYardCore - handles operator precences while parsing [OK] #1035190 - ShuntingYardParser_v2 [parses things like "1+2*(3-4)"] - reimplementation over ShuntingYardCore |