1
+ # Scanner for AppleScript Created by Sebastian Yepes F.
2
+ # Web: http://sebastian.yepes.in
3
+ # e-Mail: sebastian@yepes.in
4
+
5
+ module CodeRay
6
+ module Scanners
7
+
8
+ class AppleScript < Scanner
9
+
10
+ register_for :applescript
11
+
12
+ RESERVED_WORDS = [
13
+ '#include' , 'for' , 'foreach' , 'if' , 'elseif' , 'else' , 'while' , 'do' , 'dowhile' , 'end' ,
14
+ 'switch' , 'case' , 'return' , 'break' , 'continue' , 'in' , 'to' , 'of' , 'repeat' , 'tell' , 'then' , 'as'
15
+ ]
16
+
17
+ KEYWORD_OPERATOR = [
18
+ 'is greater than' , 'comes after' , 'is less than' , 'comes before' ,
19
+ 'is greater than or equal to' , 'is less than or equal to' , 'is equal to' ,
20
+ 'is' , 'is not equal to' , 'is not' , 'contains' , 'does not contain' , 'is in' ,
21
+ 'is not in' , 'starts with' , 'ends with'
22
+ ]
23
+
24
+
25
+ DIRECTIVES = [
26
+ 'activate' , '#endinitclip' , '#initclip' , '__proto__' , '_accProps' , '_alpha' , '_currentframe' ,
27
+ '_droptarget' , '_focusrect' , '_framesloaded' , '_height' , '_highquality' , '_lockroot' ,
28
+ '_name' , '_parent' , '_quality' , '_root' , '_rotation' , '_soundbuftime' , '_target' , '_totalframes' ,
29
+ '_url' , '_visible' , '_width' , '_x' , '_xmouse' , '_xscale' , '_y' , '_ymouse' , '_yscale' , 'abs' ,
30
+ 'Accessibility' , 'acos' , 'activityLevel' , 'add' , 'addListener' , 'addPage' , 'addProperty' ,
31
+ 'addRequestHeader' , 'align' , 'allowDomain' , 'allowInsecureDomain' , 'and' , 'appendChild' ,
32
+ 'apply' , 'Arguments' , 'Array' , 'asfunction' , 'asin' , 'atan' , 'atan2' , 'attachAudio' , 'attachMovie' ,
33
+ 'attachSound' , 'attachVideo' , 'attributes' , 'autosize' , 'avHardwareDisable' , 'background' ,
34
+ 'backgroundColor' , 'BACKSPACE' , 'bandwidth' , 'beginFill' , 'beginGradientFill' , 'blockIndent' ,
35
+ 'bold' , 'Boolean' , 'border' , 'borderColor' , 'bottomScroll' , 'bufferLength' , 'bufferTime' ,
36
+ 'builtInItems' , 'bullet' , 'Button' , 'bytesLoaded' , 'bytesTotal' , 'call' , 'callee' , 'caller' ,
37
+ 'Camera' , 'capabilities' , 'CAPSLOCK' , 'caption' , 'catch' , 'ceil' , 'charAt' , 'charCodeAt' ,
38
+ 'childNodes' , 'chr' , 'clear' , 'clearInterval' , 'cloneNode' , 'close' , 'Color' , 'concat' ,
39
+ 'connect' , 'condenseWhite' , 'constructor' , 'contentType' , 'ContextMenu' , 'ContextMenuItem' ,
40
+ 'CONTROL' , 'copy' , 'cos' , 'createElement' , 'createEmptyMovieClip' , 'createTextField' ,
41
+ 'createTextNode' , 'currentFps' , 'curveTo' , 'CustomActions' , 'customItems' , 'data' , 'Date' ,
42
+ 'deblocking' , 'delete' , 'DELETEKEY' , 'docTypeDecl' , 'domain' , 'DOWN' ,
43
+ 'duplicateMovieClip' , 'duration' , 'dynamic' , 'E' , 'embedFonts' , 'enabled' ,
44
+ 'endFill' , 'ENTER' , 'eq' , 'Error' , 'ESCAPE(Konstante)' , 'escape(Funktion)' , 'eval' ,
45
+ 'exactSettings' , 'exp' , 'extends' , 'finally' , 'findText' , 'firstChild' , 'floor' ,
46
+ 'flush' , 'focusEnabled' , 'font' , 'fps' , 'fromCharCode' , 'fscommand' ,
47
+ 'gain' , 'ge' , 'get' , 'getAscii' , 'getBeginIndex' , 'getBounds' , 'getBytesLoaded' , 'getBytesTotal' ,
48
+ 'getCaretIndex' , 'getCode' , 'getCount' , 'getDate' , 'getDay' , 'getDepth' , 'getEndIndex' , 'getFocus' ,
49
+ 'getFontList' , 'getFullYear' , 'getHours' , 'getInstanceAtDepth' , 'getLocal' , 'getMilliseconds' ,
50
+ 'getMinutes' , 'getMonth' , 'getNewTextFormat' , 'getNextHighestDepth' , 'getPan' , 'getProgress' ,
51
+ 'getProperty' , 'getRGB' , 'getSeconds' , 'getSelected' , 'getSelectedText' , 'getSize' , 'getStyle' ,
52
+ 'getStyleNames' , 'getSWFVersion' , 'getText' , 'getTextExtent' , 'getTextFormat' , 'getTextSnapshot' ,
53
+ 'getTime' , 'getTimer' , 'getTimezoneOffset' , 'getTransform' , 'getURL' , 'getUTCDate' , 'getUTCDay' ,
54
+ 'getUTCFullYear' , 'getUTCHours' , 'getUTCMilliseconds' , 'getUTCMinutes' , 'getUTCMonth' , 'getUTCSeconds' ,
55
+ 'getVersion' , 'getVolume' , 'getYear' , 'globalToLocal' , 'goto' , 'gotoAndPlay' , 'gotoAndStop' ,
56
+ 'hasAccessibility' , 'hasAudio' , 'hasAudioEncoder' , 'hasChildNodes' , 'hasEmbeddedVideo' , 'hasMP3' ,
57
+ 'hasPrinting' , 'hasScreenBroadcast' , 'hasScreenPlayback' , 'hasStreamingAudio' , 'hasStreamingVideo' ,
58
+ 'hasVideoEncoder' , 'height' , 'hide' , 'hideBuiltInItems' , 'hitArea' , 'hitTest' , 'hitTestTextNearPos' ,
59
+ 'HOME' , 'hscroll' , 'html' , 'htmlText' , 'ID3' , 'ifFrameLoaded' , 'ignoreWhite' , 'implements' ,
60
+ 'import' , 'indent' , 'index' , 'indexOf' , 'Infinity' , '-Infinity' , 'INSERT' , 'insertBefore' , 'install' ,
61
+ 'instanceof' , 'int' , 'interface' , 'isActive' , 'isDebugger' , 'isDown' , 'isFinite' , 'isNaN' , 'isToggled' ,
62
+ 'italic' , 'join' , 'Key' , 'language' , 'lastChild' , 'lastIndexOf' , 'le' , 'leading' , 'LEFT' , 'leftMargin' ,
63
+ 'length' , 'level' , 'lineStyle' , 'lineTo' , 'list' , 'LN10' , 'LN2' , 'load' , 'loadClip' , 'loaded' , 'loadMovie' ,
64
+ 'loadMovieNum' , 'loadSound' , 'loadVariables' , 'loadVariablesNum' , 'LoadVars' , 'LocalConnection' ,
65
+ 'localFileReadDisable' , 'localToGlobal' , 'log' , 'LOG10E' , 'LOG2E' , 'manufacturer' , 'Math' , 'max' ,
66
+ 'MAX_VALUE' , 'maxChars' , 'maxhscroll' , 'maxscroll' , 'mbchr' , 'mblength' , 'mbord' , 'mbsubstring' , 'menu' ,
67
+ 'message' , 'Microphone' , 'min' , 'MIN_VALUE' , 'MMExecute' , 'motionLevel' , 'motionTimeOut' , 'Mouse' ,
68
+ 'mouseWheelEnabled' , 'moveTo' , 'Movieclip' , 'MovieClipLoader' , 'multiline' , 'muted' , 'name' , 'names' , 'NaN' ,
69
+ 'ne' , 'NEGATIVE_INFINITY' , 'NetConnection' , 'NetStream' , 'newline' , 'nextFrame' ,
70
+ 'nextScene' , 'nextSibling' , 'nodeName' , 'nodeType' , 'nodeValue' , 'not' , 'Number' , 'Object' ,
71
+ 'on' , 'onActivity' , 'onChanged' , 'onClipEvent' , 'onClose' , 'onConnect' , 'onData' , 'onDragOut' ,
72
+ 'onDragOver' , 'onEnterFrame' , 'onID3' , 'onKeyDown' , 'onKeyUp' , 'onKillFocus' , 'onLoad' , 'onLoadComplete' ,
73
+ 'onLoadError' , 'onLoadInit' , 'onLoadProgress' , 'onLoadStart' , 'onMouseDown' , 'onMouseMove' , 'onMouseUp' ,
74
+ 'onMouseWheel' , 'onPress' , 'onRelease' , 'onReleaseOutside' , 'onResize' , 'onRollOut' , 'onRollOver' ,
75
+ 'onScroller' , 'onSelect' , 'onSetFocus' , 'onSoundComplete' , 'onStatus' , 'onUnload' , 'onUpdate' , 'onXML' ,
76
+ 'or(logischesOR)' , 'ord' , 'os' , 'parentNode' , 'parseCSS' , 'parseFloat' , 'parseInt' , 'parseXML' , 'password' ,
77
+ 'pause' , 'PGDN' , 'PGUP' , 'PI' , 'pixelAspectRatio' , 'play' , 'playerType' , 'pop' , 'position' ,
78
+ 'POSITIVE_INFINITY' , 'pow' , 'prevFrame' , 'previousSibling' , 'prevScene' , 'print' , 'printAsBitmap' ,
79
+ 'printAsBitmapNum' , 'PrintJob' , 'printNum' , 'private' , 'prototype' , 'public' , 'push' , 'quality' ,
80
+ 'random' , 'rate' , 'registerClass' , 'removeListener' , 'removeMovieClip' , 'removeNode' , 'removeTextField' ,
81
+ 'replaceSel' , 'replaceText' , 'resolutionX' , 'resolutionY' , 'restrict' , 'reverse' , 'RIGHT' ,
82
+ 'rightMargin' , 'round' , 'scaleMode' , 'screenColor' , 'screenDPI' , 'screenResolutionX' , 'screenResolutionY' ,
83
+ 'scroll' , 'seek' , 'selectable' , 'Selection' , 'send' , 'sendAndLoad' , 'separatorBefore' , 'serverString' ,
84
+ 'set' , 'setvariable' , 'setBufferTime' , 'setClipboard' , 'setDate' , 'setFocus' , 'setFullYear' , 'setGain' ,
85
+ 'setHours' , 'setInterval' , 'setMask' , 'setMilliseconds' , 'setMinutes' , 'setMode' , 'setMonth' ,
86
+ 'setMotionLevel' , 'setNewTextFormat' , 'setPan' , 'setProperty' , 'setQuality' , 'setRate' , 'setRGB' ,
87
+ 'setSeconds' , 'setSelectColor' , 'setSelected' , 'setSelection' , 'setSilenceLevel' , 'setStyle' ,
88
+ 'setTextFormat' , 'setTime' , 'setTransform' , 'setUseEchoSuppression' , 'setUTCDate' , 'setUTCFullYear' ,
89
+ 'setUTCHours' , 'setUTCMilliseconds' , 'setUTCMinutes' , 'setUTCMonth' , 'setUTCSeconds' , 'setVolume' ,
90
+ 'setYear' , 'SharedObject' , 'SHIFT(Konstante)' , 'shift(Methode)' , 'show' , 'showMenu' , 'showSettings' ,
91
+ 'silenceLevel' , 'silenceTimeout' , 'sin' , 'size' , 'slice' , 'smoothing' , 'sort' , 'sortOn' , 'Sound' , 'SPACE' ,
92
+ 'splice' , 'split' , 'sqrt' , 'SQRT1_2' , 'SQRT2' , 'Stage' , 'start' , 'startDrag' , 'static' , 'status' , 'stop' ,
93
+ 'stopAllSounds' , 'stopDrag' , 'StyleSheet(Klasse)' , 'styleSheet(Eigenschaft)' , 'substr' ,
94
+ 'substring' , 'super' , 'swapDepths' , 'System' , 'TAB' , 'tabChildren' , 'tabEnabled' , 'tabIndex' ,
95
+ 'tabStops' , 'tan' , 'target' , 'targetPath' , 'tellTarget' , 'text' , 'textColor' , 'TextField' , 'TextFormat' ,
96
+ 'textHeight' , 'TextSnapshot' , 'textWidth' , 'this' , 'throw' , 'time' , 'toggleHighQuality' , 'toLowerCase' ,
97
+ 'toString' , 'toUpperCase' , 'trace' , 'trackAsMenu' , 'try' , 'type' , 'typeof' , 'undefined' ,
98
+ 'underline' , 'unescape' , 'uninstall' , 'unloadClip' , 'unloadMovie' , 'unLoadMovieNum' , 'unshift' , 'unwatch' ,
99
+ 'UP' , 'updateAfterEvent' , 'updateProperties' , 'url' , 'useCodePage' , 'useEchoSuppression' , 'useHandCursor' ,
100
+ 'UTC' , 'valueOf' , 'variable' , 'version' , 'Video' , 'visible' , 'void' , 'watch' , 'width' ,
101
+ 'with' , 'wordwrap' , 'XML' , 'xmlDecl' , 'XMLNode' , 'XMLSocket'
102
+ ]
103
+
104
+ PREDEFINED_TYPES = [
105
+ 'boolean' , 'small integer' , 'integer' , 'double integer' ,
106
+ 'small real' , 'real' , 'date' , 'list' , 'record' , 'string' , 'class'
107
+ ]
108
+
109
+ PREDEFINED_CONSTANTS = [
110
+ 'pi' , 'true' , 'false' ,
111
+ 'application responses' , 'case' , 'diacriticals' , 'expansion' , 'hyphens' , 'punctuation' , 'white space' ,
112
+ 'seconds' , 'minutes' , 'hours' , 'days' , 'weeks' ,
113
+ 'Monday' , 'Tuesday' , 'Wednesday' , 'Thursday' , 'Friday' , 'Saturday' , 'Sunday' , 'Mon' , 'Tue' , 'Wed' , 'Thu' , 'Fri' , 'Sat' , 'Sun' ,
114
+ 'January' , 'February' , 'March' , 'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' , 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' , 'Oct' , 'Nov' , 'Dec' ,
115
+ 'anything' , 'current application' , 'it' , 'me' , 'missing value' , 'my' , 'result' ,
116
+ 'yes' , 'no' , 'ask' ,
117
+ 'return' , 'space' , 'tab' ,
118
+ 'all caps' , 'all lowercase' , 'bold' , 'condensed' , 'expanded' , 'hidden' , 'italic' , 'outline' , 'plain' , 'shadow' , 'small caps' , 'strikethrough' , 'subscript' , 'superscript' , 'underline' ,
119
+ 'version'
120
+ ]
121
+
122
+ PLAIN_STRING_CONTENT = {
123
+ "'" => /[^'\n ]+/ ,
124
+ '"' => /[^"\n ]+/ ,
125
+ }
126
+
127
+
128
+ IDENT_KIND = CaseIgnoringWordList . new ( :ident ) .
129
+ add ( RESERVED_WORDS , :reserved ) .
130
+ add ( KEYWORD_OPERATOR , :operator ) .
131
+ add ( DIRECTIVES , :directive ) .
132
+ add ( PREDEFINED_TYPES , :pre_type ) .
133
+ add ( PREDEFINED_CONSTANTS , :pre_constant )
134
+
135
+
136
+
137
+ def scan_tokens tokens , options
138
+
139
+ state = :initial
140
+ plain_string_content = @plain_string_content
141
+
142
+ until eos?
143
+
144
+ kind = nil
145
+ match = nil
146
+
147
+ if state == :initial
148
+
149
+ if scan ( /\s +/x )
150
+ kind = :space
151
+
152
+ elsif scan ( %r! \{ \$ [^}]* \} ? | \( \* \$ (?: .*? \* \) | .* ) !mx )
153
+ kind = :preprocessor
154
+
155
+ elsif scan ( /^[\s \t ]*--.*/x )
156
+ kind = :comment
157
+ elsif scan ( /\( \* (?: .*? \* \) $ | .* )/mx )
158
+ kind = :comment
159
+
160
+ elsif scan ( / [-+*\/ =<>:;,.@\^ |\( \) \[ \] ]+ /x )
161
+ kind = :operator
162
+
163
+ elsif match = scan ( / [A-Za-z_][A-Za-z_0-9]* /x )
164
+ kind = IDENT_KIND [ match ]
165
+
166
+ elsif match = scan ( / ' ( [^\n ']|'' ) (?:'|$) /x )
167
+ tokens << [ :open , :char ]
168
+ tokens << [ "'" , :delimiter ]
169
+ tokens << [ self [ 1 ] , :content ]
170
+ tokens << [ "'" , :delimiter ]
171
+ tokens << [ :close , :char ]
172
+ next
173
+
174
+ elsif match = scan ( /["']/ )
175
+ tokens << [ :open , :string ]
176
+ state = :string
177
+ plain_string_content = PLAIN_STRING_CONTENT [ match ]
178
+ kind = :delimiter
179
+
180
+ else
181
+ kind = :plain
182
+ getch
183
+
184
+ end
185
+
186
+ elsif state == :string
187
+ if scan ( plain_string_content )
188
+ kind = :content
189
+ elsif scan ( /['"]/ )
190
+ tokens << [ matched , :delimiter ]
191
+ tokens << [ :close , :string ]
192
+ state = :initial
193
+ next
194
+ elsif scan ( / \\ | $ /x )
195
+ tokens << [ :close , :string ]
196
+ kind = :error
197
+ state = :initial
198
+ end
199
+
200
+ else
201
+ raise_inspect "else case \" reached; %p not handled." % peek ( 1 ) , tokens
202
+ end
203
+
204
+ match ||= matched
205
+ if $DEBUG and not kind
206
+ raise_inspect 'Error token %p in line %d' %
207
+ [ [ match , kind ] , line ] , tokens
208
+ end
209
+ raise_inspect 'Empty token' , tokens unless match
210
+ tokens << [ match , kind ]
211
+
212
+ end
213
+ tokens
214
+ end
215
+
216
+ end
217
+
218
+ end
219
+ end
0 commit comments