Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

116
LINES

< > BotCompany Repo | #1032659 // ShuntingYardParser [parses things like "1+2*(3-4)"] - simple parser with priorities

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (9315L/51K).

1  
// https://en.wikipedia.org/wiki/Shunting-yard_algorithm
2  
3  
sclass ShuntingYardParser is Steppable {
4  
  // input
5  
  LS tok;
6  
  int iTok = 1;
7  
  
8  
  // output
9  
  new LS outputQueue;
10  
  
11  
  // transitional
12  
  int iLiteralStart;
13  
  new LS operatorStack;
14  
  S lastNonSpacer;
15  
  
16  
  *() {}
17  
  *(S s) { this(noTok(s)); }
18  
  *(LS *tok) {}
19  
  
20  
  run { stepAll(this); }
21  
  
22  
  public bool step() {
23  
    if (iTok >= l(tok)) {
24  
      finishLiteral();
25  
      while (nempty(operatorStack)) {
26  
        var o = popLast(operatorStack);
27  
        assertNequals(o, "(");
28  
        outputQueue.add(o);
29  
      }
30  
      false;
31  
    }
32  
    
33  
    S t = tok.get(iTok);
34  
    bool op = isOperator(t), space = isSpacer(t);
35  
    if (op && space) warn("Operators should not be spacers");
36  
    
37  
    if (eq(t, "(")) {
38  
      finishLiteral();
39  
      operatorStack.add(t);
40  
    } else if (eq(t, ")")) {
41  
      finishLiteral();
42  
      while (!eq(last(operatorStack), "(")) {
43  
        assertNempty(operatorStack);
44  
        outputQueue.add(popLast(operatorStack));
45  
      }
46  
      popLast(operatorStack);
47  
    } else if (op) {
48  
      finishLiteral();
49  
      S o1 = t, o2;
50  
      ifdef ShuntingYardParser_debug
51  
        printVars(+o1, +operatorStack);
52  
      endifdef
53  
      while (!eqOneOf(o2 = last(operatorStack), "(", null)
54  
        && (precedence(o2) > precedence(o1)
55  
        ||  precedence(o2) == precedence(o1) && isLeftAssociative(o1))) {
56  
          ifdef ShuntingYardParser_debug
57  
            print("popLast");
58  
          endifdef
59  
          outputQueue.add(popLast(operatorStack));
60  
        }
61  
        
62  
      S lastTokenProcessed = lastNonSpacer;      
63  
      bool unary;
64  
      if (lastTokenProcessed == null)
65  
        unary = true; // operator is first token in stream - unary
66  
      else if (eq(lastTokenProcessed, "("))
67  
        unary = true; // directly after opening bracket - unary
68  
      else if (eq(lastTokenProcessed, ")"))
69  
        unary = false; // directly after closing bracket - binary
70  
      else if (!isOperator(lastTokenProcessed))
71  
        unary = false; // directly after literal - binary
72  
      else
73  
        unary = true; // directly after another operator - unary
74  
75  
      operatorStack.add(unary ? "u" + o1 : o1);
76  
    } else if (iLiteralStart == 0)
77  
      iLiteralStart = iTok;
78  
    
79  
    iTok += 2;
80  
     
81  
    if (!space) lastNonSpacer = t;
82  
83  
    true;
84  
  }
85  
  
86  
  // return 0 for non-operator
87  
  int precedence(S op) {
88  
    if (eqOneOf(op, "*", "/")) ret 2;
89  
    if (eqOneOf(op, "+", "-")) ret 1;
90  
    ret 0;
91  
  }
92  
  bool isLeftAssociative(S op) { true; }
93  
  
94  
  bool isSpacer(S t) {
95  
    ret emptyAfterTrim(t);
96  
  }
97  
  
98  
  bool isOperator(S t) {
99  
    ret !isSpacer(t)
100  
      && !startsWithLetterOrDigit(t) && !eq(t, ".");
101  
  }
102  
  
103  
  void finishLiteral {
104  
    if (iLiteralStart == 0) ret;
105  
    S s = joinSubList(tok, iLiteralStart, iTok-1);
106  
    if (!isSpacer(s))
107  
      outputQueue.add(s);
108  
    iLiteralStart = 0;
109  
  }
110  
  
111  
  // returns list that can be processed with CalcRPN
112  
  LS get() {
113  
    run();
114  
    ret outputQueue;
115  
  }
116  
}

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: 227 / 445
Version history: 26 change(s)
Referenced in: [show references]