📄 plscan.pas
字号:
{ Pass1 : THE PL SCANNER -- PLSCANNER.PAS }
unit plscan;
interface
uses pcommon;
const
MaxChar = 5000;
MaxKey = 631;
MaxInt = 32767;
type
SymbolType = (And1{&}, Array1,arrow1{->},Asterisk1{*}, Becomes1{:=}, Begin1,
Boolean1, Bracket1{[]}, Call1, Comma1{,},Const1, Div1{/}, Do1, End1,
EndText1,Equal1{=}, False1,Fi1,Greater1{>},If1, Integer1, LeftBracket1{[},
LeftParenthesis1{(},Less1{<},Minus1{-}, Mod1{\}, Name1, Newline1,
Not1{~}, Numeral1,od1, Or1{|},Period1{.},Plus1{+},Proc1,Read1,
RightBracket1{]},RightParenthesis1{)},Semicolon1{;},skip1,
True1,Unknown1,Write1); //按字母顺序排列
procedure Pass1;
implementation
procedure Pass1;
const
ETX = chr(3);
NL = chr(10);
SP = chr(32);
Dollor = chr(36);
LastStandardName = Write1;
type
CharSet = set of char;
SpellingTable = array [1..MaxChar] of char;
WordPointer = ^ WordRecord;
WordRecord = record
NextWord: WordPointer;
IsName: Boolean;
Index, Length, LastChar: integer
end;
HashTable = array [1..MaxKey] of WordPointer;
var
AlphaNumeric, Digits,
EndComment, Invisible,
Letters, Separators,
SmallLetters,CapitalLetters : CharSet;
ch: char;
Characters: integer;
Spelling: SpellingTable;
Hash: HashTable; Names: integer;
{ OUTPUT }
procedure Emit1(Symbol: SymbolType);
begin
Emit(ord(Symbol))
end;
procedure Emit2(Symbol: SymbolType; Argument: integer);
begin
Emit(ord(Symbol));
Emit(Argument)
end;
{ PROCESSING EOLN }
procedure BeginLine(Number: integer);
begin
LineNo := Number;
NewLine(LineNo);
Emit2(NewLine1, LineNo)
end;
procedure EndLine;
begin
BeginLine(LineNo + 1)
end;
{ INPUT }
procedure NextChar;
begin
if EOF(Input1) then ch := ETX
else
if EOLN(Input1) then
begin
ch := NL;
Readln(Input1)
end
else
begin
Read(Input1, ch);
if ch in Invisible then
NextChar
end
end;
{ WORD SYMBOLS AND NAMES }
function Key(Text1: String; Length: integer): integer;
const
W = 32641 { 32768 - 127 };
N = MaxKey;
var
Sum, i: integer;
begin
Sum := 0;
for i := 1 to Length do
Sum := (Sum + ord(Text1[i])) mod W;
Key := Sum mod N + 1
end;
procedure Insert(IsName: Boolean; Text1: String;
Length,Index,KeyNo: integer);
var
Pointer: WordPointer;
M, N: integer;
begin { Insert the word in the spelling table }
N := Characters;
Characters := Characters + Length;
TestLimit(Characters, MaxChar);
for M := 1 to Length do
Spelling[N + M] := Text1[M];
{ Insert the word in a word list }
New(Pointer);
Pointer^.NextWord := Hash[KeyNo];
Pointer^.IsName := IsName;
Pointer^.Index := Index;
Pointer^.Length := Length;
Pointer^.LastChar := Characters;
Hash[KeyNo] := Pointer
end;
function Found(Text1: String; Length: integer;
Pointer: WordPointer): Boolean;
var
Same: Boolean;
M, N: integer;
begin
if Pointer^.Length <> Length then
Same := false
else
begin
Same := true;
M := Length;
N := Pointer^.LastChar - M;
while Same and (M > 0) do
begin
Same := Text1[M] = Spelling[M + N];
M := M -1
end
end;
Found := Same
end;
procedure Define(IsName: Boolean; Text1: String;
Length, Index: integer);
begin
Insert(IsName, Text1, Length, Index, Key(Text1, Length))
end;
procedure Search(Text1: String; Length: integer;
var Isname: Boolean;var Index: integer);
var
KeyNo: integer; Pointer: WordPointer; Done: Boolean;
begin
KeyNo := Key(Text1, Length);
Pointer := Hash[KeyNo];
Done := false;
while not Done do
if Pointer = nil then
begin
IsName := true;
Names := Names + 1; Index := Names;
Insert(true, Text1, Length, Index, KeyNo);
Done := True
end
else
if Found(Text1, Length, Pointer) then
begin
IsName := Pointer^.IsName;
Index := Pointer^.Index;
Done := true
end
else
Pointer := Pointer^.NextWord
end;
procedure Initialize;
var
KeyNo: integer;
begin
Digits := ['0'..'9'];
CapitalLetters := ['A'..'Z'];
SmallLetters := ['a'..'z'];
Letters := CapitalLetters + SmallLetters;
AlphaNumeric := Letters + Digits + ['_'];
EndComment := [ETX];
Invisible := [chr(0)..chr(31), chr(127)] - [NL, ETX];
Separators := [SP, NL, Dollor];
Characters := 0;
for KeyNo := 1 to MaxKey do Hash[KeyNo] := nil;
{ Insert the word symbols }
Define(false,'array',5,ord(Array1));
Define(false,'begin',5,ord(Begin1));
Define(false,'call',4,ord(call1));
Define(false,'const',5,ord(Const1));
Define(false,'do',2,ord(Do1));
Define(false,'end',3,ord(End1));
Define(false,'fi',2,ord(fi1));
Define(false,'if',2,ord(If1));
Define(false,'od',2,ord(od1));
Define(false,'proc',4,ord(Proc1));
Define(false,'skip',4,ord(skip1));
{ Insert the standard names }
Define(false,'integer',7,ord(Integer1));
Define(false,'boolean',7,ord(Boolean1));
Define(false,'false',5,ord(False1));
Define(false,'true',4,ord(True1));
Define(false,'read',4,ord(Read1));
Define(false,'write',5,ord(Write1));
// define(true,'writeln',7,writeln0);
Names := ord(LastStandardName);
end;
{ LEXICAL ANALYSIS }
procedure Comment;
begin {ch = Dollor}
NextChar;
while not ((ch = NL )or(ch = ETX)) do NextChar;
if ch = NL then
begin
EndLine;
NextChar
end;
end;
procedure NextSymbol;
var
IsName: Boolean; Text1: String;
Length, Index, Value, Digit: integer;
begin
while ch in Separators do
if ch = SP then NextChar
else
if ch = NL then
begin
EndLine;
NextChar
end
else {ch = Dollor} Comment;
if ch in Letters then
begin
Length := 0; Text1 := '';
while ch in AlphaNumeric do
begin
// if ch in CapitalLetters then
// ch := chr(ord(ch) + ord('a') - ord('A'));
Length := Length + 1;
Text1 := Text1 + ch;
NextChar
end;
Search(Text1, Length, IsName, Index);
if IsName then Emit2(Name1, Index)
else Emit(Index);
end
else
if ch in Digits then
begin
Value := 0;
while ch in Digits do
begin
Digit := ord(ch) - ord('0');
if Value <= (MaxInt - Digit) div 10 then
begin
Value := 10 * Value + Digit;
NextChar
end
else
Begin
Error(Numeral3);
while ch in Digits do
NextChar
end
end;
Emit2(Numeral1, Value)
end
else
case ch of
'+': begin
Emit1(Plus1);
NextChar
end;
'-': begin
Nextchar;
if ch = '>' then
begin
Emit1(Arrow1);
NextChar
end
else Emit1(Minus1);
end;
'*': begin
Emit1(Asterisk1);
NextChar
end;
'<': begin
Emit1(Less1);
Nextchar;
end;
'=': begin
Emit1(Equal1);
NextChar
end;
'>': begin
Emit1(Greater1);
Nextchar;
end;
':': begin
Nextchar;
if ch = '=' then
begin
Emit1(Becomes1);
NextChar
end
else
Error(Ambiguous3)
end;
'(': begin
Emit1(LeftParenthesis1);
NextChar
end;
')': begin
Emit1(rightParenthesis1);
NextChar
end;
'[': begin
Nextchar;
if ch = ']' then
begin
Emit1(Bracket1);
NextChar
end
else Emit1(LeftBracket1);
end;
']': begin
Emit1(RightBracket1);
NextChar
end;
',': begin
Emit1(Comma1);
NextChar
end;
'.': begin
Emit1(Period1);
Nextchar;
end;
';': begin
Emit1(Semicolon1);
NextChar
end;
'&': begin
Emit1(And1);
NextChar
end;
'|': begin
Emit1(Or1);
NextChar
end;
'~': begin
Emit1(Not1);
NextChar
end;
'/': begin
Emit1(Div1);
NextChar
end;
'\': begin
Emit1(Mod1);
NextChar
end;
else
if ch <> ETX then
begin
Emit1(Unknown1);
NextChar
end
end { case }
end;
{ Pass1 : THE PL SCANNER }
begin
Initialize;
BeginLine(1);
NextChar;
while ch <> ETX do
NextSymbol;
Emit1(EndText1)
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -