lexerState.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. package govaluate
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. type lexerState struct {
  7. isEOF bool
  8. isNullable bool
  9. kind TokenKind
  10. validNextKinds []TokenKind
  11. }
  12. // lexer states.
  13. // Constant for all purposes except compiler.
  14. var validLexerStates = []lexerState{
  15. lexerState{
  16. kind: UNKNOWN,
  17. isEOF: false,
  18. isNullable: true,
  19. validNextKinds: []TokenKind{
  20. PREFIX,
  21. NUMERIC,
  22. BOOLEAN,
  23. VARIABLE,
  24. PATTERN,
  25. FUNCTION,
  26. STRING,
  27. TIME,
  28. CLAUSE,
  29. },
  30. },
  31. lexerState{
  32. kind: CLAUSE,
  33. isEOF: false,
  34. isNullable: true,
  35. validNextKinds: []TokenKind{
  36. PREFIX,
  37. NUMERIC,
  38. BOOLEAN,
  39. VARIABLE,
  40. PATTERN,
  41. FUNCTION,
  42. STRING,
  43. TIME,
  44. CLAUSE,
  45. CLAUSE_CLOSE,
  46. },
  47. },
  48. lexerState{
  49. kind: CLAUSE_CLOSE,
  50. isEOF: true,
  51. isNullable: true,
  52. validNextKinds: []TokenKind{
  53. COMPARATOR,
  54. MODIFIER,
  55. NUMERIC,
  56. BOOLEAN,
  57. VARIABLE,
  58. STRING,
  59. PATTERN,
  60. TIME,
  61. CLAUSE,
  62. CLAUSE_CLOSE,
  63. LOGICALOP,
  64. TERNARY,
  65. SEPARATOR,
  66. },
  67. },
  68. lexerState{
  69. kind: NUMERIC,
  70. isEOF: true,
  71. isNullable: false,
  72. validNextKinds: []TokenKind{
  73. MODIFIER,
  74. COMPARATOR,
  75. LOGICALOP,
  76. CLAUSE_CLOSE,
  77. TERNARY,
  78. SEPARATOR,
  79. },
  80. },
  81. lexerState{
  82. kind: BOOLEAN,
  83. isEOF: true,
  84. isNullable: false,
  85. validNextKinds: []TokenKind{
  86. MODIFIER,
  87. COMPARATOR,
  88. LOGICALOP,
  89. CLAUSE_CLOSE,
  90. TERNARY,
  91. SEPARATOR,
  92. },
  93. },
  94. lexerState{
  95. kind: STRING,
  96. isEOF: true,
  97. isNullable: false,
  98. validNextKinds: []TokenKind{
  99. MODIFIER,
  100. COMPARATOR,
  101. LOGICALOP,
  102. CLAUSE_CLOSE,
  103. TERNARY,
  104. SEPARATOR,
  105. },
  106. },
  107. lexerState{
  108. kind: TIME,
  109. isEOF: true,
  110. isNullable: false,
  111. validNextKinds: []TokenKind{
  112. MODIFIER,
  113. COMPARATOR,
  114. LOGICALOP,
  115. CLAUSE_CLOSE,
  116. SEPARATOR,
  117. },
  118. },
  119. lexerState{
  120. kind: PATTERN,
  121. isEOF: true,
  122. isNullable: false,
  123. validNextKinds: []TokenKind{
  124. MODIFIER,
  125. COMPARATOR,
  126. LOGICALOP,
  127. CLAUSE_CLOSE,
  128. SEPARATOR,
  129. },
  130. },
  131. lexerState{
  132. kind: VARIABLE,
  133. isEOF: true,
  134. isNullable: false,
  135. validNextKinds: []TokenKind{
  136. MODIFIER,
  137. COMPARATOR,
  138. LOGICALOP,
  139. CLAUSE_CLOSE,
  140. TERNARY,
  141. SEPARATOR,
  142. },
  143. },
  144. lexerState{
  145. kind: MODIFIER,
  146. isEOF: false,
  147. isNullable: false,
  148. validNextKinds: []TokenKind{
  149. PREFIX,
  150. NUMERIC,
  151. VARIABLE,
  152. FUNCTION,
  153. STRING,
  154. BOOLEAN,
  155. CLAUSE,
  156. CLAUSE_CLOSE,
  157. },
  158. },
  159. lexerState{
  160. kind: COMPARATOR,
  161. isEOF: false,
  162. isNullable: false,
  163. validNextKinds: []TokenKind{
  164. PREFIX,
  165. NUMERIC,
  166. BOOLEAN,
  167. VARIABLE,
  168. FUNCTION,
  169. STRING,
  170. TIME,
  171. CLAUSE,
  172. CLAUSE_CLOSE,
  173. PATTERN,
  174. },
  175. },
  176. lexerState{
  177. kind: LOGICALOP,
  178. isEOF: false,
  179. isNullable: false,
  180. validNextKinds: []TokenKind{
  181. PREFIX,
  182. NUMERIC,
  183. BOOLEAN,
  184. VARIABLE,
  185. FUNCTION,
  186. STRING,
  187. TIME,
  188. CLAUSE,
  189. CLAUSE_CLOSE,
  190. },
  191. },
  192. lexerState{
  193. kind: PREFIX,
  194. isEOF: false,
  195. isNullable: false,
  196. validNextKinds: []TokenKind{
  197. NUMERIC,
  198. BOOLEAN,
  199. VARIABLE,
  200. FUNCTION,
  201. CLAUSE,
  202. CLAUSE_CLOSE,
  203. },
  204. },
  205. lexerState{
  206. kind: TERNARY,
  207. isEOF: false,
  208. isNullable: false,
  209. validNextKinds: []TokenKind{
  210. PREFIX,
  211. NUMERIC,
  212. BOOLEAN,
  213. STRING,
  214. TIME,
  215. VARIABLE,
  216. FUNCTION,
  217. CLAUSE,
  218. SEPARATOR,
  219. },
  220. },
  221. lexerState{
  222. kind: FUNCTION,
  223. isEOF: false,
  224. isNullable: false,
  225. validNextKinds: []TokenKind{
  226. CLAUSE,
  227. },
  228. },
  229. lexerState{
  230. kind: SEPARATOR,
  231. isEOF: false,
  232. isNullable: true,
  233. validNextKinds: []TokenKind{
  234. PREFIX,
  235. NUMERIC,
  236. BOOLEAN,
  237. STRING,
  238. TIME,
  239. VARIABLE,
  240. FUNCTION,
  241. CLAUSE,
  242. },
  243. },
  244. }
  245. func (this lexerState) canTransitionTo(kind TokenKind) bool {
  246. for _, validKind := range this.validNextKinds {
  247. if validKind == kind {
  248. return true
  249. }
  250. }
  251. return false
  252. }
  253. func checkExpressionSyntax(tokens []ExpressionToken) error {
  254. var state lexerState
  255. var lastToken ExpressionToken
  256. var err error
  257. state = validLexerStates[0]
  258. for _, token := range tokens {
  259. if !state.canTransitionTo(token.Kind) {
  260. // call out a specific error for tokens looking like they want to be functions.
  261. if lastToken.Kind == VARIABLE && token.Kind == CLAUSE {
  262. return errors.New("Undefined function " + lastToken.Value.(string))
  263. }
  264. firstStateName := fmt.Sprintf("%s [%v]", state.kind.String(), lastToken.Value)
  265. nextStateName := fmt.Sprintf("%s [%v]", token.Kind.String(), token.Value)
  266. return errors.New("Cannot transition token types from " + firstStateName + " to " + nextStateName)
  267. }
  268. state, err = getLexerStateForToken(token.Kind)
  269. if err != nil {
  270. return err
  271. }
  272. if !state.isNullable && token.Value == nil {
  273. errorMsg := fmt.Sprintf("Token kind '%v' cannot have a nil value", token.Kind.String())
  274. return errors.New(errorMsg)
  275. }
  276. lastToken = token
  277. }
  278. if !state.isEOF {
  279. return errors.New("Unexpected end of expression")
  280. }
  281. return nil
  282. }
  283. func getLexerStateForToken(kind TokenKind) (lexerState, error) {
  284. for _, possibleState := range validLexerStates {
  285. if possibleState.kind == kind {
  286. return possibleState, nil
  287. }
  288. }
  289. errorMsg := fmt.Sprintf("No lexer state found for token kind '%v'\n", kind.String())
  290. return validLexerStates[0], errors.New(errorMsg)
  291. }