?? cncodeformater.pas
字號:
?{******************************************************************************}
{ CnPack For Delphi/C++Builder }
{ 中國人自己的開放源碼第三方開發包 }
{ (C)Copyright 2001-2009 CnPack 開發組 }
{ ------------------------------------ }
{ }
{ 本開發包是開源的自由軟件,您可以遵照 CnPack 的發布協議來修 }
{ 改和重新發布這一程序。 }
{ }
{ 發布這一開發包的目的是希望它有用,但沒有任何擔保。甚至沒有 }
{ 適合特定目的而隱含的擔保。更詳細的情況請參閱 CnPack 發布協議。 }
{ }
{ 您應該已經和開發包一起收到一份 CnPack 發布協議的副本。如果 }
{ 還沒有,可訪問我們的網站: }
{ }
{ 網站地址:http://www.cnpack.org }
{ 電子郵件:master@cnpack.org }
{ }
{******************************************************************************}
unit CnCodeFormater;
{* |<PRE>
================================================================================
* 軟件名稱:CnPack 代碼格式化專家
* 單元名稱:格式化專家核心類 CnCodeFormater
* 單元作者:CnPack開發組
* 備 注:該單元實現了代碼格式化的核心類
* 開發平臺:Win2003 + Delphi 5.0
* 兼容測試:not test yet
* 本 地 化:not test hell
* 單元標識:$Id: CnCodeFormater.pas,v 1.41 2009/01/02 08:36:28 liuxiao Exp $
* 修改記錄:2003.12.16 V0.4
* 最初級的實現,巨大的工作量,使用遞歸下降分析法基本完整的實現了
* Delphi 5 的 Object Pascal 語法解析。代碼格式上包括代碼縮進、關
* 鍵字大小寫的設置。
================================================================================
|</PRE>}
interface
uses
Classes, SysUtils, Dialogs, CnTokens, CnScaners, CnCodeGenerators,
CnCodeFormatRules;
type
TCnAbstractCodeFormater = class
private
FScaner: TAbstractScaner;
FCodeGen: TCnCodeGenerator;
FLastToken: TPascalToken;
FInternalRaiseException: Boolean;
protected
{* 錯誤處理函數 }
procedure Error(const Ident: string);
procedure ErrorFmt(const Ident: string; const Args: array of const);
procedure ErrorStr(const Message: string);
procedure ErrorToken(Token: TPascalToken);
procedure ErrorTokens(Tokens: array of TPascalToken);
procedure ErrorExpected(Str: string);
procedure ErrorNotSurpport(FurtureStr: string);
procedure CheckHeadComments;
{* 處理代碼開始之前的注釋}
function CanBeSymbol(Token: TPascalToken): Boolean;
procedure Match(Token: TPascalToken; BeforeSpaceCount: Byte = 0;
AfterSpaceCount: Byte = 0; IgnorePreSpace: Boolean = False;
SemicolonIsLineStart: Boolean = False);
procedure MatchOperator(Token: TPascalToken); //操作符
procedure WriteToken(Token: TPascalToken; BeforeSpaceCount: Byte = 0;
AfterSpaceCount: Byte = 0; IgnorePreSpace: Boolean = False;
SemicolonIsLineStart: Boolean = False);
function CheckFunctionName(S: string): string;
{* 檢查給定字符串是否是一個常用函數名,如果是則返回正確的格式 }
function Tab(PreSpaceCount: Byte = 0; CareBeginBlock: Boolean = True): Byte;
{* 根據代碼格式風格設置返回縮進一次的前導空格數 }
function Space(Count: Word): string;
{* 返回指定數目空格的字符串 }
procedure Writeln;
{* 格式結果換行 }
procedure WriteLine;
{* 格式結果加一空行 }
function FormatString(const KeywordStr: string; KeywordStyle: TKeywordStyle): string;
{* 返回指定關鍵字風格的字符串}
function UpperFirst(const KeywordStr: string): string;
{* 返回首字母大寫的字符串}
property CodeGen: TCnCodeGenerator read FCodeGen;
{* 目標代碼生成器}
property Scaner: TAbstractScaner read FScaner;
{* 詞法掃描器}
public
constructor Create(AStream: TStream);
destructor Destroy; override;
procedure FormatCode(PreSpaceCount: Byte = 0); virtual; abstract;
procedure SaveToFile(FileName: string);
procedure SaveToStream(Stream: TStream);
procedure SaveToStrings(AStrings: TStrings);
end;
TCnExpressionFormater = class(TCnAbstractCodeFormater)
protected
procedure FormatExprList(PreSpaceCount: Byte = 0);
procedure FormatExpression(PreSpaceCount: Byte = 0);
procedure FormatSimpleExpression(PreSpaceCount: Byte = 0);
procedure FormatTerm(PreSpaceCount: Byte = 0);
procedure FormatFactor(PreSpaceCount: Byte = 0);
procedure FormatDesignator(PreSpaceCount: Byte = 0);
procedure FormatDesignatorList(PreSpaceCount: Byte = 0);
procedure FormatQualID(PreSpaceCount: Byte = 0);
procedure FormatTypeID(PreSpaceCount: Byte = 0);
procedure FormatIdent(PreSpaceCount: Byte = 0; const CanHaveUnitQual: Boolean = False);
procedure FormatIdentList(PreSpaceCount: Byte = 0; const CanHaveUnitQual: Boolean = False);
procedure FormatConstExpr(PreSpaceCount: Byte = 0);
procedure FormatConstExprInType(PreSpaceCount: Byte = 0);
procedure FormatSetConstructor(PreSpaceCount: Byte = 0);
// 泛型支持
procedure FormatFormalTypeParamList(PreSpaceCount: Byte = 0);
procedure FormatTypeParams(PreSpaceCount: Byte = 0);
procedure FormatTypeParamDeclList(PreSpaceCount: Byte = 0);
procedure FormatTypeParamDecl(PreSpaceCount: Byte = 0);
procedure FormatTypeParamList(PreSpaceCount: Byte = 0);
procedure FormatTypeParamIdentList(PreSpaceCount: Byte = 0);
procedure FormatTypeParamIdent(PreSpaceCount: Byte = 0);
public
procedure FormatCode(PreSpaceCount: Byte = 0); override;
end;
TCnStatementFormater = class(TCnExpressionFormater)
protected
procedure FormatCompoundStmt(PreSpaceCount: Byte = 0);
procedure FormatStmtList(PreSpaceCount: Byte = 0);
procedure FormatStatement(PreSpaceCount: Byte = 0);
procedure FormatLabel(PreSpaceCount: Byte = 0);
procedure FormatSimpleStatement(PreSpaceCount: Byte = 0);
procedure FormatStructStmt(PreSpaceCount: Byte = 0);
procedure FormatIfStmt(PreSpaceCount: Byte = 0; IgnorePreSpace: Boolean = False);
{* IgnorePreSpace 是為了控制 else if 的情形}
procedure FormatCaseLabel(PreSpaceCount: Byte = 0);
procedure FormatCaseSelector(PreSpaceCount: Byte = 0);
procedure FormatCaseStmt(PreSpaceCount: Byte = 0);
procedure FormatRepeatStmt(PreSpaceCount: Byte = 0);
procedure FormatWhileStmt(PreSpaceCount: Byte = 0);
procedure FormatForStmt(PreSpaceCount: Byte = 0);
procedure FormatWithStmt(PreSpaceCount: Byte = 0);
procedure FormatTryStmt(PreSpaceCount: Byte = 0);
procedure FormatTryEnd(PreSpaceCount: Byte = 0);
procedure FormatExceptionHandler(PreSpaceCount: Byte = 0);
procedure FormatRaiseStmt(PreSpaceCount: Byte = 0);
procedure FormatAsmBlock(PreSpaceCount: Byte = 0);
public
procedure FormatCode(PreSpaceCount: Byte = 0); override;
end;
TCnTypeSectionFormater = class(TCnStatementFormater)
protected
procedure FormatTypeSection(PreSpaceCount: Byte = 0);
procedure FormatTypeDecl(PreSpaceCount: Byte = 0);
procedure FormatTypedConstant(PreSpaceCount: Byte = 0);
procedure FormatArrayConstant(PreSpaceCount: Byte = 0);
procedure FormatRecordConstant(PreSpaceCount: Byte = 0);
procedure FormatRecordFieldConstant(PreSpaceCount: Byte = 0);
procedure FormatType(PreSpaceCount: Byte = 0; IgnoreDirective: Boolean = False);
procedure FormatRestrictedType(PreSpaceCount: Byte = 0);
procedure FormatClassRefType(PreSpaceCount: Byte = 0);
procedure FormatSimpleType(PreSpaceCount: Byte = 0);
procedure FormatOrdinalType(PreSpaceCount: Byte = 0);
procedure FormatSubrangeType(PreSpaceCount: Byte = 0);
procedure FormatEnumeratedType(PreSpaceCount: Byte = 0);
procedure FormatEnumeratedList(PreSpaceCount: Byte = 0);
procedure FormatEmumeratedIdent(PreSpaceCount: Byte = 0);
procedure FormatStringType(PreSpaceCount: Byte = 0);
procedure FormatStructType(PreSpaceCount: Byte = 0);
procedure FormatArrayType(PreSpaceCount: Byte = 0);
procedure FormatRecType(PreSpaceCount: Byte = 0);
procedure FormatFieldList(PreSpaceCount: Byte = 0; IgnoreFirst: Boolean = False);
{* 處理 record 中 case 內部的首行無需縮進的問題}
procedure FormatFieldDecl(PreSpaceCount: Byte = 0);
procedure FormatVariantSection(PreSpaceCount: Byte = 0);
procedure FormatRecVariant(PreSpaceCount: Byte = 0; IgnoreFirst: Boolean = False);
{* 處理 record 中 case 內部的首行無需縮進的問題}
procedure FormatSetType(PreSpaceCount: Byte = 0);
procedure FormatFileType(PreSpaceCount: Byte = 0);
procedure FormatPointerType(PreSpaceCount: Byte = 0);
procedure FormatProcedureType(PreSpaceCount: Byte = 0);
procedure FormatFunctionHeading(PreSpaceCount: Byte = 0; AllowEqual: Boolean = True);
procedure FormatProcedureHeading(PreSpaceCount: Byte = 0; AllowEqual: Boolean = True);
{* 用 AllowEqual 區分 ProcType 和 ProcDecl 可否帶等于號的情形}
procedure FormatMethodName(PreSpaceCount: Byte = 0);
procedure FormatFormalParameters(PreSpaceCount: Byte = 0);
procedure FormatFormalParm(PreSpaceCount: Byte = 0);
procedure FormatParameter(PreSpaceCount: Byte = 0);
procedure FormatDirective(PreSpaceCount: Byte = 0; IgnoreFirst: Boolean = False);
procedure FormatObjectType(PreSpaceCount: Byte = 0);
procedure FormatObjHeritage(PreSpaceCount: Byte = 0);
procedure FormatMethodList(PreSpaceCount: Byte = 0);
procedure FormatMethodHeading(PreSpaceCount: Byte = 0);
procedure FormatConstructorHeading(PreSpaceCount: Byte = 0);
procedure FormatDestructorHeading(PreSpaceCount: Byte = 0);
procedure FormatObjFieldList(PreSpaceCount: Byte = 0);
procedure FormatClassType(PreSpaceCount: Byte = 0);
procedure FormatClassHeritage(PreSpaceCount: Byte = 0);
procedure FormatClassVisibility(PreSpaceCount: Byte = 0);
// fixed grammer
procedure FormatClassBody(PreSpaceCount: Byte = 0);
procedure FormatClassMemberList(PreSpaceCount: Byte = 0);
procedure FormatClassMember(PreSpaceCount: Byte = 0);
procedure FormatClassField(PreSpaceCount: Byte = 0);
procedure FormatClassMethod(PreSpaceCount: Byte = 0);
procedure FormatClassProperty(PreSpaceCount: Byte = 0);
// orgin grammer
procedure FormatClassFieldList(PreSpaceCount: Byte = 0);
procedure FormatClassMethodList(PreSpaceCount: Byte = 0);
procedure FormatClassPropertyList(PreSpaceCount: Byte = 0);
procedure FormatPropertyList(PreSpaceCount: Byte = 0);
procedure FormatPropertyInterface(PreSpaceCount: Byte = 0);
procedure FormatPropertyParameterList(PreSpaceCount: Byte = 0);
procedure FormatPropertySpecifiers(PreSpaceCount: Byte = 0);
procedure FormatInterfaceType(PreSpaceCount: Byte = 0);
procedure FormatGuid(PreSpaceCount: Byte = 0);
procedure FormatInterfaceHeritage(PreSpaceCount: Byte = 0);
procedure FormatRequiresClause(PreSpaceCount: Byte = 0);
procedure FormatContainsClause(PreSpaceCount: Byte = 0);
//procedure FormatTypeID(PreSpaceCount: Byte = 0);
end;
TCnProgramBlockFormater = class(TCnTypeSectionFormater)
protected
procedure FormatProgramBlock(PreSpaceCount: Byte = 0);
procedure FormatUsesClause(PreSpaceCount: Byte = 0; const NeedCRLF: Boolean = False);
procedure FormatUsesList(PreSpaceCount: Byte = 0; const CanHaveUnitQual: Boolean = False;
const NeedCRLF: Boolean = False);
procedure FormatUsesDecl(PreSpaceCount: Byte; const CanHaveUnitQual: Boolean = False);
procedure FormatBlock(PreSpaceCount: Byte = 0; IsInternal: Boolean = False);
procedure FormatDeclSection(PreSpaceCount: Byte; IndentProcs: Boolean = True;
IsInternal: Boolean = False);
procedure FormatLabelDeclSection(PreSpaceCount: Byte = 0);
procedure FormatConstSection(PreSpaceCount: Byte = 0);
procedure FormatConstantDecl(PreSpaceCount: Byte = 0);
procedure FormatVarSection(PreSpaceCount: Byte = 0);
procedure FormatVarDecl(PreSpaceCount: Byte = 0);
procedure FormatProcedureDeclSection(PreSpaceCount: Byte = 0);
procedure FormatProcedureDecl(PreSpaceCount: Byte = 0);
procedure FormatFunctionDecl(PreSpaceCount: Byte = 0);
procedure FormatLabelID(PreSpaceCount: Byte = 0);
procedure FormatExportsSection(PreSpaceCount: Byte = 0);
procedure FormatExportsList(PreSpaceCount: Byte = 0);
procedure FormatExportsDecl(PreSpaceCount: Byte = 0);
end;
TCnGoalCodeFormater = class(TCnProgramBlockFormater)
protected
procedure FormatGoal(PreSpaceCount: Byte = 0);
procedure FormatProgram(PreSpaceCount: Byte = 0);
procedure FormatUnit(PreSpaceCount: Byte = 0);
procedure FormatLibrary(PreSpaceCount: Byte = 0);
procedure FormatInterfaceSection(PreSpaceCount: Byte = 0);
procedure FormatInterfaceDecl(PreSpaceCount: Byte = 0);
procedure FormatExportedHeading(PreSpaceCount: Byte = 0);
procedure FormatImplementationSection(PreSpaceCount: Byte = 0);
procedure FormatInitSection(PreSpaceCount: Byte = 0);
public
procedure FormatCode(PreSpaceCount: Byte = 0); override;
end;
TCnPascalCodeFormater = class(TCnGoalCodeFormater);
implementation
uses
CnParseConsts;
{ TCnAbstractCodeFormater }
function TCnAbstractCodeFormater.CheckFunctionName(S: string): string;
begin
{ TODO: Check the S with functon name e.g. ShowMessage }
Result := S;
end;
constructor TCnAbstractCodeFormater.Create(AStream: TStream);
begin
FCodeGen := TCnCodeGenerator.Create;
FScaner := TScaner.Create(AStream, FCodeGen);
end;
destructor TCnAbstractCodeFormater.Destroy;
begin
FScaner.Free;
inherited;
end;
procedure TCnAbstractCodeFormater.Error(const Ident: string);
begin
ErrorStr(Ident);
end;
procedure TCnAbstractCodeFormater.ErrorFmt(const Ident: string;
const Args: array of const);
begin
ErrorStr(Format(Ident, Args));
end;
procedure TCnAbstractCodeFormater.ErrorNotSurpport(FurtureStr: string);
begin
ErrorFmt(SNotSurpport, [FurtureStr]);
end;
procedure TCnAbstractCodeFormater.ErrorStr(const Message: string);
begin
raise EParserError.CreateResFmt(
@SParseError,
[ Message, FScaner.SourceLine, FScaner.SourcePos ]
);
end;
procedure TCnAbstractCodeFormater.ErrorToken(Token: TPascalToken);
begin
if TokenToString(Scaner.Token) = '' then
ErrorFmt(SSymbolExpected, [TokenToString(Token), Scaner.TokenString] )
else
ErrorFmt(SSymbolExpected, [TokenToString(Token), TokenToString(Scaner.Token)]);
end;
procedure TCnAbstractCodeFormater.ErrorTokens(Tokens: array of TPascalToken);
var
S: string;
I: Integer;
begin
S := '';
for I := Low(Tokens) to High(Tokens) do
S := S + TokenToString(Tokens[I]) + ' ';
ErrorExpected(S);
end;
procedure TCnAbstractCodeFormater.ErrorExpected(Str: string);
begin
ErrorFmt(SSymbolExpected, [Str, TokenToString(Scaner.Token)]);
end;
function TCnAbstractCodeFormater.FormatString(const KeywordStr: string;
KeywordStyle: TKeywordStyle): string;
begin
case KeywordStyle of
ksPascalKeyword: Result := UpperFirst(KeywordStr);
ksUpperCaseKeyword: Result := UpperCase(KeywordStr);
ksLowerCaseKeyword: Result := LowerCase(KeywordStr);
else
Result := KeywordStr;
end;
end;
function TCnAbstractCodeFormater.UpperFirst(const KeywordStr: string): string;
begin
Result := LowerCase(KeywordStr);
if Length(Result) >= 1 then
Result[1] := Char(Ord(Result[1]) + Ord('A') - Ord('a'));
end;
function TCnAbstractCodeFormater.CanBeSymbol(Token: TPascalToken): Boolean;
begin
Result := Scaner.Token in ([tokSymbol] + ComplexTokens); //KeywordTokens + DirectiveTokens);
end;
procedure TCnAbstractCodeFormater.Match(Token: TPascalToken; BeforeSpaceCount,
AfterSpaceCount: Byte; IgnorePreSpace: Boolean; SemicolonIsLineStart: Boolean);
begin
if (Scaner.Token = Token) or ( (Token = tokSymbol) and
CanBeSymbol(Scaner.Token) ) then
begin
WriteToken(Token, BeforeSpaceCount, AfterSpaceCount,
IgnorePreSpace, SemicolonIsLineStart);
Scaner.NextToken;
end
else if FInternalRaiseException or not CnPascalCodeForRule.ContinueAfterError then
ErrorToken(Token)
else // 要繼續的場合,寫了再說
begin
WriteToken(Token, BeforeSpaceCount, AfterSpaceCount,
IgnorePreSpace, SemicolonIsLineStart);
Scaner.NextToken;
end;
end;
procedure TCnAbstractCodeFormater.MatchOperator(Token: TPascalToken);
begin
Match(Token, CnPascalCodeForRule.SpaceBeforeOperator,
CnPascalCodeForRule.SpaceAfterOperator);
end;
procedure TCnAbstractCodeFormater.SaveToFile(FileName: string);
begin
CodeGen.SaveToFile(FileName);
end;
procedure TCnAbstractCodeFormater.SaveToStream(Stream: TStream);
begin
CodeGen.SaveToStream(Stream);
end;
procedure TCnAbstractCodeFormater.SaveToStrings(AStrings: TStrings);
begin
CodeGen.SaveToStrings(AStrings);
end;
function TCnAbstractCodeFormater.Space(Count: Word): string;
begin
Result := 'a'#10'a'#13'sd'; // ???
if SmallInt(Count) > 0 then
Result := StringOfChar(' ', Count)
else
Result := '';
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -