From ae219f763adb81f160564f8bfbc45f9b263b047a Mon Sep 17 00:00:00 2001 From: Aadhavan Srinivasan Date: Sun, 27 Oct 2024 15:30:33 -0400 Subject: [PATCH] Added alternate function, removed relevant code from main; also started working on escape characters --- main.go | 29 +++++++++++++---------------- nfa.go | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/main.go b/main.go index 2cbf1e2..f4b83fc 100644 --- a/main.go +++ b/main.go @@ -54,7 +54,7 @@ func shuntingYard(re string) string { outQueue := make([]rune, 0) // Output queue // Actual algorithm - for _, c := range re_postfix { + for i := 0; i < len(re_postfix); i++ { /* Two cases: 1. Current character is alphanumeric - send to output queue 2. Current character is operator - do the following: @@ -65,9 +65,19 @@ func shuntingYard(re string) string { 3. If current character is '(', push to opStack 4. If current character is ')', pop from opStack (and append to outQueue) until '(' is found. Discard parantheses. */ + c := re_postfix[i] if isAlphaNum(c) { outQueue = append(outQueue, c) + continue } + // Escape character - NOT IMPLEMENTED YET - DO NOT USE + // if c == '\\' { // Escape character - next character is treated as alphanum + // if i == len(re_postfix)-1 { // End of string - panic, because backslash is an escape character (something needs to come after it) + // panic("ERROR: Backslash with no escape character.") + // } + // outQueue = append(outQueue, re_postfix[i+1]) + // } + if isOperator(c) { if len(opStack) == 0 { opStack = append(opStack, c) @@ -146,21 +156,8 @@ func thompson(re string) *State { case '|': s1 := mustPop(&nfa) s2 := mustPop(&nfa) - s3 := State{} - s3.transitions = make(map[int][]*State) - s3.output = append(s3.output, s1.output...) - s3.output = append(s3.output, s2.output...) - // Unique append is used here (and elsewhere) to ensure that, - // for any given transition, a state can only be mentioned once. - // For example, given the transition 'a', the state 's1' can only be mentioned once. - // This would lead to multiple instances of the same set of match indices, since both - // 's1' states would be considered to match. - s3.transitions[s1.content] = unique_append(s3.transitions[s1.content], s1) - s3.transitions[s2.content] = unique_append(s3.transitions[s2.content], s2) - s3.content = EPSILON - s3.isEmpty = true - - nfa = append(nfa, &s3) + s3 := alternate(s1, s2) + nfa = append(nfa, s3) } } if len(nfa) != 1 { diff --git a/nfa.go b/nfa.go index 2e5fd7c..4e7cba3 100644 --- a/nfa.go +++ b/nfa.go @@ -74,3 +74,21 @@ func kleene(s1 State) *State { toReturn.transitions[s1.content] = unique_append(toReturn.transitions[s1.content], &s1) return toReturn } + +func alternate(s1 *State, s2 *State) *State { + toReturn := &State{} + toReturn.transitions = make(map[int][]*State) + toReturn.output = append(toReturn.output, s1.output...) + toReturn.output = append(toReturn.output, s2.output...) + // Unique append is used here (and elsewhere) to ensure that, + // for any given transition, a state can only be mentioned once. + // For example, given the transition 'a', the state 's1' can only be mentioned once. + // This would lead to multiple instances of the same set of match indices, since both + // 's1' states would be considered to match. + toReturn.transitions[s1.content] = unique_append(toReturn.transitions[s1.content], s1) + toReturn.transitions[s2.content] = unique_append(toReturn.transitions[s2.content], s2) + toReturn.content = EPSILON + toReturn.isEmpty = true + + return toReturn +}