419 lines
11 KiB
ObjectPascal
419 lines
11 KiB
ObjectPascal
unit wpPar;
|
|
|
|
interface
|
|
uses
|
|
SysUtils,
|
|
Generics.Collections,
|
|
wpLex;
|
|
|
|
type
|
|
TStringMap = TDictionary<AnsiString,AnsiString>;
|
|
|
|
|
|
TwpPar = class
|
|
private
|
|
fLex : TwpLex;
|
|
|
|
fConstants : TStringMap;
|
|
fTypes : TStringMap;
|
|
|
|
protected
|
|
function Match( ttype : TTokenType; dispose: boolean=true):TToken; overload;
|
|
function Match( ttypes : TTokenTypes; dispose: boolean=true):TToken; overload;
|
|
|
|
protected
|
|
procedure block;
|
|
procedure constant;
|
|
procedure uconstant;
|
|
procedure typedef;
|
|
|
|
public
|
|
procedure prg;
|
|
|
|
public
|
|
constructor Create( Lexer: TwpLex);
|
|
destructor Destroy; override;
|
|
end;
|
|
|
|
EwpPar = Exception;
|
|
|
|
|
|
implementation
|
|
|
|
{ TwpPar }
|
|
|
|
|
|
|
|
// @@@: Construction / destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Construction / destruction
|
|
//
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ================================================================================================
|
|
// Constructor
|
|
// ================================================================================================
|
|
constructor TwpPar.Create(Lexer: TwpLex);
|
|
begin
|
|
inherited Create;
|
|
|
|
fLex := Lexer;
|
|
fConstants := TStringMap.Create;
|
|
fTypes := TStringMap.Create;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// Destructor
|
|
// ================================================================================================
|
|
destructor TwpPar.Destroy;
|
|
begin
|
|
fConstants .Free;
|
|
fTypes .Free;
|
|
|
|
inherited
|
|
end;
|
|
|
|
|
|
|
|
// @@@: Internals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Internals
|
|
//
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ================================================================================================
|
|
//
|
|
// ================================================================================================
|
|
function TwpPar.Match(ttype: TTokenType; dispose: boolean): TToken;
|
|
var
|
|
t: TToken;
|
|
|
|
begin
|
|
result := nil;
|
|
t := fLex.NextToken;
|
|
|
|
if t.TokenType = ttype then
|
|
if dispose
|
|
then t.Free
|
|
else result := t
|
|
|
|
else
|
|
raise EwpPar.Create('Unexpected token')
|
|
end;
|
|
|
|
// ================================================================================================
|
|
//
|
|
// ================================================================================================
|
|
function TwpPar.Match(ttypes: TTokenTypes; dispose: boolean): TToken;
|
|
var
|
|
t: TToken;
|
|
|
|
begin
|
|
result := nil;
|
|
t := fLex.NextToken;
|
|
|
|
if t.TokenType in ttypes then
|
|
if dispose
|
|
then t.Free
|
|
else result := t
|
|
else
|
|
raise EwpPar.Create('Unexpected token')
|
|
end;
|
|
|
|
// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// Interface
|
|
//
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// ================================================================================================
|
|
// Program
|
|
// ================================================================================================
|
|
procedure TwpPar.prg;
|
|
var
|
|
t : TToken;
|
|
|
|
begin
|
|
if Assigned( fLex) then
|
|
begin
|
|
Match(LT_PROGRAM);
|
|
Match(TT_ID);
|
|
Match(TT_LPAREN);
|
|
|
|
t := fLex.NextToken;
|
|
|
|
// id [, id]*
|
|
if t.TokenType = TT_ID then
|
|
begin
|
|
t.Free;
|
|
t := fLex.NextToken;
|
|
|
|
while t.TokenType = TT_COMMA do
|
|
begin
|
|
t.Free;
|
|
Match(TT_ID);
|
|
t := fLex.NextToken;
|
|
end;
|
|
end;
|
|
|
|
if t.TokenType <> TT_RPAREN then
|
|
raise EwpPar.Create('")" expected');
|
|
|
|
Match(TT_SEMI);
|
|
block;
|
|
Match(TT_DOT)
|
|
end;
|
|
end;
|
|
|
|
|
|
// ================================================================================================
|
|
// block
|
|
// ================================================================================================
|
|
procedure TwpPar.block;
|
|
var
|
|
token : TToken;
|
|
ttype : TTokenType;
|
|
start : TTokenTypes;
|
|
start2: TTokenTypes;
|
|
|
|
begin
|
|
start := [LT_LABEL,LT_CONST,LT_TYPE,LT_VAR,LT_PROCEDURE,LT_FUNCTION,LT_BEGIN];
|
|
start2:= [LT_LABEL,LT_CONST,LT_TYPE,LT_VAR,LT_PROCEDURE,LT_FUNCTION];
|
|
token := fLex.NextToken;
|
|
|
|
if token.TokenType in start then
|
|
begin
|
|
while token.TokenType in start2 do
|
|
begin
|
|
case token.TokenType of
|
|
// ------------------------------------------------------
|
|
// Label
|
|
// ------------------------------------------------------
|
|
LT_LABEL:
|
|
while true do
|
|
begin
|
|
Match( TT_UINT);
|
|
|
|
token := fLex.NextToken;
|
|
ttype := token.TokenType;
|
|
|
|
token.Free;
|
|
|
|
case ttype of
|
|
TT_COMMA : ;
|
|
TT_SEMI : begin token := fLex.NextToken; break end;
|
|
else raise EwpPar.Create('Expected: ,;');
|
|
end;
|
|
end;
|
|
|
|
// ------------------------------------------------------
|
|
// Const
|
|
// ------------------------------------------------------
|
|
LT_CONST:
|
|
begin
|
|
token := fLex.NextToken;
|
|
ttype := token.TokenType;
|
|
|
|
while ttype = TT_ID do
|
|
begin
|
|
token.Free;
|
|
Match(TT_EQ);
|
|
constant;
|
|
Match(TT_SEMI);
|
|
|
|
token := flex.NextToken;
|
|
ttype := token.TokenType;
|
|
end;
|
|
end;
|
|
|
|
// ------------------------------------------------------
|
|
// Type
|
|
// ------------------------------------------------------
|
|
LT_TYPE:
|
|
begin
|
|
token := fLex.NextToken;
|
|
ttype := token.TokenType;
|
|
|
|
while ttype = TT_ID do
|
|
begin
|
|
token.Free;
|
|
Match(TT_EQ);
|
|
typedef;
|
|
Match(TT_SEMI);
|
|
|
|
token := flex.NextToken;
|
|
ttype := token.TokenType;
|
|
end;
|
|
end;
|
|
|
|
LT_VAR:
|
|
begin
|
|
|
|
end;
|
|
|
|
LT_PROCEDURE:
|
|
begin
|
|
|
|
end;
|
|
|
|
LT_FUNCTION:
|
|
begin
|
|
|
|
end;
|
|
end;
|
|
|
|
// token := fLex.NextToken
|
|
end;
|
|
|
|
if token.TokenType = LT_BEGIN then
|
|
begin
|
|
|
|
Match(LT_END)
|
|
end
|
|
|
|
else
|
|
raise EwpPar.Create('Expected: Begin');
|
|
end
|
|
|
|
else
|
|
raise EwpPar.Create('Expected: label, const, type, var, procedure, function, begin');
|
|
end;
|
|
|
|
|
|
// ================================================================================================
|
|
// Constant
|
|
// ================================================================================================
|
|
procedure TwpPar.constant;
|
|
var
|
|
token: TToken;
|
|
ttype: TTokenType;
|
|
|
|
begin
|
|
token := fLex.NextToken;
|
|
ttype := token.TokenType;
|
|
|
|
if ttype in [TT_PLUS,TT_MINUS,TT_ID,TT_UINT,TT_UREAL] then
|
|
begin
|
|
if ttype in [TT_PLUS,TT_MINUS] then
|
|
begin
|
|
token.Free;
|
|
|
|
token := fLex.NextToken;
|
|
ttype := token.TokenType;
|
|
end;
|
|
|
|
token.Free;
|
|
|
|
case ttype of
|
|
TT_ID : ;
|
|
TT_UINT : ;
|
|
TT_UREAL : ;
|
|
else raise EwpPar.Create('Expected: id,int,real')
|
|
end
|
|
end
|
|
|
|
else if ttype in [TT_CHAR, TT_STRING] then
|
|
begin
|
|
token.Free;
|
|
end
|
|
|
|
else
|
|
raise EwpPar.Create('Expected: +,-,id,int,real,string');
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// Unsigned constant
|
|
// ================================================================================================
|
|
procedure TwpPar.uconstant;
|
|
var
|
|
token: TToken;
|
|
ttype: TTokenType;
|
|
|
|
begin
|
|
token := fLex.NextToken;
|
|
ttype := token.TokenType;
|
|
|
|
token.Free;
|
|
|
|
case token.TokenType of
|
|
TT_ID : ;
|
|
TT_UINT : ;
|
|
TT_UREAL : ;
|
|
LT_NIL : ;
|
|
TT_STRING: ;
|
|
else raise EwpPar.Create('Expected: id,int,real,nil,string')
|
|
end;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// Type
|
|
// ================================================================================================
|
|
procedure TwpPar.typedef;
|
|
var
|
|
token: TToken;
|
|
ttype: TTokenType;
|
|
ttext: AnsiString;
|
|
|
|
f_const : TTokenTypes;
|
|
|
|
begin
|
|
token := fLex.NextToken;
|
|
ttype := token.TokenType;
|
|
ttext := token.TokenText;
|
|
|
|
token.Free;
|
|
|
|
// ---------------------------------------------------------------
|
|
// TT_ID
|
|
//
|
|
// Identifier can be an existing type identifier, or an existing
|
|
// constant identifier. If it is contant identifier, then it must
|
|
// be a range specification.
|
|
// ---------------------------------------------------------------
|
|
if ttype = TT_ID then
|
|
begin
|
|
// --------------------------------------------------
|
|
// constant .. constant
|
|
// --------------------------------------------------
|
|
if fConstants.ContainsKey(ttext) then
|
|
begin
|
|
Match(TT_RANGE);
|
|
|
|
token := fLex.NextToken;
|
|
ttype := token.TokenType;
|
|
ttext := token.TokenText;
|
|
|
|
token.Free;
|
|
end
|
|
|
|
// --------------------------------------------------
|
|
// type identifier
|
|
// --------------------------------------------------
|
|
else if fTypes.ContainsKey(ttext) then
|
|
begin
|
|
|
|
end
|
|
|
|
// --------------------------------------------------
|
|
// Not an constant or type identifier
|
|
// --------------------------------------------------
|
|
else
|
|
EwpPar.Create('Expected a type or constant identifier' );
|
|
end;
|
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|