-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtokeneval.h
152 lines (129 loc) · 5.84 KB
/
tokeneval.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
; https://mit-license.org/
; Copyright © 2022 Julian Terrell [email protected]
;
; Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
; documentation files (the “Software”), to deal in the Software without restriction, including without limitation
; the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
; and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above
; copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
; TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
; CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
; DEALINGS IN THE SOFTWARE.
; --------------------------------------------------------------------------------------------
; Section: tokeneval.h
; --------------------------------------------------------------------------------------------
; Token evaluation
; --------------------------------------------------------------------------------------------
; macros to aid with parsing long token lists
.ifndef _TOKENEVAL_
_TOKENEVAL_ = 1
.scope tokenListEval
active .set 0 ; token list is being evaluated and related .defines active
tokenOffset .set 0 ; position in the token list
savedTokenOffset .set 0 ; save position to allow restoring previous
tokenCount .set 0 ; total tokens before EOT will be true
verifyTokenOn .set 0 ; verify the tokens when invoking nextToken
.endscope
; --------------------------------------------------------------------------------------------
; Establish a token list to be evaluated
.macro startTokenListEval tokenList, startOffset
.if tokenListEval::active
.error "startTokenListEval is active."
.endif
.ifnblank startOffset
tokenListEval::tokenOffset .set startOffset
.else
tokenListEval::tokenOffset .set 0
.endif
tokenListEval::tokenCount .set .tcount( { tokenList } )
tokenListEval::verifyTokenOn .set 0
tokenListEval::active .set 1
.define thisTokenList () tokenList
.define currentToken () .mid (tokenListEval::tokenOffset, 1, {thisTokenList} )
.define matchToken (t) .match ( {t}, {currentToken} )
.define xmatchToken (t) .xmatch ( {t}, {currentToken} )
.define EOT () ( tokenListEval::tokenOffset + 1 > tokenListEval::tokenCount )
.define currentTokenNumber tokenListEval::tokenOffset
.define allowedTokens
.define tokenErrorMessage ""
.endmacro
; --------------------------------------------------------------------------------------------
; pass a list of tokens that must have a match
; when nextToken is next called
.macro verifyNextToken tokenList, message
.undefine tokenErrorMessage
.ifblank message
.define tokenErrorMessage ""
.else
.define tokenErrorMessage () message
.endif
.undefine allowedTokens
.define allowedTokens () tokenList
tokenListEval::verifyTokenOn .set 1
.endmacro
; don't verify tokens
.macro allowAllTokens
tokenListEval::verifyTokenOn .set 0
.endmacro
; --------------------------------------------------------------------------------------------
; Override the total amount of tokens for current token list
.macro setTokenCount count
tokenListEval::tokenCount .set count
.endmacro
; --------------------------------------------------------------------------------------------
; read the next token and verify it is in the list of allowed tokens if needed
.macro nextToken
.local matchFound
.if !EOT
tokenListEval::tokenOffset .set tokenListEval::tokenOffset + 1
.if (!EOT) && tokenListEval::verifyTokenOn
matchFound .set 0
.repeat .tcount( {allowedTokens} ), ___i
.if .match( {currentToken}, { .mid( ___i, 1, {allowedTokens} ) } )
matchFound .set 1
.endif
.endrepeat
.if !matchFound
; it would be nice to output the offending token, but .string() doesn't work with all tokens
.error .sprintf("Error in expression. %s", tokenErrorMessage)
.fatal "STOP"
.endif
.endif
.endif
.endmacro
; --------------------------------------------------------------------------------------------
; step back one token
.macro previousToken
tokenListEval::tokenOffset .set tokenListEval::tokenOffset - 1
.endmacro
; --------------------------------------------------------------------------------------------
; save/restore position
; can save/restore one position. (Could add support for multiple via stack if needed.)
.macro saveTokenListPosition
tokenListEval::savedTokenOffset .set tokenListEval::tokenOffset
.endmacro
.macro restoreTokenListPosition
tokenListEval::tokenOffset .set tokenListEval::savedTokenOffset
.endmacro
; --------------------------------------------------------------------------------------------
; clear token list evaluation.
.macro endTokenListEval savedOffset
.if tokenListEval::active
.ifnblank savedOffset
savedOffset .set tokenListEval::tokenOffset
.endif
.undefine thisTokenList
.undefine currentToken
.undefine matchToken
.undefine xmatchToken
.undefine EOT
.undefine currentTokenNumber
.undefine allowedTokens
.undefine tokenErrorMessage
tokenListEval::active .set 0
.endif
.endmacro
.endif