📄 yaccsem.pas
字号:
{
Semantic routines for the Yacc parser.
Copyright (c) 1990-92 Albert Graef <ag@muwiinfa.geschichte.uni-mainz.de>
Copyright (C) 1996 Berend de Boer <berend@pobox.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Revision: 2 $
$Modtime: 96-08-01 6:03 $
$History: YACCSEM.PAS $
*
* ***************** Version 2 *****************
* User: Berend Date: 96-10-10 Time: 21:16
* Updated in $/Lex and Yacc/tply
* Updated for protected mode, windows and Delphi 1.X and 2.X.
}
unit YaccSem;
interface
var
act_prec : Integer;
(* active precedence level in token and precedence declarations (0 in
%token declaration) *)
act_type : Integer;
(* active type tag in token, precedence and type declarations *)
procedure yyerror ( msg : String );
(* YaccLib.yyerror redefined to ignore 'syntax error' message; the parser
does its own error handling *)
function sym ( k : Integer ) : Integer;
(* returns internal symbol number for the symbol k; if k is yet undefined,
a new nonterminal or literal symbol is created, according to the
appearance of symbol k (nonterminal if an ordinary identifier, literal
otherwise) *)
function ntsym ( k : Integer ) : Integer;
(* like sym, but requires symbol k to be a nonterminal symbol; if it
is already defined a literal, an error message is issued, and a dummy
nonterminal symbol returned *)
function litsym ( k : Integer; n : Integer ) : Integer;
(* same for literal symbols; if n>0 it denotes the literal number to be
assigned to the symbol; when a new literal identifier is defined, a
corresponding constant definition is also written to the definition
file *)
procedure next_section;
(* find next section mark (%%) in code template *)
procedure definitions;
(* if necessary, write out definition of the semantic value type YYSType *)
procedure copy_code;
(* copy Turbo Pascal code section ( %{ ... %} ) to output file *)
procedure copy_action;
(* copy an action to the output file *)
procedure copy_single_action;
(* like copy_action, but action must be single statement terminated
with `;' *)
procedure copy_rest_of_file;
(* copies the rest of the source file to the output file *)
procedure start_rule ( sym : Integer );
(* start a new rule with lhs nonterminal symbol sym *)
procedure start_body;
(* start a new rule body (rhs) *)
procedure end_body;
(* end a rule body *)
procedure add_symbol ( sym : Integer );
(* add the denoted symbol to the current rule body *)
procedure add_action;
(* add an action to the current rule body *)
procedure add_rule_prec ( sym : Integer );
(* add the precedence of terminal symbol sym to the current rule *)
procedure generate_parser;
(* generate the parse table *)
implementation
uses YaccBase, YaccTabl, YaccClos, YaccLR0, YaccLook,
YaccPars, YaccMsgs;
procedure yyerror ( msg : String );
begin
if msg='syntax error' then
(* ignore *)
else
fatal(msg)
end(*yyerror*);
function act_char : char;
begin
if cno>length(line) then
if eof(yyin) then
act_char := #0
else
act_char := nl
else
act_char := line[cno]
end(*act_char*);
function lookahead_char : char;
begin
if succ(cno)>length(line) then
if eof(yyin) then
lookahead_char := #0
else
lookahead_char := nl
else
lookahead_char := line[succ(cno)]
end(*lookahead_char*);
procedure next_char;
begin
if cno>length(line) then
if eof(yyin) then
{ nop }
else
begin
readln(yyin, line);
inc(lno); cno := 1
end
else
inc(cno)
end(*next_char*);
var
(* Current rule: *)
act_rule : RuleRec;
(* Actions: *)
n_act : Integer;
p_act : Boolean;
function sym ( k : Integer ) : Integer;
var s : Integer;
begin
if is_def_key(k, s) then
sym := s
else if sym_table^[k].pname^[1]='''' then
begin
s := new_lit;
def_key(k, s);
sym := s;
end
else
begin
s := new_nt;
def_key(k, s);
sym := s;
end
end(*sym*);
function ntsym ( k : Integer ) : Integer;
var s : Integer;
begin
if is_def_key(k, s) then
if s<0 then
ntsym := s
else
begin
error(nonterm_expected);
ntsym := -1;
end
else if sym_table^[k].pname^[1]='''' then
begin
error(nonterm_expected);
ntsym := -1;
end
else
begin
s := new_nt;
def_key(k, s);
ntsym := s;
end
end(*ntsym*);
function litsym ( k : Integer; n : Integer ) : Integer;
var s : Integer;
begin
if is_def_key(k, s) then
if s>=0 then
begin
if n>0 then error(double_tokennum_def);
litsym := s;
end
else
begin
error(literal_expected);
litsym := 1;
end
else if sym_table^[k].pname^[1]='''' then
begin
if n>0 then
begin
add_lit(n);
s := n;
end
else
s := new_lit;
def_key(k, s);
litsym := s;
end
else
begin
if n>0 then
begin
add_lit(n);
s := n;
end
else
s := new_lit;
def_key(k, s);
writeln(yyout, 'const ', pname(s), ' = ', s, ';');
litsym := s;
end;
end(*litsym*);
procedure next_section;
var line : String;
begin
while not eof(yycod) do
begin
readln(yycod, line);
if line='%%' then exit;
writeln(yyout, line);
end;
end(*next_section*);
procedure definitions;
var i : Integer;
begin
if n_types>0 then
begin
writeln(yyout);
writeln(yyout, 'type YYSType = record case Integer of');
for i := 1 to n_types do
writeln(yyout, ' ':15, i:3, ' : ( ',
'yy', sym_table^[type_table^[i]].pname^, ' : ',
sym_table^[type_table^[i]].pname^, ' );');
writeln(yyout, ' ':15, 'end(*YYSType*);');
end;
end(*definitions*);
procedure copy_code;
var str_state : Boolean;
begin
str_state := false;
while act_char<>#0 do
if act_char=nl then
begin
writeln(yyout);
next_char;
end
else if act_char='''' then
begin
write(yyout, '''');
str_state := not str_state;
next_char;
end
else if not str_state and (act_char='%') and (lookahead_char='}') then
exit
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -