1package lexer 2 3import ( 4 "fmt" 5 6 "github.com/ChrisTrenkamp/goxpath/xconst" 7) 8 9func absLocPathState(l *Lexer) stateFn { 10 l.emit(XItemAbsLocPath) 11 return stepState 12} 13 14func abbrAbsLocPathState(l *Lexer) stateFn { 15 l.emit(XItemAbbrAbsLocPath) 16 return stepState 17} 18 19func relLocPathState(l *Lexer) stateFn { 20 l.emit(XItemRelLocPath) 21 return stepState 22} 23 24func abbrRelLocPathState(l *Lexer) stateFn { 25 l.emit(XItemAbbrRelLocPath) 26 return stepState 27} 28 29func stepState(l *Lexer) stateFn { 30 l.skipWS(true) 31 r := l.next() 32 33 for isElemChar(r) { 34 r = l.next() 35 } 36 37 l.backup() 38 tok := l.input[l.start:l.pos] 39 40 state, err := parseSeparators(l, tok) 41 if err != nil { 42 return l.errorf(err.Error()) 43 } 44 45 return getNextPathState(l, state) 46} 47 48func parseSeparators(l *Lexer, tok string) (XItemType, error) { 49 l.skipWS(false) 50 state := XItemType(XItemQName) 51 r := l.peek() 52 53 if string(r) == ":" && string(l.peekAt(2)) == ":" { 54 var err error 55 if state, err = getAxis(l, tok); err != nil { 56 return state, fmt.Errorf(err.Error()) 57 } 58 } else if string(r) == ":" { 59 state = XItemNCName 60 l.emitVal(state, tok) 61 l.skip(1) 62 l.skipWS(true) 63 } else if string(r) == "@" { 64 state = XItemAbbrAxis 65 l.emitVal(state, tok) 66 l.skip(1) 67 l.skipWS(true) 68 } else if string(r) == "(" { 69 var err error 70 if state, err = getNT(l, tok); err != nil { 71 return state, fmt.Errorf(err.Error()) 72 } 73 } else if len(tok) > 0 { 74 l.emitVal(state, tok) 75 } 76 77 return state, nil 78} 79 80func getAxis(l *Lexer, tok string) (XItemType, error) { 81 var state XItemType 82 for i := range xconst.AxisNames { 83 if tok == xconst.AxisNames[i] { 84 state = XItemAxis 85 } 86 } 87 if state != XItemAxis { 88 return state, fmt.Errorf("Invalid Axis specifier, %s", tok) 89 } 90 l.emitVal(state, tok) 91 l.skip(2) 92 l.skipWS(true) 93 return state, nil 94} 95 96func getNT(l *Lexer, tok string) (XItemType, error) { 97 isNT := false 98 for _, i := range xconst.NodeTypes { 99 if tok == i { 100 isNT = true 101 break 102 } 103 } 104 105 if isNT { 106 return procNT(l, tok) 107 } 108 109 return XItemError, fmt.Errorf("Invalid node-type " + tok) 110} 111 112func procNT(l *Lexer, tok string) (XItemType, error) { 113 state := XItemType(XItemNodeType) 114 l.emitVal(state, tok) 115 l.skip(1) 116 l.skipWS(true) 117 n := l.peek() 118 if tok == xconst.NodeTypeProcInst && (string(n) == `"` || string(n) == `'`) { 119 if err := getStrLit(l, XItemProcLit); err != nil { 120 return state, fmt.Errorf(err.Error()) 121 } 122 l.skipWS(true) 123 n = l.next() 124 } 125 126 if string(n) != ")" { 127 return state, fmt.Errorf("Missing ) at end of NodeType declaration.") 128 } 129 130 l.skip(1) 131 return state, nil 132} 133 134func procFunc(l *Lexer, tok string) error { 135 state := XItemType(XItemFunction) 136 l.emitVal(state, tok) 137 l.skip(1) 138 l.skipWS(true) 139 if string(l.peek()) != ")" { 140 l.emit(XItemArgument) 141 for { 142 for state := startState; state != nil; { 143 state = state(l) 144 } 145 l.skipWS(true) 146 147 if string(l.peek()) == "," { 148 l.emit(XItemArgument) 149 l.skip(1) 150 } else if string(l.peek()) == ")" { 151 l.emit(XItemEndFunction) 152 l.skip(1) 153 break 154 } else if l.peek() == eof { 155 return fmt.Errorf("Missing ) at end of function declaration.") 156 } 157 } 158 } else { 159 l.emit(XItemEndFunction) 160 l.skip(1) 161 } 162 163 return nil 164} 165 166func getNextPathState(l *Lexer, state XItemType) stateFn { 167 isMultiPart := state == XItemAxis || state == XItemAbbrAxis || state == XItemNCName 168 169 l.skipWS(true) 170 171 for string(l.peek()) == "[" { 172 if err := getPred(l); err != nil { 173 return l.errorf(err.Error()) 174 } 175 } 176 177 if string(l.peek()) == "/" && !isMultiPart { 178 l.skip(1) 179 if string(l.peek()) == "/" { 180 l.skip(1) 181 return abbrRelLocPathState 182 } 183 l.skipWS(true) 184 return relLocPathState 185 } else if isMultiPart && isElemChar(l.peek()) { 186 return stepState 187 } 188 189 if isMultiPart { 190 return l.errorf("Step is not complete") 191 } 192 193 l.emit(XItemEndPath) 194 return findOperatorState 195} 196 197func getPred(l *Lexer) error { 198 l.emit(XItemPredicate) 199 l.skip(1) 200 l.skipWS(true) 201 202 if string(l.peek()) == "]" { 203 return fmt.Errorf("Missing content in predicate.") 204 } 205 206 for state := startState; state != nil; { 207 state = state(l) 208 } 209 210 l.skipWS(true) 211 if string(l.peek()) != "]" { 212 return fmt.Errorf("Missing ] at end of predicate.") 213 } 214 l.skip(1) 215 l.emit(XItemEndPredicate) 216 l.skipWS(true) 217 218 return nil 219} 220