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, 15 years ago

ParseDllProc?/SetParamsAndReturnTypeForUserProcを実装。

File size: 16.8 KB
Line 
1#include "stdafx.h"
2
3using namespace ActiveBasic::Compiler;
4
5bool LexicalAnalyzer::AnalyzeParameter( Parameters &params, const Jenga::Common::Strings &parameterStrings, int nowLine )
6{
7    int i2,i3,sw;
8    char temporary[8192],temp2[VN_SIZE];
9
10    //パラメータ
11    BOOST_FOREACH( const std::string &paramStr, parameterStrings )
12    {
13        int i = 0;
14
15        if( paramStr[i] == '\0' )
16        {
17            break;
18        }
19
20        //ByRef
21        bool isRef;
22        if(paramStr[i]==1&&paramStr[i+1]==ESC_BYVAL){
23            isRef = false;
24            i+=2;
25        }
26        else if(paramStr[i]==1&&paramStr[i+1]==ESC_BYREF){
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++){
38            if(paramStr[i]=='('){
39                if(!sw) sw=1;
40
41                i3=GetStringInPare(name+i2,paramStr.c_str()+i);
42                i2+=i3-1;
43                i+=i3-1;
44                continue;
45            }
46            if(paramStr[i]=='['){
47                if(!sw) sw=1;
48
49                i3=GetStringInBracket(name+i2,paramStr.c_str()+i);
50                i2+=i3-1;
51                i+=i3-1;
52                continue;
53            }
54            if(!IsVariableChar(paramStr[i])){
55                name[i2]=0;
56                break;
57            }
58            name[i2]=paramStr[i];
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] = "";
85        if( paramStr[i] == '=' ){
86            i++;
87            i = GetOneParameter( paramStr.c_str(), i, initValue );
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        }
99        else if(paramStr[i]==1&&paramStr[i+1]==ESC_AS){
100            // As指定
101            i+=2;
102
103            i2=0;
104            while(paramStr[i]=='*'){
105                temporary[i2]=paramStr[i];
106                i++;
107                i2++;
108            }
109            for(;;i++,i2++){
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];
114                        continue;
115                    }
116                    temporary[i2]=0;
117                    break;
118                }
119                temporary[i2]=paramStr[i];
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
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
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"
449    SetParamsAndReturnTypeForUserProc( *pUserProc, buffer + i, nowLine, isStatic );
450
451    pUserProc->_paramStr = buffer + i;
452
453    return pUserProc;
454}
455
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
578void LexicalAnalyzer::CollectProcedures( const char *source, UserProcs &userProcs, DllProcs &dllProcs )
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            }
664            DllProc *pDllProc = ParseDllProc( namespaceScopes, temporary, i );
665            dllProcs.Put( pDllProc );
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.