lexerState.go 5.5 KB

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