200 lines (155 with data), 5.3 kB
@! analyze.fw -- first edit Mon Dec 19 1994 -- by Karl Prott
@p typesetter = tex
@p maximum_input_line_length = infinity
\documentstyle[11pt,a4]{article}
\setlength{\textwidth}{16.5cm}
\setlength{\textheight}{25cm}
\setlength{\parindent}{0mm}
\setlength{\parskip}{6pt}
\setlength{\voffset}{-1in}
\setlength{\hoffset}{-0.5in}
% Defaults for offset
% \setlength{\voffset}{0pt}
% \setlength{\hoffset}{0pt}
\begin{document}
\section{Semantic analysis}
This part implements the consistent renaming task and the
classification into terminals and nonterminals.
\begin{description}
{\tt
\item[depends on:] {\it nothing\/}
\item[exports:]
\begin{tabular}{l | l}
Attribute & For Symbols \\\hline
Key, Sym & connection, literal, grammarname, rulename,
nonterminal,\\
& nonliteral, terminal, t\_or\_nt, modification\\
type & terminal, nonterminal, t\_or\_nt \\
\end{tabular}
}
\end{description}
\subsection{Consistent Renaming}
Two name spaces are defined. One name space is used for literal
symbols and the other for nonliteral symbols. This is necessary to
distinguish {\tt A} from {\tt 'A'}, because literal symbols are stored
without delimiters. The symbols {\tt literal, connection} represent a
literal symbol and the symbols {\tt grammarname, rulename,
nonterminal, nonliteral} represent nonliteral symbols. {\tt
terminal, t\_or\_nt, modification} may be both.
@O@<rename.specs@>@{
$/Name/AlgScope.gnrc +instance=Literal :inst
$/Name/AlgScope.gnrc +instance=Nonliteral :inst
@}
@O@<rename.lido@>@{
ATTR Sym: int;
ATTR Key: DefTableKey;
SYMBOL LiteralIdDefScope COMPUTE
SYNT.Sym = TERM;
END;
SYMBOL NonliteralIdDefScope COMPUTE
SYNT.Sym = TERM;
END;
SYMBOL root INHERITS LiteralRootScope, NonliteralRootScope END;
SYMBOL connection INHERITS LiteralIdDefScope END;
SYMBOL literal INHERITS LiteralIdDefScope END;
SYMBOL grammarname INHERITS NonliteralIdDefScope END;
SYMBOL rulename INHERITS NonliteralIdDefScope END;
SYMBOL nonterminal INHERITS NonliteralIdDefScope END;
SYMBOL nonliteral INHERITS NonliteralIdDefScope END;
SYMBOL lit_or_nonlit COMPUTE
SYNT.Key = CONSTITUENT (literal.Key, nonliteral.Key);
SYNT.Sym = CONSTITUENT (literal.Sym, nonliteral.Sym);
END;
SYMBOL terminal INHERITS lit_or_nonlit END;
SYMBOL t_or_nt INHERITS lit_or_nonlit END;
SYMBOL modification INHERITS lit_or_nonlit END;
@}
\subsection{Classifying in Terminals and Nonterminals}
For symbol {\tt t\_or\_nt} it is necessary to decide whether it
represents a terminal or a nonterminal. If a symbol is classified as
terminal and nonterminal an error message is printed. Property {\tt
Class} implements the result of the classification.
@O@<classify.head@>@{
#include "classify.h"
#include "err.h"
@}
@O@<classify.pdl@>@{
Class: int;
@}
@O@<classify.lido@>@{
/**** Classifying in terminals and nonterminals ****/
/***************************************************/
ATTR type: int;
ATTR Class, GotAllClass: VOID;
SYMBOL root COMPUTE
SYNT.GotAllClass = CONSTITUENTS(nonterminal.Class, terminal.Class);
END;
SYMBOL terminal COMPUTE
SYNT.type = Kp_term;
SYNT.Class = Classify(THIS.Key, TERMINAL);
IF( EQ(GetClass(THIS.Key, FAULT), FAULT),
message(ERROR, MESSAGE1, 0, COORDREF)
) DEPENDS_ON INCLUDING root.GotAllClass;
END;
SYMBOL nonterminal COMPUTE
SYNT.type = Kp_nterm;
SYNT.Class = Classify(THIS.Key, NONTERMINAL);
IF( EQ(GetClass(THIS.Key, FAULT), FAULT),
message(ERROR, MESSAGE2, 0, COORDREF)
) DEPENDS_ON INCLUDING root.GotAllClass;
END;
SYMBOL t_or_nt COMPUTE
SYNT.Class = IF( EQ(GetClass(THIS.Key, UNDEF), UNDEF),
ResetClass(THIS.Key, TERMINAL)
) DEPENDS_ON INCLUDING root.GotAllClass;
SYNT.type =
IF( EQ(GetClass(THIS.Key, UNDEF), NONTERMINAL), Kp_nterm, Kp_term)
DEPENDS_ON THIS.Class;
END;
@}
@O@<classify.h@>@{
#ifndef CLASSIFY_H
#define CLASSIFY_H
#include "deftbl.h" /* for DefTableKey */
#define FAULT (-1)
#define UNDEF 0
#define TERMINAL 1
#define NONTERMINAL 2
#define MESSAGE1 "Terminal expected: symbol has been used as nonterminal too"
#define MESSAGE2 "Nonterminal expected: symbol has been used as terminal too"
extern void
#if defined(__STDC__) || defined(__cplusplus)
Classify(DefTableKey key, int class);
#else
Classify();
#endif
#endif
@}
@O@<classify.c@>@{
#include "classify.h"
#include "pdl_gen.h"
void
#if defined(__STDC__) || defined(__cplusplus)
Classify(DefTableKey key, int class)
#else
Classify(key, class)
int class;
DefTableKey key;
#endif
{
switch ( GetClass(key, UNDEF) )
{
case FAULT : break;
case UNDEF : ResetClass(key, class);
break;
case TERMINAL : if ( class == NONTERMINAL )
ResetClass(key, FAULT);
break;
case NONTERMINAL: if ( class == TERMINAL )
ResetClass(key, FAULT);
break;
} /* of switch */
return;
} /* of Classify() */
@}
\end{document}