• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-341  評論-2670  文章-0  trackbacks-0
                做編譯器難免會遇到如何輸出錯誤信息的問題。這個問題不是那么好解決的,因為有可能你需要提供中文、英文還是其他什么亂七八糟語言的編譯器。于是就要想一種辦法讓錯誤信息的語言可以很方便的切換。

                由于同時提供中文和英文的編譯器其實沒什么用,中文的編譯器和英文的編譯器其實可以是兩個不同的exe,因此我想寫兩個宏,譬如說中文.bat點擊了之后,代碼里面的錯誤信息就被換成中文,英文.bat被點擊之后,代碼里面的錯誤信息就被換成英文。選擇完之后再編譯,就可以產(chǎn)生需要的語言種類的編譯器了。

                因此我想到了一個辦法。這次在Vczh Library++3.0里面實現(xiàn)了一個小工具StrGen.exe(代碼也一并上傳了)。StrGen.exe需要有四個參數(shù):
                1、Library文件夾的位置
                2、字符串資源文件的位置
                3、生成的.h文件的位置
                4、生成的.cpp文件的位置

                首先,StrGen.exe讀入下面這個文件:
             1 resource:vl.scripting.basiclanguage.BasicErrorMessage
             2 
             3 TypeNameNotExists(type)=Type {type} does not exists.
             4 FunctionAlreadyExists(name)=Function {name} already exists.
             5 VariableAlreadyExists(name)=Variable {name} already exists.
             6 TypeAlreadyExists(name)=Type {name} already exists.
             7 StructureMemberAlreadyExists(name)=Member {name} already exists.
             8 VariableNotExists(name)=Variable {name} not exists.
             9 FailToCast(from,to)=Fail to cast from {from} to {to}.
            10 VoidFunctionNotHaveResult=Cannot access function result in a function without return value.
            11 GlobalNotHaveResult=Cannot access function result in global definitions.
            12 CannotInvokeNonFunctionValue(type)=Cannot invoke a value of {type}.
            13 ArgumentNumnerNotMatch=Argument number should not be greater or less than the function required.
            14 ArgumentTypeNotMatch(index,from,to)=Cannot implicitly cast argument {index} from {from} to {to}.
            15 StructureMemberNotExists(name)=Member {name} not exists.
            16 CannotConvertIndexToInt(from,to)=Cannot implicit cast the index from {from} to {to}.
            17 CannotSubscribe(type)=Cannot subscribe a value of {type}.
            18 UnaryOperandShouldBeLeftValue=Operand should be left value.
            19 UnaryTypeNotMatch(op,type)=Unary operator {op} cannot apply to a value of {type}.
            20 BinaryLeftOperandShouldBeLeftValue(op)=Left operand of binary operator {op} should be left value.
            21 BinaryTypeNotMatch=(op,left,right)=Binary operator {op} cannot apply to values of {left} and {right}.
            22 ConditionCannotConvertToBool(from,boolean)=Cannot convert the condition from {from} to {boolean}.
            23 BreakShouldBeInLooping(breakStatement)={breakStatement} should be used in a loop.
            24 ContinueShouldBeInLooping(continueStatement)={continueStatement} should be used in a loop.
            25 InitializerTypeNotMatch(from,to)=Cannot convert the variable initializer from {from} to {to}.
            26 ParameterCountNotMatch=Parameter number should not be greater or less than the function required.
            27 ParameterAlreadyExists(name)=Parameter (name) already exists.
            28 StructureMemberCannotBeUndefinedType(name)=Cannot refer to an undefined structure {name}.
            29 LeftOperandShouldBeStructure=Left operand should be a structure.
            30 LeftOperandShouldBePointerToStructure=Left operand should be a pointer to a structure.
            31 PredeclaredStructureShouldBeDefined(name)=Predeclared structure (name) should be defined.

                第一行resource告訴StrGen生成的類的namespace和類名。然后用如下的命令去生成:
            1 ..\Tools\StrGen\Debug\StrGen .\ .\Scripting\Languages\BasicErrorMessage_English.txt .\Scripting\Languages\BasicErrorMessage.h .\Scripting\Languages\BasicErrorMessage.cpp
            2 pause

                這個English.bat放在Library目錄下,所以第一個參數(shù)自然是“.\”。后面的都好理解,就是三個文件名。那么想替換成中文怎么辦呢?只要寫一個BasicErrorMessage_Chinese.txt,然后寫一個Chinese.bat去讀他就好了。bat文件里面可以放很多行,就能批量替換了。實際上生成的兩個代碼文件如下:

                首先是BasicErrorMessage.h
             1 /***********************************************************************
             2 Vczh Library++ 3.0
             3 Developer: 陳梓瀚(vczh)
             4 StringResource::BasicErrorMessage
             5 
             6 Classes:
             7     BasicErrorMessage                                    :字符串資源類
             8     
             9 本文件使用Vczh String Resource Code Generator工具自動生成
            10 ***********************************************************************/
            11 
            12 #ifndef VCZH_STRING_RESOURCE_CODE_FILE_VL_SCRIPTING_BASICLANGUAGE_BASICERRORMESSAGE
            13 #define VCZH_STRING_RESOURCE_CODE_FILE_VL_SCRIPTING_BASICLANGUAGE_BASICERRORMESSAGE
            14 
            15 #include "..\..\String.h"
            16 
            17 using namespace vl;
            18 
            19 namespace vl
            20 {
            21     namespace scripting
            22     {
            23         namespace basiclanguage
            24         {
            25             class BasicErrorMessage
            26             {
            27             public:
            28                 static WString TypeNameNotExists(const WString& type);
            29                 static WString FunctionAlreadyExists(const WString& name);
            30                 static WString VariableAlreadyExists(const WString& name);
            31                 static WString TypeAlreadyExists(const WString& name);
            32                 static WString StructureMemberAlreadyExists(const WString& name);
            33                 static WString VariableNotExists(const WString& name);
            34                 static WString FailToCast(const WString& from, const WString& to);
            35                 static WString VoidFunctionNotHaveResult();
            36                 static WString GlobalNotHaveResult();
            37                 static WString CannotInvokeNonFunctionValue(const WString& type);
            38                 static WString ArgumentNumnerNotMatch();
            39                 static WString ArgumentTypeNotMatch(const WString& index, const WString& from, const WString& to);
            40                 static WString StructureMemberNotExists(const WString& name);
            41                 static WString CannotConvertIndexToInt(const WString& from, const WString& to);
            42                 static WString CannotSubscribe(const WString& type);
            43                 static WString UnaryOperandShouldBeLeftValue();
            44                 static WString UnaryTypeNotMatch(const WString& op, const WString& type);
            45                 static WString BinaryLeftOperandShouldBeLeftValue(const WString& op);
            46                 static WString BinaryTypeNotMatch();
            47                 static WString ConditionCannotConvertToBool(const WString& from, const WString& boolean);
            48                 static WString BreakShouldBeInLooping(const WString& breakStatement);
            49                 static WString ContinueShouldBeInLooping(const WString& continueStatement);
            50                 static WString InitializerTypeNotMatch(const WString& from, const WString& to);
            51                 static WString ParameterCountNotMatch();
            52                 static WString ParameterAlreadyExists(const WString& name);
            53                 static WString StructureMemberCannotBeUndefinedType(const WString& name);
            54                 static WString LeftOperandShouldBeStructure();
            55                 static WString LeftOperandShouldBePointerToStructure();
            56                 static WString PredeclaredStructureShouldBeDefined(const WString& name);
            57             };
            58         }
            59     }
            60 }
            61 
            62 #endif

                看到這里一般都知道是怎么一回事了吧。資源的名字被編譯成靜態(tài)函數(shù)。容易想象函數(shù)里面自然是這些內(nèi)容:
              1 #include "BasicErrorMessage.h"
              2 
              3 namespace vl
              4 {
              5     namespace scripting
              6     {
              7         namespace basiclanguage
              8         {
              9             WString BasicErrorMessage::TypeNameNotExists(const WString& type)
             10             {
             11                 return L"Type "+type+L" does not exists.";
             12             }
             13 
             14             WString BasicErrorMessage::FunctionAlreadyExists(const WString& name)
             15             {
             16                 return L"Function "+name+L" already exists.";
             17             }
             18 
             19             WString BasicErrorMessage::VariableAlreadyExists(const WString& name)
             20             {
             21                 return L"Variable "+name+L" already exists.";
             22             }
             23 
             24             WString BasicErrorMessage::TypeAlreadyExists(const WString& name)
             25             {
             26                 return L"Type "+name+L" already exists.";
             27             }
             28 
             29             WString BasicErrorMessage::StructureMemberAlreadyExists(const WString& name)
             30             {
             31                 return L"Member "+name+L" already exists.";
             32             }
             33 
             34             WString BasicErrorMessage::VariableNotExists(const WString& name)
             35             {
             36                 return L"Variable "+name+L" not exists.";
             37             }
             38 
             39             WString BasicErrorMessage::FailToCast(const WString& from, const WString& to)
             40             {
             41                 return L"Fail to cast from "+from+L" to "+to+L".";
             42             }
             43 
             44             WString BasicErrorMessage::VoidFunctionNotHaveResult()
             45             {
             46                 return L"Cannot access function result in a function without return value.";
             47             }
             48 
             49             WString BasicErrorMessage::GlobalNotHaveResult()
             50             {
             51                 return L"Cannot access function result in global definitions.";
             52             }
             53 
             54             WString BasicErrorMessage::CannotInvokeNonFunctionValue(const WString& type)
             55             {
             56                 return L"Cannot invoke a value of "+type+L".";
             57             }
             58 
             59             WString BasicErrorMessage::ArgumentNumnerNotMatch()
             60             {
             61                 return L"Argument number should not be greater or less than the function required.";
             62             }
             63 
             64             WString BasicErrorMessage::ArgumentTypeNotMatch(const WString& index, const WString& from, const WString& to)
             65             {
             66                 return L"Cannot implicitly cast argument "+index+L" from "+from+L" to "+to+L".";
             67             }
             68 
             69             WString BasicErrorMessage::StructureMemberNotExists(const WString& name)
             70             {
             71                 return L"Member "+name+L" not exists.";
             72             }
             73 
             74             WString BasicErrorMessage::CannotConvertIndexToInt(const WString& from, const WString& to)
             75             {
             76                 return L"Cannot implicit cast the index from "+from+L" to "+to+L".";
             77             }
             78 
             79             WString BasicErrorMessage::CannotSubscribe(const WString& type)
             80             {
             81                 return L"Cannot subscribe a value of "+type+L".";
             82             }
             83 
             84             WString BasicErrorMessage::UnaryOperandShouldBeLeftValue()
             85             {
             86                 return L"Operand should be left value.";
             87             }
             88 
             89             WString BasicErrorMessage::UnaryTypeNotMatch(const WString& op, const WString& type)
             90             {
             91                 return L"Unary operator "+op+L" cannot apply to a value of "+type+L".";
             92             }
             93 
             94             WString BasicErrorMessage::BinaryLeftOperandShouldBeLeftValue(const WString& op)
             95             {
             96                 return L"Left operand of binary operator "+op+L" should be left value.";
             97             }
             98 
             99             WString BasicErrorMessage::BinaryTypeNotMatch()
            100             {
            101                 return L"(op,left,right)=Binary operator "L"{op}"L" cannot apply to values of "L"{left}"L" and "L"{right}"L".";
            102             }
            103 
            104             WString BasicErrorMessage::ConditionCannotConvertToBool(const WString& from, const WString& boolean)
            105             {
            106                 return L"Cannot convert the condition from "+from+L" to "+boolean+L".";
            107             }
            108 
            109             WString BasicErrorMessage::BreakShouldBeInLooping(const WString& breakStatement)
            110             {
            111                 return breakStatement+L" should be used in a loop.";
            112             }
            113 
            114             WString BasicErrorMessage::ContinueShouldBeInLooping(const WString& continueStatement)
            115             {
            116                 return continueStatement+L" should be used in a loop.";
            117             }
            118 
            119             WString BasicErrorMessage::InitializerTypeNotMatch(const WString& from, const WString& to)
            120             {
            121                 return L"Cannot convert the variable initializer from "+from+L" to "+to+L".";
            122             }
            123 
            124             WString BasicErrorMessage::ParameterCountNotMatch()
            125             {
            126                 return L"Parameter number should not be greater or less than the function required.";
            127             }
            128 
            129             WString BasicErrorMessage::ParameterAlreadyExists(const WString& name)
            130             {
            131                 return L"Parameter (name) already exists.";
            132             }
            133 
            134             WString BasicErrorMessage::StructureMemberCannotBeUndefinedType(const WString& name)
            135             {
            136                 return L"Cannot refer to an undefined structure "+name+L".";
            137             }
            138 
            139             WString BasicErrorMessage::LeftOperandShouldBeStructure()
            140             {
            141                 return L"Left operand should be a structure.";
            142             }
            143 
            144             WString BasicErrorMessage::LeftOperandShouldBePointerToStructure()
            145             {
            146                 return L"Left operand should be a pointer to a structure.";
            147             }
            148 
            149             WString BasicErrorMessage::PredeclaredStructureShouldBeDefined(const WString& name)
            150             {
            151                 return L"Predeclared structure (name) should be defined.";
            152             }
            153 
            154         }
            155     }
            156 }
            157 

                使用的時候就十分方便了,譬如說BasicErrorMessage::VariableNotExists(L"a"),就會給你一個相應(yīng)的錯誤信息的字符串了。

                在Vczh Library++3.0的目錄.\Tools\StrGen\下面有這個工具的源代碼。
            posted on 2010-03-05 23:08 陳梓瀚(vczh) 閱讀(2505) 評論(2)  編輯 收藏 引用 所屬分類: VL++3.0開發(fā)紀事

            評論:
            # re: Vczh Library++3.0開發(fā)紀事之字符串資源生成器StrGen.exe 2010-03-07 01:12 | Kevin Lynx
            對這種支持多種字符串資源的問題,沒必要自己寫個程序去生成對應(yīng)的代碼文件吧?
            english_res.txt:
            IDS_TYPE_ERROR "XXXXX%s"

            const char *s = LoadString( IDS_TYPE_ERROR );
            sprintf( buf, s, err );

              回復(fù)  更多評論
              
            # re: Vczh Library++3.0開發(fā)紀事之字符串資源生成器StrGen.exe 2010-03-07 01:31 | 陳梓瀚(vczh)
            @Kevin Lynx
            我不會用需要%s這種肯定動用printf或者sprintf的類型不安全函數(shù)的方法的。一向來的風(fēng)格是讓編譯器能夠檢查更多的事情,于是我致力于用類型去表達程序需要干的事情(而不是語句)。當然只好去寫StrGen.exe了。因為每一個資源都是有類型的(指參數(shù),以后可能會支持更多)。

            而且從另外一個觀點看,如果寫一個類庫出來需要外部文件的支持,其實是很危險的……當然寫應(yīng)用程序是另外一回事了。  回復(fù)  更多評論
              
            国产精品国色综合久久| 久久久艹| 久久久噜噜噜久久中文字幕色伊伊| 99久久精品费精品国产一区二区 | 久久婷婷五月综合色奶水99啪| 久久五月精品中文字幕| 久久九九免费高清视频| 国产综合精品久久亚洲| 精品一久久香蕉国产线看播放| 99精品久久久久久久婷婷| 久久精品国产亚洲综合色| 久久久中文字幕| 国产成人久久久精品二区三区| 四虎国产永久免费久久| 国产精品美女久久久免费| 九九久久精品国产| 偷偷做久久久久网站| 国产69精品久久久久9999APGF| A级毛片无码久久精品免费| 久久久久亚洲AV无码麻豆| 久久国产精品99国产精| 国产精品视频久久久| 国产成人精品久久亚洲高清不卡 | 久久久久久一区国产精品| 人人狠狠综合88综合久久| 久久久久久久久久久精品尤物| 日日躁夜夜躁狠狠久久AV| 久久96国产精品久久久| 久久精品国产99久久丝袜| 国产精品久久婷婷六月丁香| 欧美丰满熟妇BBB久久久| 伊人丁香狠狠色综合久久| 亚洲国产成人久久综合野外| 午夜精品久久久久久久| 欧美激情精品久久久久| 色偷偷88欧美精品久久久 | 亚洲国产精品无码久久一线| 2021久久国自产拍精品| 久久久久婷婷| 精品久久久久久久无码| 久久亚洲电影|