• <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  評(píng)論-2670  文章-0  trackbacks-0
                做編譯器難免會(huì)遇到如何輸出錯(cuò)誤信息的問題。這個(gè)問題不是那么好解決的,因?yàn)橛锌赡苣阈枰峁┲形摹⒂⑽倪€是其他什么亂七八糟語言的編譯器。于是就要想一種辦法讓錯(cuò)誤信息的語言可以很方便的切換。

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

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

                首先,StrGen.exe讀入下面這個(gè)文件:
             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

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

                首先是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工具自動(dòng)生成
            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 

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

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

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

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

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

            而且從另外一個(gè)觀點(diǎn)看,如果寫一個(gè)類庫出來需要外部文件的支持,其實(shí)是很危險(xiǎn)的……當(dāng)然寫應(yīng)用程序是另外一回事了。  回復(fù)  更多評(píng)論
              
            亚洲国产精品久久66| 精品国产综合区久久久久久 | 久久无码AV中文出轨人妻| 色综合久久中文综合网| 99久久成人国产精品免费| 伊人久久久AV老熟妇色| 狠狠综合久久AV一区二区三区| 三级片免费观看久久| 久久天天日天天操综合伊人av| 国产亚洲精午夜久久久久久| 国产精品丝袜久久久久久不卡| 中文字幕亚洲综合久久| segui久久国产精品| 狠狠精品久久久无码中文字幕 | 99精品国产在热久久| 久久福利青草精品资源站| 久久国产精品国产自线拍免费| 99久久久国产精品免费无卡顿| 国产欧美久久久精品| 99久久伊人精品综合观看| 久久九九免费高清视频| 亚洲国产精品无码久久久久久曰 | 日本精品久久久久中文字幕8| 中文字幕亚洲综合久久| 久久影院亚洲一区| 久久SE精品一区二区| 久久99精品久久只有精品| 国产精品免费久久| 伊人久久大香线蕉无码麻豆| 久久影院综合精品| 色综合久久综精品| 久久九九兔免费精品6| 成人免费网站久久久| 久久精品女人天堂AV麻| 精品久久久无码人妻中文字幕| AV无码久久久久不卡蜜桃| 久久精品国产一区二区三区| 热re99久久6国产精品免费| 一级做a爰片久久毛片人呢| 久久精品国产亚洲AV蜜臀色欲| 久久国产乱子精品免费女|