|
|
|
@ -69,12 +69,17 @@ func shuntingYard(re string) string {
|
|
|
|
|
if len(opStack) == 0 {
|
|
|
|
|
opStack = append(opStack, c)
|
|
|
|
|
} else {
|
|
|
|
|
if priority(c) > priority(peek(opStack)) { // 2a
|
|
|
|
|
topStack, err := peek(opStack)
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic("ERROR: Operator without operand.")
|
|
|
|
|
}
|
|
|
|
|
if priority(c) > priority(topStack) { // 2a
|
|
|
|
|
opStack = append(opStack, c)
|
|
|
|
|
} else {
|
|
|
|
|
for len(opStack) > 0 && priority(c) <= priority(peek(opStack)) { // 2b
|
|
|
|
|
to_append := pop(&opStack)
|
|
|
|
|
for priority(c) <= priority(topStack) { // 2b
|
|
|
|
|
to_append := mustPop(&opStack)
|
|
|
|
|
outQueue = append(outQueue, to_append)
|
|
|
|
|
topStack, _ = peek(opStack)
|
|
|
|
|
}
|
|
|
|
|
opStack = append(opStack, c)
|
|
|
|
|
}
|
|
|
|
@ -84,17 +89,21 @@ func shuntingYard(re string) string {
|
|
|
|
|
opStack = append(opStack, c)
|
|
|
|
|
}
|
|
|
|
|
if c == ')' {
|
|
|
|
|
for peek(opStack) != '(' {
|
|
|
|
|
to_append := pop(&opStack)
|
|
|
|
|
// Keep popping from opStack until we encounter an opening parantheses. Panic if we reach the end of the stack.
|
|
|
|
|
for val, err := peek(opStack); val != '('; val, err = peek(opStack) {
|
|
|
|
|
if err != nil {
|
|
|
|
|
panic("ERROR: Imbalanced parantheses.")
|
|
|
|
|
}
|
|
|
|
|
to_append := mustPop(&opStack)
|
|
|
|
|
outQueue = append(outQueue, to_append)
|
|
|
|
|
}
|
|
|
|
|
_ = pop(&opStack) // Get rid of opening parantheses
|
|
|
|
|
_ = mustPop(&opStack) // Get rid of opening parantheses
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pop all remaining operators (and append to outQueue)
|
|
|
|
|
for len(opStack) > 0 {
|
|
|
|
|
to_append := pop(&opStack)
|
|
|
|
|
to_append := mustPop(&opStack)
|
|
|
|
|
outQueue = append(outQueue, to_append)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -118,15 +127,15 @@ func thompson(re string) *State {
|
|
|
|
|
// Must be an operator if it isn't alphanumeric
|
|
|
|
|
switch c {
|
|
|
|
|
case CONCAT:
|
|
|
|
|
s2 := pop(&nfa)
|
|
|
|
|
s1 := pop(&nfa)
|
|
|
|
|
s2 := mustPop(&nfa)
|
|
|
|
|
s1 := mustPop(&nfa)
|
|
|
|
|
for i := range s1.output {
|
|
|
|
|
s1.output[i].transitions[s2.content] = append(s1.output[i].transitions[s2.content], s2)
|
|
|
|
|
}
|
|
|
|
|
s1.output = s2.output
|
|
|
|
|
nfa = append(nfa, s1)
|
|
|
|
|
case '*': // Create a 0-state, concat the popped state after it, concat the 0-state after the popped state
|
|
|
|
|
s1 := pop(&nfa)
|
|
|
|
|
s1 := mustPop(&nfa)
|
|
|
|
|
stateToAdd := &State{}
|
|
|
|
|
stateToAdd.transitions = make(map[int][]*State)
|
|
|
|
|
stateToAdd.content = EPSILON
|
|
|
|
@ -139,7 +148,7 @@ func thompson(re string) *State {
|
|
|
|
|
stateToAdd.transitions[s1.content] = append(stateToAdd.transitions[s1.content], s1)
|
|
|
|
|
nfa = append(nfa, stateToAdd)
|
|
|
|
|
case '+':
|
|
|
|
|
s1 := pop(&nfa)
|
|
|
|
|
s1 := mustPop(&nfa)
|
|
|
|
|
for i := range s1.output {
|
|
|
|
|
s1.output[i].transitions[s1.content] = append(s1.output[i].transitions[s1.content], s1)
|
|
|
|
|
}
|
|
|
|
@ -148,8 +157,8 @@ func thompson(re string) *State {
|
|
|
|
|
s1.output = append(s1.output, s1)
|
|
|
|
|
nfa = append(nfa, s1)
|
|
|
|
|
case '|':
|
|
|
|
|
s1 := pop(&nfa)
|
|
|
|
|
s2 := pop(&nfa)
|
|
|
|
|
s1 := mustPop(&nfa)
|
|
|
|
|
s2 := mustPop(&nfa)
|
|
|
|
|
s3 := State{}
|
|
|
|
|
s3.transitions = make(map[int][]*State)
|
|
|
|
|
s3.output = append(s3.output, s1.output...)
|
|
|
|
|