11import * as vscode from 'vscode' ;
2- import * as fstream from 'fs' ;
32import * as nls from 'vscode-nls'
43const localize = nls . loadMessageBundle ( )
5-
4+ const symbols :TasmSymbol [ ] = [ ]
5+ let _document :vscode . TextDocument
6+ let docsymbol :vscode . DocumentSymbol [ ] = [ ]
67enum symboltype {
7- macro , procedure , struct , label , asmvar
8+ other ,
9+ macro ,
10+ procedure ,
11+ struct ,
12+ label ,
13+ asmvar ,
14+ segment
15+ }
16+ function SymbolVSCfy ( a :symboltype ) {
17+ let output = vscode . SymbolKind . Null
18+ switch ( a ) {
19+ case symboltype . macro :output = vscode . SymbolKind . Module ; break ;
20+ case symboltype . segment :output = vscode . SymbolKind . Class ; break ;
21+ case symboltype . procedure :output = vscode . SymbolKind . Function ; break ;
22+ case symboltype . struct :output = vscode . SymbolKind . Struct ; break ;
23+ case symboltype . label :output = vscode . SymbolKind . Key ; break ;
24+ case symboltype . asmvar :output = vscode . SymbolKind . Variable ; break ;
25+ }
26+ return output
827}
928class TasmSymbol {
1029 type :number
1130 name :string
1231 location :vscode . Location | undefined
13- constructor ( type : number , name : string , RangeorPosition : vscode . Range | vscode . Position ) {
14- let uri = vscode . window . activeTextEditor ?. document . uri
32+ belong : string | undefined
33+ constructor ( type : number , name : string , RangeorPosition : vscode . Range | vscode . Position , belong ?: string ) {
1534 this . type = type
1635 this . name = name
17- if ( uri ) this . location = new vscode . Location ( uri , RangeorPosition )
36+ if ( _document ) this . location = new vscode . Location ( _document . uri , RangeorPosition )
1837 }
1938 public markdown ( ) :vscode . MarkdownString {
2039 let md = new vscode . MarkdownString ( )
@@ -25,12 +44,13 @@ class TasmSymbol{
2544 case symboltype . procedure :typestr = localize ( "keykind.Procedure" , "procedure" ) ; break ;
2645 case symboltype . struct :typestr = localize ( "keykind.Structure" , "Structure" ) ; break ;
2746 case symboltype . macro :typestr = localize ( "keykind.Macro" , "macro" ) ; break ;
47+ case symboltype . macro :typestr = localize ( "keykind.Segment" , "segment" ) ; break ;
2848 }
2949 md . appendMarkdown ( '**' + typestr + "** " + this . name )
3050 return md
3151 }
3252}
33- enum linetype { other , macro , endm , segment , ends , proc , endp }
53+ enum linetype { other , macro , endm , segment , ends , struct , proc , endp } //暂时先不支持struct因为可能会与ends(segment)冲突
3454
3555export function findSymbol ( word :string ) :TasmSymbol | undefined {
3656 for ( let sym of symbols ) {
@@ -40,76 +60,141 @@ export function findSymbol (word:string):TasmSymbol|undefined{
4060 }
4161 return
4262}
43- const symbols :TasmSymbol [ ] = [ ]
44- function scanline ( line :string ) {
45- let str = line . toLowerCase ( )
46- if ( str . includes ( "macro" ) ) return linetype . macro
47- if ( str . includes ( "endm" ) ) return linetype . endm
48- if ( str . includes ( "segment" ) ) return linetype . segment
49- if ( str . includes ( "ends" ) ) return linetype . ends
50- if ( str . includes ( "proc" ) ) return linetype . proc
51- if ( str . includes ( "endp" ) ) return linetype . endp
63+ class Asmline {
64+ type :linetype
65+ name :string | undefined
66+ line :number
67+ index :number
68+ constructor ( type :linetype , line :number , index :number , name ?:string )
69+ {
70+ this . type = type
71+ this . line = line
72+ this . index = index
73+ this . name = name
74+ }
75+ public selectrange ( ) {
76+ if ( this . name ) return new vscode . Range ( this . line , this . index , this . line , this . index + this . name ?. length )
77+ }
78+ }
79+ function scanline ( item :string , line :number ) :Asmline | null {
80+ let r : RegExpMatchArray | null = null
81+ let asmline :Asmline | null = null
82+ r = item . match ( / ( \w + ) \s + ( \w + ) \s / )
83+ if ( r ) {
84+ let type1 :linetype | undefined
85+ switch ( r [ 2 ] . toUpperCase ( ) ) {
86+ case 'MACRO' :type1 = linetype . macro ; break ;
87+ case 'SEGMENT' :type1 = linetype . segment ; break ;
88+ case 'PROC' :type1 = linetype . proc ; break ;
89+ case 'ENDS' :type1 = linetype . ends ; break ;
90+ case 'ENDP' :type1 = linetype . endp ; break
91+ }
92+ if ( type1 ) asmline = new Asmline ( type1 , line , item . indexOf ( r [ 1 ] ) , r [ 1 ] )
93+ }
94+ r = item . match ( / ( e n d m | E N D M ) / )
95+ if ( r ) asmline = new Asmline ( linetype . endm , line , item . indexOf ( r [ 1 ] ) )
96+ return asmline
5297}
53- async function sacnDoc ( document :string [ ] , alsoVars : boolean = true ) : Promise < number > {
98+ function getvarlabel ( item :string , index :number , belong ?:string ) :vscode . DocumentSymbol | undefined {
99+ let r = item . match ( / \s * ( \w + ) \s * : / )
100+ let vscsymbol :vscode . DocumentSymbol
101+ let name :string
102+ let range :vscode . Range
103+ let srange :vscode . Range
104+ if ( r ) {
105+ name = r [ 1 ]
106+ let start = item . indexOf ( name )
107+ let one :TasmSymbol = new TasmSymbol ( symboltype . label , r [ 1 ] , new vscode . Position ( index , start ) , belong )
108+ symbols . push ( one )
109+ range = new vscode . Range ( index , 0 , start , item . length )
110+ srange = new vscode . Range ( index , start , index , index + r [ 1 ] . length )
111+ let kind = SymbolVSCfy ( symboltype . label )
112+ vscsymbol = new vscode . DocumentSymbol ( name , item , kind , range , srange )
113+ console . log ( vscsymbol )
114+ }
115+ r = item . match ( / \s * ( \w + ) \s * [ d D ] [ b B w W d D f F q Q t T ] / )
116+ if ( r ) {
117+ name = r [ 1 ]
118+ let start = item . indexOf ( r [ 1 ] )
119+ let one :TasmSymbol = new TasmSymbol ( symboltype . asmvar , r [ 1 ] , new vscode . Position ( index , start ) , belong )
120+ symbols . push ( one )
121+ range = new vscode . Range ( index , 0 , start , item . length )
122+ srange = new vscode . Range ( index , start , index , index + r [ 1 ] . length )
123+ return new vscode . DocumentSymbol ( r [ 1 ] , item , SymbolVSCfy ( symboltype . label ) , range , srange )
124+ }
125+ return
126+ }
127+ export function sacnDoc ( document :vscode . TextDocument ) : vscode . DocumentSymbol [ ] {
128+ _document = document
129+ let doc = document . getText ( ) . split ( '\n' )
54130 // scan the document for necessary information
55- let labelreg = / ^ \s * ( \w + ) \s * : /
56- document . forEach (
57- ( item , index , array ) => {
58- let a = labelreg . exec ( item )
59- if ( a ) {
60- let name :string = a [ 1 ]
61- let idx :number = item . indexOf ( a [ 1 ] )
62- let one :TasmSymbol = new TasmSymbol ( symboltype . label , name , new vscode . Position ( index , idx ) )
63- symbols . push ( one )
131+ let docsymbol :vscode . DocumentSymbol [ ] = [ ]
132+ let asmline :Asmline [ ] = [ ]
133+ doc . forEach (
134+ ( item , index ) => {
135+ let line = scanline ( item , index )
136+ if ( line !== null ) asmline . push ( line )
137+ }
138+ )
139+ let skip :boolean , i :number
140+ asmline . forEach (
141+ ( line , index , array ) => {
142+ //是否为宏指令
143+ if ( line . type === linetype . macro ) {
144+ let line_endm :Asmline | undefined
145+ //寻赵宏指令结束的位置
146+ for ( i = index ; i < asmline . length ; i ++ ) {
147+ if ( array [ i ] . type === linetype . endm ) {
148+ line_endm = array [ i ]
149+ break
150+ }
151+ }
152+ //找到宏指令结束标志
153+ if ( line . name && line_endm ?. line ) {
154+ let macrorange = new vscode . Range ( line . line , line . index , line_endm ?. line , line_endm ?. index )
155+ symbols . push ( new TasmSymbol ( symboltype . macro , line . name , macrorange ) )
156+ let varlabel :vscode . DocumentSymbol [ ] = [ ]
157+ let symbol1 = new vscode . DocumentSymbol ( line . name + ": " + getType ( KeywordType . Macro ) , " " , SymbolVSCfy ( symboltype . macro ) , macrorange , new vscode . Range ( line . line , line . index , line . line , line . index + line . name . length ) )
158+ symbol1 . children = varlabel
159+ docsymbol . push ( symbol1 )
160+ }
64161 }
65- let b = item . match ( / \s * ( \w + ) \s * [ d b | D B | d w | D W | d d | D D | d f | D F | d q | D Q | d t | D T ] / )
66- if ( b ) {
67- let name :string = b [ 1 ]
68- let idx :number = item . indexOf ( b [ 1 ] )
69- let one :TasmSymbol = new TasmSymbol ( symboltype . asmvar , name , new vscode . Position ( index , idx ) )
70- symbols . push ( one )
162+ if ( line . type === linetype . segment ) {
163+ let line_ends :Asmline | undefined
164+ //寻赵段结束的位置
165+ for ( i = index ; i < asmline . length ; i ++ ) {
166+ if ( array [ i ] . type === linetype . ends && array [ i ] . name === line . name ) {
167+ line_ends = array [ i ]
168+ break
169+ }
170+ }
171+ //找到逻辑段结束标志
172+ if ( line . name && line_ends ?. line ) {
173+ let range = new vscode . Range ( line . line , line . index , line_ends ?. line , line_ends ?. index )
174+ symbols . push ( new TasmSymbol ( symboltype . segment , line . name , range ) )
175+ let varlabel :vscode . DocumentSymbol [ ] = [ ]
176+ let symbol1 = new vscode . DocumentSymbol ( line . name + ": " + getType ( KeywordType . Segment ) , " " , SymbolVSCfy ( symboltype . segment ) , range , new vscode . Range ( line . line , line . index , line . line , line . index + line . name . length ) )
177+ symbol1 . children = varlabel
178+ docsymbol . push ( symbol1 )
179+ }
71180 }
72- } ,
181+ }
73182 )
74- return new Promise ( resolve => {
75- setTimeout ( ( ) => {
76- resolve ( 2 ) ;
77- } , 10 ) ;
78- } ) ;
79- }
80- const autoScanDoc = async ( change : vscode . TextDocumentChangeEvent ) => {
81- if ( vscode . window . activeTextEditor === undefined ) {
82- return ;
83- }
84- let doc : string = await fstream . readFileSync ( vscode . window . activeTextEditor . document . uri . fsPath , 'utf8' ) ;
85- let fin : string [ ] = doc . split ( '\n' ) ;
86- sacnDoc ( fin ) ;
87- } ;
88- const autoScanDoc2 = async ( change : vscode . TextDocument ) => {
89- let fin = doucmentToStringArray ( change ) ;
90- sacnDoc ( fin ) ;
91- } ;
92- const autoScanDoc3 = async ( change : vscode . TextEditor | undefined ) => {
93- if ( change === undefined ) {
94- return ;
95- }
96- let fin = doucmentToStringArray ( change . document ) ;
97- sacnDoc ( fin ) ;
98- } ;
99- function doucmentToStringArray ( str :vscode . TextDocument ) : string [ ] {
100- let array : string [ ] = [ ] ;
101- for ( let i = 0 ; i < str . lineCount ; i ++ ) {
102- const line = str . lineAt ( i ) ;
103- array . push ( line . text ) ;
183+ docsymbol . forEach (
184+ ( item ) => {
185+ // if(item.kind==SymbolVSCfy(symboltype.macro)){
186+ // let symbol3:vscode.DocumentSymbol|undefined
187+ // for (i=item.range.start.line;i<=item.range.end.line;i++){
188+ // symbol3=getvarlabel(doc[i],i)
189+ // if(symbol3)item.children.push(symbol3)
190+ // }
191+ // }
192+ item . children . push ( new vscode . DocumentSymbol ( "fk" , "fake" , 1 , new vscode . Range ( 1 , 1 , 1 , 1 ) , new vscode . Range ( 1 , 1 , 1 , 1 ) ) )
193+ }
194+ )
195+ return docsymbol
104196 }
105- return array ;
106- }
107- export function scanDoc ( ) {
108- vscode . workspace . onDidChangeTextDocument ( e => autoScanDoc ( e ) ) ;
109- vscode . workspace . onDidOpenTextDocument ( e => autoScanDoc2 ( e ) ) ;
110- vscode . workspace . onDidSaveTextDocument ( e => autoScanDoc2 ( e ) ) ;
111- vscode . window . onDidChangeActiveTextEditor ( e => autoScanDoc3 ( e ) ) ;
112- }
197+
113198const possibleNumbers : string [ ] = [ '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' ] ;
114199
115200export function isNumberStr ( str :string ) : boolean {
@@ -235,7 +320,7 @@ class KeywordDef {
235320 }
236321}
237322enum KeywordType {
238- MacroLabel , File , Instruction , Register , PreCompileCommand , MemoryAllocation , SavedWord , Size , Variable , Method , Structure , Macro , Label
323+ MacroLabel , File , Instruction , Register , PreCompileCommand , MemoryAllocation , SavedWord , Size , Variable , Method , Structure , Macro , Label , Segment
239324}
240325const KEYWORD_DICONTARY : Array < KeywordDef > = [
241326 //Sizes
@@ -544,6 +629,8 @@ export function getType(type : KeywordType) : string {
544629 return localize ( "keykind.Structure" , "(Structure)" ) ;
545630 case KeywordType . Variable :
546631 return localize ( "keykind.Variable" , "(Variable)" ) ;
632+ case KeywordType . Segment :
633+ return localize ( "keykind.Segment" , "(Segment)" ) ;
547634 }
548635 return "(Unknown)" ;
549636}
0 commit comments