source: dev/trunk/ab5.0/abdev/BasicCompiler_Common/src/LexicalAnalyzer_Procedure.cpp@ 572

Last change on this file since 572 was 572, checked in by dai_9181, 16 years ago

ParseDllProc/SetParamsAndReturnTypeForUserProcを実装。

File size: 16.8 KB
RevLine 
[546]1#include "stdafx.h"
2
3using namespace ActiveBasic::Compiler;
4
[571]5bool LexicalAnalyzer::AnalyzeParameter( Parameters &params, const Jenga::Common::Strings &parameterStrings, int nowLine )
[568]6{
7 int i2,i3,sw;
8 char temporary[8192],temp2[VN_SIZE];
9
10 //パラメータ
[571]11 BOOST_FOREACH( const std::string &paramStr, parameterStrings )
12 {
13 int i = 0;
14
15 if( paramStr[i] == '\0' )
[568]16 {
17 break;
18 }
19
20 //ByRef
21 bool isRef;
[571]22 if(paramStr[i]==1&&paramStr[i+1]==ESC_BYVAL){
[568]23 isRef = false;
24 i+=2;
25 }
[571]26 else if(paramStr[i]==1&&paramStr[i+1]==ESC_BYREF){
[568]27 isRef = true;
28 i+=2;
29 }
30 else isRef = false;
31
32 //パラメータ名
33 bool isArray = false;
34 Subscripts subscripts;
35 char name[VN_SIZE];
36 sw=0;
37 for(i2=0;;i++,i2++){
[571]38 if(paramStr[i]=='('){
[568]39 if(!sw) sw=1;
40
[571]41 i3=GetStringInPare(name+i2,paramStr.c_str()+i);
[568]42 i2+=i3-1;
43 i+=i3-1;
44 continue;
45 }
[571]46 if(paramStr[i]=='['){
[568]47 if(!sw) sw=1;
48
[571]49 i3=GetStringInBracket(name+i2,paramStr.c_str()+i);
[568]50 i2+=i3-1;
51 i+=i3-1;
52 continue;
53 }
[571]54 if(!IsVariableChar(paramStr[i])){
[568]55 name[i2]=0;
56 break;
57 }
[571]58 name[i2]=paramStr[i];
[568]59 }
60 if(sw){
61 //配列パラメータ
62 if( isRef == false )
63 {
64 compiler.errorMessenger.Output(29,NULL,nowLine);
65 }
66 isArray = true;
67
68 if((name[i2-2]=='('&&name[i2-1]==')')||
69 (name[i2-2]=='['&&name[i2-1]==']'))
70 {
71 subscripts.push_back( LONG_MAX );
72
73 name[i2-2]=0;
74 }
75 else{
76 GetArrange(name,temp2,subscripts);
77 lstrcpy(name,temp2);
78 }
79
80 i2=lstrlen(name);
81 }
82
83 Type type( DEF_NON );
84 char initValue[8192] = "";
[571]85 if( paramStr[i] == '=' ){
[568]86 i++;
[571]87 i = GetOneParameter( paramStr.c_str(), i, initValue );
[568]88
89 // TODO: エラー用 fix me!!!
90 //cp = nowLine;
91
92 NumOpe_GetType( initValue, GetStringTypeInfo(), type );
93
94 if( IS_LITERAL(type.GetIndex()) )
95 {
96 type.SetIndex( -1 );
97 }
98 }
[571]99 else if(paramStr[i]==1&&paramStr[i+1]==ESC_AS){
[568]100 // As指定
101 i+=2;
102
103 i2=0;
[571]104 while(paramStr[i]=='*'){
105 temporary[i2]=paramStr[i];
[568]106 i++;
107 i2++;
108 }
109 for(;;i++,i2++){
[571]110 if(!IsVariableChar(paramStr[i])){
111 if(paramStr[i]==1&&(paramStr[i+1]==ESC_FUNCTION||paramStr[i+1]==ESC_SUB)){
112 temporary[i2++]=paramStr[i++];
113 temporary[i2]=paramStr[i];
[568]114 continue;
115 }
116 temporary[i2]=0;
117 break;
118 }
[571]119 temporary[i2]=paramStr[i];
[568]120 }
121
122 compiler.StringToType( temporary, type );
123
124 if( type.IsNull() ){
125 compiler.errorMessenger.Output(3,temporary,nowLine);
126 type.SetBasicType( DEF_PTR_VOID );
127 }
128
129 if( type.IsObject() ){
130 if( type.GetClass().IsBlittableType() ){
131 // Blittable型のときは基本型として扱う
132 type = type.GetClass().GetBlittableType();
133 }
134 }
135 }
136 else{
137 type.SetBasicType( Type::GetBasicTypeFromSimpleName(temporary) );
138 compiler.errorMessenger.Output(-103,temporary,nowLine);
139 }
140
141 Parameter *pParam = new Parameter( name, type, isRef, initValue );
142 if( isArray ){
143 pParam->SetArray( subscripts );
144 }
145
146 //パラメータを追加
147 params.push_back( pParam );
148 }
149
150 return true;
151}
152
[572]153bool LexicalAnalyzer::SetParamsAndReturnTypeForUserProc( UserProc &userProc, const char *sourceOfParams, int nowLine, bool isStatic )
154{
155 int i = 0;
156
157 //ソースコードの位置
158 userProc.SetCodePos( nowLine );
159
160 //パラメータ
161 if(sourceOfParams[i]!='('){
162 compiler.errorMessenger.Output(1,NULL,nowLine);
163 return false;
164 }
165 if(sourceOfParams[i + 1]!=')'&& userProc.HasParentClass() ){
166 //クラスのメンバ関数の場合のみ、デストラクタにパラメータがある場合にエラーをだす
167 if(userProc.GetName()[0]=='~'){
168 compiler.errorMessenger.Output(114,NULL,nowLine);
169 return false;
170 }
171 }
172
173 // カッコ内のパラメータ文字列を取得
174 char parametersStr1[8192];
175 char parametersStr2[8192] = "";
176 i += GetStringInPare( parametersStr1, sourceOfParams + i, true );
177 if( sourceOfParams[i] == '(' )
178 {
179 i += GetStringInPare( parametersStr2, sourceOfParams + i, true );
180 }
181
182 // 戻り値文字列を取得
183 char returnTypeStr[VN_SIZE] = "";
184 if( sourceOfParams[i] )
185 {
186 if( sourceOfParams[i] == 1 && sourceOfParams[i+1] == ESC_AS )
187 {
188 if( !userProc.IsFunction() ){
189 // Sub/Macroの場合
190 compiler.errorMessenger.Output(38,userProc.GetName(),nowLine);
191 }
192
193 lstrcpy( returnTypeStr, sourceOfParams + i + 2 );
194 }
195 else
196 {
197 compiler.errorMessenger.Output(1,NULL,nowLine);
198 return false;
199 }
200 }
201
202 Jenga::Common::Strings parameters;
203
204 // パラメータ
205 SplitParameter( parametersStr1, parameters );
206 ActiveBasic::Compiler::LexicalAnalyzer::AnalyzeParameter( userProc.GetParameters(), parameters, nowLine );
207
208 // 省略可能パラメータ(古い仕様。非推奨)
209 userProc.SetSecondParmNum( (int)userProc.GetParameters().size() );
210 SplitParameter( parametersStr2, parameters );
211 ActiveBasic::Compiler::LexicalAnalyzer::AnalyzeParameter( userProc.GetParameters(), parameters, nowLine );
212
213
214 if(returnTypeStr[0]){
215 ///////////////////
216 // 戻り値を取得
217 ///////////////////
218
219 if( !userProc.IsFunction() ){
220 // Sub/Macroの場合
221 compiler.errorMessenger.Output(38,userProc.GetName(),nowLine);
222 }
223
224 if( userProc.HasParentClass() ){
225 if( userProc.GetName() == userProc.GetParentClassPtr()->GetName() ||
226 userProc.GetName()[0]=='~'){
227 //クラスのコンストラクタ、デストラクタがFunction定義の場合はエラーをだす
228 compiler.errorMessenger.Output(115,NULL,nowLine);
229 }
230 }
231
232 compiler.StringToType( returnTypeStr, userProc.ReturnType() );
233 if( userProc.ReturnType().IsNull() )
234 {
235 compiler.errorMessenger.Output(3,returnTypeStr,nowLine);
236 }
237 }
238 else{
239 if( userProc.IsFunction() )
240 {
241 // Function定義なのに、戻り値の型がセットされていない
242 compiler.errorMessenger.Output(-104,userProc.GetName().c_str(),nowLine);
243
244 userProc.ReturnType().SetBasicType( DEF_DOUBLE );
245 }
246 else
247 {
248 //戻り値なしのSub定義
249 userProc.ReturnType().SetNull();
250 }
251 }
252
253 //リアルパラメータ領域を取得(_System_LocalThisを考慮して2つだけ多く確保する場合がある)
254
255 if( userProc.HasParentClass() && isStatic == false ){
256 //オブジェクトメンバの場合は、第一パラメータを_System_LocalThis引き渡し用として利用
257 std::string name = "_System_LocalThis";
258 Type type( DEF_PTR_VOID );
259 userProc.RealParams().push_back( new Parameter( name, type ) );
260 }
261
262 if( userProc.ReturnType().IsStruct() ){
263 //構造体を戻り値として持つ場合
264 //※第一パラメータ(Thisポインタありの場合は第二パラメータ)を戻り値用の参照宣言にする
265
266 std::string name = userProc.GetName();
267 if(name[0]==1&&name[1]==ESC_OPERATOR){
268 name="_System_ReturnValue";
269 }
270 Type type( DEF_STRUCT, userProc.ReturnType().GetIndex() );
271 userProc.RealParams().push_back( new Parameter( name, type, true ) );
272 }
273
274 //パラメータをコピー
275 BOOST_FOREACH( Parameter *pParam, userProc.GetParameters() ){
276 userProc.RealParams().push_back( new Parameter( *pParam ) );
277 }
278
279 return true;
280}
281
[546]282UserProc* LexicalAnalyzer::ParseUserProc( const NamespaceScopes &namespaceScopes, const NamespaceScopesCollection &importedNamespaces, char *buffer,int nowLine,bool isVirtual,CClass *pobj_c, bool isStatic, char *interfaceName )
283{
284 int i2,i3;
285 char temporary[8192];
286
287 int i=1;
288
289 Procedure::Kind kind = Procedure::Sub;
290 bool isMacro = false;
291 if(buffer[i]==ESC_FUNCTION) kind = Procedure::Function;
292 if(buffer[i]==ESC_MACRO){
293 isMacro = true;
294 }
295
296 i++;
297
298 bool isCdecl = false;
299 bool isExport = false;
300 while(1){
301 if(buffer[i]==1&&buffer[i+1]==ESC_CDECL&& isCdecl == false ){
302 isCdecl = true;
303
304 i+=2;
305 }
306 else if(buffer[i]==1&&buffer[i+1]==ESC_EXPORT&& isExport == false ){
307 isExport = true;
308
309 i+=2;
310 }
311 else break;
312 }
313
314 i2=0;
315 if(buffer[i]==1&&buffer[i+1]==ESC_OPERATOR){
316 if(!pobj_c){
317 compiler.errorMessenger.Output(126,NULL,nowLine);
318 return 0;
319 }
320
321 //オペレータの場合
322 temporary[i2++]=buffer[i++];
323 temporary[i2++]=buffer[i++];
324
325 int iCalcId;
326 if(buffer[i]=='='&&buffer[i+1]=='='){
327 iCalcId=CALC_EQUAL;
328 i3=2;
329 }
330 else if(buffer[i]=='='){
331 iCalcId=CALC_SUBSITUATION;
332 i3=1;
333 }
334 else if(buffer[i]=='('){
335 iCalcId=CALC_AS;
336 i3=0;
337 }
338 else if(buffer[i]=='['&&buffer[i+1]==']'&&buffer[i+2]=='='){
339 iCalcId=CALC_ARRAY_SET;
340 i3=3;
341 }
342 else if(buffer[i]=='['&&buffer[i+1]==']'){
343 iCalcId=CALC_ARRAY_GET;
344 i3=2;
345 }
346 else{
347 iCalcId=GetCalcId(buffer+i,&i3);
348 i3++;
349 }
350 if(!iCalcId){
351 compiler.errorMessenger.Output(1,NULL,nowLine);
352 return 0;
353 }
354 temporary[i2++]=iCalcId;
355 temporary[i2]=0;
356
357 i+=i3;
358 }
359 else{
360 if(pobj_c){
361 //クラスメンバの場合、デストラクタには~が付くことを考慮
362 if(buffer[i]=='~'){
363 temporary[i2]='~';
364 i++;
365 i2++;
366 }
367 }
368
369 for(;;i++,i2++){
370 if(!IsVariableChar(buffer[i])){
371 temporary[i2]=0;
372 break;
373 }
374 temporary[i2]=buffer[i];
375 }
376
377 char parentName[VN_SIZE], memberName[VN_SIZE];
378 ReferenceKind refKind;
379 if( SplitMemberName( temporary, parentName, memberName, refKind ) )
380 {
381 if( pobj_c )
382 {
383 if( interfaceName )
384 {
385 lstrcpy( interfaceName, parentName );
386 }
387 else
388 {
389 compiler.errorMessenger.OutputFatalError();
390 return NULL;
391 }
392
393 char dummyMemberName[VN_SIZE];
394 if( SplitMemberName( memberName, parentName, dummyMemberName, refKind ) )
395 {
396 compiler.errorMessenger.Output(69,temporary,nowLine);
397 return NULL;
398 }
399 }
400 else
401 {
402 compiler.errorMessenger.Output(68,temporary,nowLine);
403 return NULL;
404 }
405
406 lstrcpy( temporary, memberName );
407 }
408 }
409
410 if( isMacro ){
411 //大文字に変換
412 CharUpper(temporary);
413 }
414
415 if(!pobj_c){
416 //クラスメンバ以外の場合のみ
417 //重複チェック
418
419 if(GetDeclareHash(temporary)){
420 compiler.errorMessenger.Output(15,temporary,nowLine);
421 return 0;
422 }
423 }
424
425 UserProc *pUserProc = new UserProc( namespaceScopes, importedNamespaces, temporary, kind, isMacro, isCdecl, isExport );
426 pUserProc->SetParentClass( pobj_c );
427
428 // 親インターフェイスをセット
429 if( interfaceName && interfaceName[0] )
430 {
431 ::Interface *pTargetInterface = NULL;
432 BOOST_FOREACH( ::Interface *pInterface, pobj_c->GetInterfaces() )
433 {
434 if( pInterface->GetClass().GetName() == interfaceName )
435 {
436 pTargetInterface = pInterface;
437 break;
438 }
439 }
440 pUserProc->SetInterface( pTargetInterface );
441 }
442
443 if(isExport){
444 pUserProc->Using();
445 }
446
447 // パラメータを解析
448 // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
[572]449 SetParamsAndReturnTypeForUserProc( *pUserProc, buffer + i, nowLine, isStatic );
[546]450
451 pUserProc->_paramStr = buffer + i;
452
453 return pUserProc;
454}
455
[572]456DllProc *LexicalAnalyzer::ParseDllProc(const NamespaceScopes &namespaceScopes, char *buffer,int nowLine)
457{
458 int i2;
459
460 int i=0;
461
462 //Sub/Function
463 Procedure::Kind kind = Procedure::Sub;
464 if(buffer[i]==ESC_SUB){
465 }
466 else if(buffer[i]==ESC_FUNCTION){
467 kind = Procedure::Function;
468 }
469 else{
470 compiler.errorMessenger.Output(1,NULL,nowLine);
471 return NULL;
472 }
473 i++;
474
475 //プロシージャ名
476 char procName[VN_SIZE];
477 bool isCdecl = false;
478 for(i2=0;;i++,i2++){
479 if(buffer[i]==1&&buffer[i+1]==ESC_CDECL){
480 isCdecl = true;
481
482 i+=2;
483 procName[i2]=0;
484 break;
485 }
486 if(buffer[i]==','){
487 procName[i2]=0;
488 break;
489 }
490 if(buffer[i]=='\0'){
491 compiler.errorMessenger.Output(1,NULL,nowLine);
492 return NULL;
493 }
494 procName[i2]=buffer[i];
495 }
496 i++;
497
498 //ユーザー定義関数との重複チェック
499 if(GetSubHash(procName)){
500 compiler.errorMessenger.Output(15,procName,nowLine);
501 return NULL;
502 }
503
504
505 //ライブラリ
506 char dllFileName[MAX_PATH];
507 i = GetOneParameter( buffer, i, dllFileName );
508 Type resultType;
509 _int64 i64data;
510 if( !StaticCalculation( true, dllFileName, 0, &i64data, resultType ) ){
511 return NULL;
512 }
513 if( resultType.GetBasicType() != typeOfPtrChar ){
514 compiler.errorMessenger.Output(1,NULL,nowLine);
515 return NULL;
516 }
517 lstrcpy( dllFileName, (char *)i64data );
518 CharUpper(dllFileName);
519 if(!strstr(dllFileName,".")){
520 lstrcat(dllFileName,".DLL");
521 if(lstrlen(dllFileName)>=16){
522 compiler.errorMessenger.Output(7,NULL,nowLine);
523 return NULL;
524 }
525 }
526
527 //エイリアス
528 char alias[VN_SIZE];
529 i = GetOneParameter( buffer, i, alias );
530 if( alias[0] ){
531 if( !StaticCalculation( true, alias, 0, &i64data, resultType ) ){
532 return NULL;
533 }
534 if( resultType.GetBasicType() != typeOfPtrChar ){
535 compiler.errorMessenger.Output(1,NULL,nowLine);
536 return NULL;
537 }
538 lstrcpy( alias, (char *)i64data );
539 }
540 else{
541 //省略されたときは関数名
542 lstrcpy( alias, procName );
543 }
544
545
546 // オブジェクトを生成
547 DllProc *pDllProc = new DllProc( namespaceScopes, procName, kind, isCdecl, dllFileName, alias );
548
549 // パラメータを解析
550 // ※第1パラメータにに指定するデータの例:"( s As String ) As String"
551 pDllProc->SetParamsAndReturnType( buffer + i, nowLine );
552
553 // パラメータのエラーチェック
554 BOOST_FOREACH( const Parameter *pParam, pDllProc->Params() ){
555 if( pParam->IsObject() ){
556 compiler.errorMessenger.Output(25,pParam->GetVarName(),nowLine);
557 }
558 if( !pParam->IsRef() ){
559 if( pParam->IsStruct() ){
560 compiler.errorMessenger.Output(28,pParam->GetVarName(),nowLine);
561 }
562 }
563 }
564
565 //戻り値のエラーチェック
566 if( pDllProc->IsFunction() ){
567 // Function定義
568
569 if( pDllProc->ReturnType().IsObject() ){
570 // DLL関数ではオブジェクトを戻り値にできない
571 compiler.errorMessenger.Output(40,pDllProc->GetName(),nowLine);
572 }
573 }
574
575 return pDllProc;
576}
577
[552]578void LexicalAnalyzer::CollectProcedures( const char *source, UserProcs &userProcs, DllProcs &dllProcs )
[546]579{
580 extern HANDLE hHeap;
581 int i,i2,i3;
582 char temporary[8192];
583
584 // 名前空間管理
585 NamespaceScopes &namespaceScopes = compiler.GetNamespaceSupporter().GetLivingNamespaceScopes();
586 namespaceScopes.clear();
587
588 // Importsされた名前空間の管理
589 NamespaceScopesCollection &importedNamespaces = compiler.GetNamespaceSupporter().GetImportedNamespaces();
590 importedNamespaces.clear();
591
592 i=-1;
593 while(1){
594 i++;
595
596 if(source[i]==1&&(source[i+1]==ESC_CLASS||source[i+1]==ESC_INTERFACE)){
597 /* Class ~ End Class
598 Interface ~ End Interface
599 を飛び越す */
600 i3=GetEndXXXCommand(source[i+1]);
601 for(i+=2,i2=0;;i++,i2++){
602 if(source[i]=='\0') break;
603 if(source[i]==1&&source[i+1]==(char)i3){
604 i++;
605 break;
606 }
607 }
608 if(source[i]=='\0') break;
609 continue;
610 }
611
612 if( source[i] == 1 && source[i+1] == ESC_NAMESPACE ){
613 for(i+=2,i2=0;;i2++,i++){
614 if( IsCommandDelimitation( source[i] ) ){
615 temporary[i2]=0;
616 break;
617 }
618 temporary[i2]=source[i];
619 }
620 namespaceScopes.push_back( temporary );
621
622 continue;
623 }
624 else if( source[i] == 1 && source[i+1] == ESC_ENDNAMESPACE ){
625 if( namespaceScopes.size() <= 0 ){
626 compiler.errorMessenger.Output(12, "End Namespace", i );
627 }
628 else{
629 namespaceScopes.pop_back();
630 }
631
632 i += 2;
633 continue;
634 }
635 else if( source[i] == 1 && source[i+1] == ESC_IMPORTS ){
636 for(i+=2,i2=0;;i2++,i++){
637 if( IsCommandDelimitation( source[i] ) ){
638 temporary[i2]=0;
639 break;
640 }
641 temporary[i2]=source[i];
642 }
643 if( !compiler.GetNamespaceSupporter().ImportsNamespace( temporary ) )
644 {
645 compiler.errorMessenger.Output(64,temporary,cp );
646 }
647
648 continue;
649 }
650 else if( source[i] == 1 && source[i+1] == ESC_CLEARNAMESPACEIMPORTED ){
651 importedNamespaces.clear();
652 continue;
653 }
654
655 if(source[i]==1&&source[i+1]==ESC_DECLARE){
656 for(i+=2,i2=0;;i2++,i++){
657 if(source[i]=='\n'){
658 temporary[i2]=0;
659 break;
660 }
661 temporary[i2]=source[i];
662 if(source[i]=='\0') break;
663 }
[572]664 DllProc *pDllProc = ParseDllProc( namespaceScopes, temporary, i );
665 dllProcs.Put( pDllProc );
[546]666
667 continue;
668 }
669 if(source[i]==1&&(source[i+1]==ESC_SUB||source[i+1]==ESC_FUNCTION||source[i+1]==ESC_MACRO)){
670 char statementChar = source[i+1];
671
672 for(i2=0;;i2++,i++){
673 if(IsCommandDelimitation(source[i])){
674 temporary[i2]=0;
675 break;
676 }
677 temporary[i2]=source[i];
678 if(source[i]=='\0') break;
679 }
680
681 UserProc *pUserProc = ParseUserProc( namespaceScopes, importedNamespaces, temporary, i, false, NULL, false );
682 userProcs.Insert( pUserProc, i );
683
684 /* Sub ~ End Sub
685 Function ~ End Function
686 Macro ~ End Macro
687 を飛び越す */
688 char endStatementChar = GetEndXXXCommand( statementChar );
689 for(i2=0;;i++,i2++){
690 if( source[i] == '\0' ) break;
691 if( source[i] == 1 && source[i+1] == endStatementChar ){
692 i++;
693 break;
694 }
695 }
696 if(source[i]=='\0') break;
697 continue;
698 }
699
700 //次の行
701 for(;;i++){
702 if(IsCommandDelimitation(source[i])) break;
703 }
704 if(source[i]=='\0') break;
705 }
706
707 ////////////
708 // 特殊関数
709 ////////////
710 namespaceScopes.clear();
711 importedNamespaces.clear();
712
713 compiler.globalAreaProcName = "_System_GlobalArea_" + compiler.GetModuleName();
714 sprintf(temporary,"%c%c%s()",1,ESC_SUB,compiler.globalAreaProcName.c_str());
715 UserProc *pUserProc = ParseUserProc( namespaceScopes, importedNamespaces, temporary, 0, false, NULL, false );
716 userProcs.Insert( pUserProc, i );
717}
Note: See TracBrowser for help on using the repository browser.