packages feed

HaRe-0.6: tools/base/parse2/LexerNotes.html

<link rel="alternate stylesheet" type="text/css" HREF="/~hallgren/src2.css" title="Midnight Hacker">
<link rel="stylesheet" type="text/css" HREF="/~hallgren/src.css" title="Normal">

Some useful notes by
<a href="http://www.cse.ogi.edu/~diatchki/">Iavor S. Diatchki</a>.
<small>(Converted to HTML by
<a href="http://www.cse.ogi.edu/~hallgren/">Thomas Hallgren</a>)</small>
<h2>The Lexer</h2>

We use <code class=code>LexerGen/HsLexerGen</code> to generate
<a href="Lexer/HsLex.hs"><code class=code>Lexer/HsLex.hs</code></a> which is the
basic lexer.  Its main goal is to define:
<pre class=code>
haskellLex :: String -> [(Token,String)]
</pre>
<code class=code>Token</code> is defined in
<a href="Lexer/HsTokens.hs"><code class=code>Lexer/HsTokens.hs</code></a>,
and it is basically the
different types of token we have.  The string is the value of the
token.

<hr>

Next comes
<a href="Lexer/HsLexerPass1.hs"><code class=code>Lexer/HsLexerPass1.hs</code></a>
which makes use of the basic lexer
<code class=code>haskellLex</code>.  Its main goal is to define:
<pre class=code>
lexerPass0 :: String -> [(Token,(Pos,String))]
lexerPass1Only :: [(Token,(Pos,String))] -> [(Token,(Pos,String))]
</pre>
<code class=code>lexerPass0</code> uses haskellLex to separate the input into tokens, and
then annotates them with their positions.  <code class=code>lexerPass1Only</code> removes
whitespace tokens from the input.
<p>
At this stage <code class=code>Pos</code> is simply a pair of Int (defined in
<code class=code>Lexer/HsLexerPass1.hs</code>).  The format is (rows,cols).  Positions start
at (1,1).

<hr>

Finally the file
<a href="Lexer/HsLexer.hs"><code class=code>Lexer/HsLexer.hs</code></a> contains the
real lexer that can
interact with the Happy grammar.  It defines <code class=code>lexer</code>
<pre class=code>
lexer :: ((Token,(SrcLoc,String)) -> PM a) -> PM a
</pre>
Here <CODE CLASS=CODE>PM</CODE> is the parsing monad, located in
<a href="ParseMonad.hs"><code class=code>ParseMonad.hs</code></a>
The lexer expects the parsing monad to have a state component of type:
<pre class=code>
type State = ([(Token,(SrcPos,String)],[Int])
</pre>
The first component of the state is the list of remaining tokens.
The second component is the layout context, i.e. a stack keeping track
of indentations of blocks of declarations.
<p>
The lexer accesses the state with the aid of three functions:
<pre class=code>
get         :: PM State
set         :: State -> PM ()
setreturn   :: a -> State -> PM a
fail        :: String -> PM a
</pre>
(setreturn is simply an optiomization (is it wortherd?),
setreturn x s = set s >> return x
)

<p>
Currently the file <code class=code>ParseMonad.hs</code> also defines:

<pre class=code>
eoftoken = (GotEOF,(eof,""))
eof = SrcLoc "?" (-1) (-1) -- hmm
(this is also used in HsLexer.hs)
</pre>

<p>
<code class=code>SrcLoc</code>
is a type defined in
<a href="../AST/SrcLoc.hs"><code class=code>../AST/SrcLoc.hs</code></a>
and is positions with file
names in them.  The conversion from <code class=code>Pos</code> to <code class=code>SrcLoc</code>
happens in a function parseTokens defined in <code class=code>ParseMonad.hs</code>.