<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>compiler-construction &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/compiler-construction/</link>
	<description>Feed of posts on WordPress.com tagged "compiler-construction"</description>
	<pubDate>Sun, 06 Dec 2009 04:54:36 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Expression Evaluator: Part 1 - Tokenizer]]></title>
<link>http://robertsundstrom.wordpress.com/?p=1274</link>
<pubDate>Wed, 12 Aug 2009 15:50:23 +0000</pubDate>
<dc:creator>Robert</dc:creator>
<guid>http://robertsundstrom.wordpress.com/?p=1274</guid>
<description><![CDATA[In this series in three parts I will continue with my attempt to write about compiler construction. ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>In this series in three parts I will continue with my attempt to write about compiler construction. It is a very large field and there is a lot of theory.&#160; Compilers are very complex and therefore hard to implement by hand.&#160; Thank goodness that there are tools for making the most of the complicated stuff. It is however important that developers know how it works and can implement some parts of the compiler by themselves without help from tools.</p>
<p>Mathematical expressions make an essential part of a programming language so I will show you how I would implement a simple expression evaluator in C#. I will build a<em> tokenizer</em>, a <em>parser</em> and finally a <em>code generator</em>. All from scratch with no special tools. It is not as hard as you may think.</p>
<p>In this part (the first) I will show you how a <em>lexical scanner</em> works. A scanner is sometimes known as a tokenizer. I will use that name in my article. As you see I have prepared a little walkthrough and it is as fresh as the code in it. It was completely written solely for this article.</p>
<h3>Tokenizer</h3>
<p>A tokenizer is a state-machine. It matches states of a special pattern to the characters in the input stream. When a state has been achieved it saves the token and start all over again. But if there are no characters left to read it will quit.</p>
<p>This implementation I have made identifies the tokens one by one. If there are not anything more to read from the input stream it will return an EOF-token (End-Of-File).</p>
<p>A token is identified inside the <em>Next()-</em>method which is the actual state-machine. A complex machinery built with control statements you are familiar with. It walks through the stream and checks every character and decides what to do with it.</p>
<p>This shows the part were numbers are identified:</p>
<pre class="code"><span style="color:blue;">while </span>(<span style="color:blue;">this</span>.HasNext)
{
    <span style="color:blue;">char </span>ch = <span style="color:blue;">this</span>.PeekChar();

    <span style="color:blue;">if </span>(<span style="color:blue;">char</span>.IsDigit(ch))
    {
        stringBuilder.Append(ch);
        <span style="color:blue;">this</span>.NextChar();

        <span style="color:blue;">this</span>.Col++;
        <span style="color:blue;">this</span>.Ch++;

        ch = <span style="color:blue;">this</span>.PeekChar();

        <span style="color:blue;">while</span>(<span style="color:blue;">char</span>.IsDigit(ch))
        {
            stringBuilder.Append(ch);
            <span style="color:blue;">this</span>.NextChar();

            <span style="color:blue;">this</span>.Col++;
            <span style="color:blue;">this</span>.Ch++;

            ch = <span style="color:blue;">this</span>.PeekChar();
        }

        token = <span style="color:blue;">new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Number</span>() {
            Value = stringBuilder.ToString(),
            Index = start_Index,
            Col = start_Col,
            Ch = start_Ch,
            Ln = <span style="color:blue;">this</span>.Ln,
        };
    }</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>The machine moves forward in the character stream by calling the<em> NextChar()</em> method. That will change the parameters that save the current source location too. The current state is copied to a token when any has been identified.</p>
<pre class="code"><span style="color:blue;">public char </span>NextChar()
{
    <span style="color:blue;">this</span>.Index++;
    <span style="color:blue;">this</span>.Col++;
    <span style="color:blue;">this</span>.Ch++;

    <span style="color:blue;">return </span>(<span style="color:blue;">char</span>)<span style="color:blue;">this</span>._reader.Read();
}</pre>
<p>The token is an instance of a class that inherits the abstract base class <em>Token</em>. In my example the classes are nested into the base class to make it clear that they all are types of tokens. As seen there are five types of tokens: identifiers, numbers, operators, delimiters and sequence tokens.</p>
<div style="overflow:auto;">
<pre class="code"><span style="color:blue;">public abstract class </span><span style="color:#2b91af;">Token
</span>{
    <span style="color:blue;">public string </span>Value { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }

    <span style="color:blue;">public </span><span style="color:#2b91af;">TokenKind </span>Kind { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }
    <span style="color:blue;">public </span><span style="color:#2b91af;">TokenCategory </span>Category { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }

    <span style="color:blue;">public int </span>Index { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }
    <span style="color:blue;">public int </span>Ch { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }
    <span style="color:blue;">public int </span>Col { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }
    <span style="color:blue;">public int </span>Ln { <span style="color:blue;">get</span>; <span style="color:blue;">set</span>; }

    <span style="color:blue;">public </span><span style="color:#2b91af;">SourceLocation </span>GetStartLoc()
    {
        <span style="color:blue;">return new </span><span style="color:#2b91af;">SourceLocation</span>(<span style="color:blue;">this</span>.Index, <span style="color:blue;">this</span>.Col, <span style="color:blue;">this</span>.Ln);
    }

    <span style="color:blue;">public class </span><span style="color:#2b91af;">Identifier </span>: <span style="color:#2b91af;">Token
    </span>{
        <span style="color:blue;">public </span>Identifier()
        {
            <span style="color:blue;">this</span>.Kind = <span style="color:#2b91af;">TokenKind</span>.IDENTIFIER;
            <span style="color:blue;">this</span>.Category = <span style="color:#2b91af;">TokenCategory</span>.Identifier;
        }
    }

    <span style="color:blue;">public class </span><span style="color:#2b91af;">Number </span>: <span style="color:#2b91af;">Token
    </span>{
        <span style="color:blue;">public </span>Number()
        {
            <span style="color:blue;">this</span>.Kind = <span style="color:#2b91af;">TokenKind</span>.NUMBER;
            <span style="color:blue;">this</span>.Category = <span style="color:#2b91af;">TokenCategory</span>.Number;
        }
    }

    <span style="color:blue;">public class </span><span style="color:#2b91af;">Operator </span>: <span style="color:#2b91af;">Token
    </span>{
        <span style="color:blue;">public </span>Operator()
        {
            <span style="color:blue;">this</span>.Category = <span style="color:#2b91af;">TokenCategory</span>.Operator;
        }
    }

    <span style="color:blue;">public class </span><span style="color:#2b91af;">SequenceToken </span>: <span style="color:#2b91af;">Token
    </span>{
        <span style="color:blue;">public </span>SequenceToken()
        {
            <span style="color:blue;">this</span>.Category = <span style="color:#2b91af;">TokenCategory</span>.SequenceToken;
        }
    }

    <span style="color:blue;">public class </span><span style="color:#2b91af;">Delimiter </span>: <span style="color:#2b91af;">Token
    </span>{
        <span style="color:blue;">public </span>Delimiter()
        {
            <span style="color:blue;">this</span>.Category = <span style="color:#2b91af;">TokenCategory</span>.Delimiter;
        }
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
</div>
<p>Another feature of the tokenizer is the <em>LookaheadToken</em>. It peeks the next token by identifying it and put it in a state buffer. The <em>NextToken() </em>method will return it from the buffer and move the pointer the next time it is called.<em> (Note that PeekToken just is another way to call LookaheadToken)</em></p>
<div style="height:607px;overflow:auto;">
<pre class="code"><span style="color:blue;">public </span><span style="color:#2b91af;">Token </span>LookaheadToken
{
    <span style="color:blue;">get
    </span>{
        <span style="color:blue;">if </span>(_tokenBuffer == <span style="color:blue;">null</span>)
        {
            <span style="color:#2b91af;">Token </span>lookaheadToken = Next();

            <span style="color:green;">// Save position
            </span><span style="color:blue;">int </span>index = <span style="color:blue;">this</span>.Index;
            <span style="color:blue;">int </span>ch = <span style="color:blue;">this</span>.Ch;
            <span style="color:blue;">int </span>ln = <span style="color:blue;">this</span>.Ln;
            <span style="color:blue;">int </span>col = <span style="color:blue;">this</span>.Col;

            <span style="color:green;">// Get next token and save it to buffer
            </span>_tokenBuffer = <span style="color:blue;">new </span><span style="color:#2b91af;">TokenBufferState</span>(lookaheadToken, Index, Ln, Col, Ch);

            <span style="color:green;">// Restore position
            </span><span style="color:blue;">this</span>.Index = index;
            <span style="color:blue;">this</span>.Ch = ch;
            <span style="color:blue;">this</span>.Ln = ln;
            <span style="color:blue;">this</span>.Col = col;
        }

        <span style="color:blue;">return </span>_tokenBuffer.Token;
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
</div>
<p>You may have realized that the tokenizer just is doing regular expressions. So it is nothing you are not familiar with to say. It is just another way of expressing.</p>
<p>Now you have the opportunity to add some of your own stuff to the tokenizer.</p>
<h3>Exercise</h3>
<p>You have now studied the code and I think that you are ready to try to add new functionality to the tokenizer. You have probably noticed that there are some features missing. One of those are identifiers (variables). There is a token class but no identifier-tokens are produced by the tokenizer. I suggest that you try to implement that.</p>
<p>The same thing about decimal numbers. The tokenizer will produce an error on that when it comes to a period or a comma.</p>
<p>In the next part of this series you will be introduced to the parser.</p>
<p>‘til then… Happy coding! <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Here is the complete Tokenizer-class. You can download the entire Visual Studio-project from&#160; <a href="http://www.mediafire.com/?sharekey=835f72c49f7fe3f51686155677bb26853f0e8e1900719042">here</a>.</p>
<div style="height:700px;overflow:auto;">
<pre class="code"><span style="color:blue;">public class </span><span style="color:#2b91af;">Tokenizer
    </span>{
        <span style="color:blue;">private </span>System.IO.<span style="color:#2b91af;">TextReader </span>_reader;
        <span style="color:blue;">private </span><span style="color:#2b91af;">TokenBufferState </span>_tokenBuffer;
        <span style="color:blue;">private </span><span style="color:#2b91af;">List</span>&#60;<span style="color:#2b91af;">Error</span>&#62; _errors;

        <span style="color:blue;">public </span>Tokenizer(System.IO.<span style="color:#2b91af;">TextReader </span>reader)
        {
            <span style="color:blue;">this</span>._errors = <span style="color:blue;">new </span><span style="color:#2b91af;">List</span>&#60;<span style="color:#2b91af;">Error</span>&#62;();
            <span style="color:blue;">this</span>._reader = reader;

            <span style="color:blue;">this</span>.Index = -1;
            <span style="color:blue;">this</span>.Col = 0;
            <span style="color:blue;">this</span>.Ch = -1;
            <span style="color:blue;">this</span>.Ln = 1;
        }

        <span style="color:blue;">public </span><span style="color:#2b91af;">Token </span>NextToken()
        {
            <span style="color:blue;">if </span>(_tokenBuffer != <span style="color:blue;">null</span>)
            {
                CurrentToken = _tokenBuffer.Token;

                Index = _tokenBuffer.Index;
                Ln = _tokenBuffer.Ln;
                Ch = _tokenBuffer.Ch;
                Col = _tokenBuffer.Col;

                _tokenBuffer = <span style="color:blue;">null</span>;

                <span style="color:blue;">return </span>CurrentToken;
            }

            CurrentToken = Next();

            <span style="color:blue;">return </span>CurrentToken;
        }

        <span style="color:blue;">private </span><span style="color:#2b91af;">Token </span>Next()
        {
            <span style="color:#2b91af;">Token </span>token = <span style="color:blue;">null</span>;

            <span style="color:blue;">int </span>start_Index = <span style="color:blue;">this</span>.Index + 1;
            <span style="color:blue;">int </span>start_Col = <span style="color:blue;">this</span>.Col + 1;
            <span style="color:blue;">int </span>start_Ch = <span style="color:blue;">this</span>.Ch + 1;

            <span style="color:#2b91af;">StringBuilder </span>stringBuilder = <span style="color:blue;">new </span><span style="color:#2b91af;">StringBuilder</span>();

            <span style="color:blue;">while </span>(<span style="color:blue;">this</span>.HasNext)
            {
                <span style="color:blue;">char </span>ch = <span style="color:blue;">this</span>.PeekChar();

                <span style="color:blue;">if </span>(<span style="color:blue;">char</span>.IsDigit(ch))
                {
                    stringBuilder.Append(ch);
                    <span style="color:blue;">this</span>.NextChar();

                    ch = <span style="color:blue;">this</span>.PeekChar();

                    <span style="color:blue;">while</span>(<span style="color:blue;">char</span>.IsDigit(ch))
                    {
                        stringBuilder.Append(ch);
                        <span style="color:blue;">this</span>.NextChar();

                        ch = <span style="color:blue;">this</span>.PeekChar();
                    }

                    token = <span style="color:blue;">new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Number</span>() {
                        Value = stringBuilder.ToString(),
                        Index = start_Index,
                        Col = start_Col,
                        Ch = start_Ch,
                        Ln = <span style="color:blue;">this</span>.Ln,
                    };
                }

                <span style="color:blue;">if </span>(token != <span style="color:blue;">null</span>)
                {
                    <span style="color:blue;">return </span>token;
                }

                <span style="color:blue;">switch </span>(ch)
                {
                    <span style="color:blue;">case </span><span style="color:#a31515;">'+'</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Operator</span>()
                        {
                            Value = <span style="color:#a31515;">&#34;+&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.ADD,
                        };
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">'-'</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Operator</span>()
                        {
                            Value = <span style="color:#a31515;">&#34;-&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.SUB,
                        };
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">'*'</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Operator</span>()
                        {
                            Value = <span style="color:#a31515;">&#34;*&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.MUL,
                        };
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">'/'</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Operator</span>()
                        {
                            Value = <span style="color:#a31515;">&#34;/&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.DIV,
                        };
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">'^'</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Operator</span>()
                        {
                            Value = <span style="color:#a31515;">&#34;^&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.POW,
                        };
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">'%'</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Operator</span>()
                        {
                            Value = <span style="color:#a31515;">&#34;%&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.REM,
                        };
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">'('</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Delimiter</span>()
                        {
                            Value = <span style="color:#a31515;">&#34;(&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.LPAR,
                        };
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">')'</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">Delimiter</span>()
                        {
                            Value = <span style="color:#a31515;">&#34;)&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.RPAR,
                        };
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">'\n'</span>:
                        <span style="color:blue;">this</span>.Ln++;
                        <span style="color:blue;">this</span>.NextEscapeChar();

                        <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">SequenceToken</span>() {
                            Value = <span style="color:#a31515;">&#34;EOL&#34;</span>,
                            Index = start_Index,
                            Col = start_Col,
                            Ch = start_Ch,
                            Ln = <span style="color:blue;">this</span>.Ln,
                            Kind = <span style="color:#2b91af;">TokenKind</span>.EOL,
                        };
                        <span style="color:blue;">this</span>.Col = -1;
                        <span style="color:blue;">this</span>.Ch = -1;
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">case </span><span style="color:#a31515;">' '</span>:
                        <span style="color:blue;">this</span>.NextChar();
                        <span style="color:blue;">break</span>;

                    <span style="color:blue;">default</span>:
                        <span style="color:blue;">this</span>.NextChar();

                        <span style="color:blue;">string </span>text = <span style="color:blue;">string</span>.Format(<span style="color:#a31515;">&#34;Unexpected character \'{0}\'.&#34;</span>, ch);

                        <span style="color:#2b91af;">SourceLocation </span>location = <span style="color:blue;">new </span><span style="color:#2b91af;">SourceLocation</span>(<span style="color:blue;">this</span>.Index, <span style="color:blue;">this</span>.Col, <span style="color:blue;">this</span>.Ln);
                        <span style="color:#2b91af;">Error </span>error = <span style="color:blue;">new </span><span style="color:#2b91af;">Error</span>(text, location);

                        <span style="color:blue;">this</span>._errors.Add(error);
                        <span style="color:blue;">break</span>;
                }
            }

            <span style="color:blue;">return new </span><span style="color:#2b91af;">Token</span>.<span style="color:#2b91af;">SequenceToken</span>() {
                Value=<span style="color:#a31515;">&#34;EOL&#34;</span>,
                Index = start_Index,
                Col = start_Col,
                Ch = start_Ch,
                Ln = <span style="color:blue;">this</span>.Ln,
                Kind = <span style="color:#2b91af;">TokenKind</span>.EOF
            };
        }

        <span style="color:blue;">public </span><span style="color:#2b91af;">Token </span>LookaheadToken
        {
            <span style="color:blue;">get
            </span>{
                <span style="color:blue;">if </span>(_tokenBuffer == <span style="color:blue;">null</span>)
                {
                    <span style="color:#2b91af;">Token </span>lookaheadToken = Next();

                    <span style="color:green;">// Save position
                    </span><span style="color:blue;">int </span>index = <span style="color:blue;">this</span>.Index;
                    <span style="color:blue;">int </span>ch = <span style="color:blue;">this</span>.Ch;
                    <span style="color:blue;">int </span>ln = <span style="color:blue;">this</span>.Ln;
                    <span style="color:blue;">int </span>col = <span style="color:blue;">this</span>.Col;

                    <span style="color:green;">// Get next token and save it to buffer
                    </span>_tokenBuffer = <span style="color:blue;">new </span><span style="color:#2b91af;">TokenBufferState</span>(lookaheadToken, Index, Ln, Col, Ch);

                    <span style="color:green;">// Restore position
                    </span><span style="color:blue;">this</span>.Index = index;
                    <span style="color:blue;">this</span>.Ch = ch;
                    <span style="color:blue;">this</span>.Ln = ln;
                    <span style="color:blue;">this</span>.Col = col;
                }

                <span style="color:blue;">return </span>_tokenBuffer.Token;
            }
        }

        <span style="color:blue;">public </span><span style="color:#2b91af;">Token </span>PeekToken()
        {
            <span style="color:blue;">return this</span>.LookaheadToken;
        }

        <span style="color:blue;">public </span><span style="color:#2b91af;">Token </span>CurrentToken
        {
            <span style="color:blue;">get</span>;
            <span style="color:blue;">protected set</span>;
        }

        <span style="color:blue;">public char </span>NextChar()
        {
            <span style="color:blue;">this</span>.Index++;
            <span style="color:blue;">this</span>.Col++;
            <span style="color:blue;">this</span>.Ch++;

            <span style="color:blue;">return </span>(<span style="color:blue;">char</span>)<span style="color:blue;">this</span>._reader.Read();
        }

        <span style="color:blue;">public char </span>NextEscapeChar()
        {
            <span style="color:blue;">this</span>.Index++;
            <span style="color:blue;">this</span>.Ch++;

            <span style="color:blue;">return </span>(<span style="color:blue;">char</span>)<span style="color:blue;">this</span>._reader.Read();
        }

        <span style="color:blue;">public char </span>PeekChar()
        {
            <span style="color:blue;">return </span>(<span style="color:blue;">char</span>)<span style="color:blue;">this</span>._reader.Peek();
        }

        <span style="color:blue;">public bool </span>HasNext
        {
            <span style="color:blue;">get </span>{ <span style="color:blue;">return this</span>._reader.Peek() != -1; }
        }

        <span style="color:blue;">public int </span>Index { <span style="color:blue;">get</span>; <span style="color:blue;">protected set</span>; }
        <span style="color:blue;">public int </span>Col { <span style="color:blue;">get</span>; <span style="color:blue;">protected set</span>; }
        <span style="color:blue;">public int </span>Ch { <span style="color:blue;">get</span>; <span style="color:blue;">protected set</span>; }
        <span style="color:blue;">public int </span>Ln { <span style="color:blue;">get</span>; <span style="color:blue;">protected set</span>; }

        <span style="color:blue;">public </span><span style="color:#2b91af;">List</span>&#60;<span style="color:#2b91af;">Error</span>&#62; Errors
        {
            <span style="color:blue;">get
            </span>{
                <span style="color:blue;">return this</span>._errors;
            }
        }
    }</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
</div>
<p><strong>Links:</strong></p>
<ul>
<li><a href="http://robertsundstrom.wordpress.com/2009/06/28/lexical-scanners/">Previous blogpost about lexical scanners</a> </li>
<li><a href="http://www.mediafire.com/?sharekey=835f72c49f7fe3f51686155677bb26853f0e8e1900719042">Project files</a> </li>
</ul>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Lexical scanners]]></title>
<link>http://robertsundstrom.wordpress.com/2009/06/28/lexical-scanners/</link>
<pubDate>Sun, 28 Jun 2009 20:49:47 +0000</pubDate>
<dc:creator>Robert</dc:creator>
<guid>http://robertsundstrom.wordpress.com/2009/06/28/lexical-scanners/</guid>
<description><![CDATA[How do a scanner work then? Is it hard to write one by hand? I will show you and no it is not. Let]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>How do a scanner work then? Is it hard to write one by hand? I will show you and no it is not.</p>
<p>Let&#8217;s start with theory.</p>
<p>A scanner is a finite state-machine, or more precisely a <em><a href="http://en.wikipedia.org/wiki/Deterministic_finite_state_machine">Deterministic Finite-state Machine</a> (DFSM).</em> It handles different states through regular expressions. In this case it maps the characters in the input stream to the rules. Do not worry if this does do not make sense right now.</p>
<p>The DFSM has a starting state and from that you may fulfill some conditions to reach another state, and another from that. If there are no condition that can be satisfied you simply go back to the initial state.</p>
<p>We will take a look at this example where we have a string: &#8220;foozie30 23.3&#8243;. A valid DFSM for this input could be drawn like this:</p>
<p><img class="alignnone size-full wp-image-984" title="dfa" src="http://robertsundstrom.wordpress.com/files/2009/06/dfa.png" alt="dfa" width="317" height="377" /></p>
<p>The most common ways of implementing this state machine in an imperative programming language would be using state controllers <em>like if, while </em>and <em>for</em> or any equivalents. You process each character and when you got the string you return an object of a type which symbolizes the symbol that was found. In an object-oriented language it would be even simpler to implement if you ask me.</p>
<p>If you want to take a look at an implementation you just download my <em><a href="http://www.mediafire.com/?sharekey=835f72c49f7fe3f5d2db6fb9a8902bda">Expression parser</a> </em>project. <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Most <em>compiler geeks</em>, as they are called, are using parser generators and grammars that create both scanner and parser. A parser is far more advanced than scanner. It is not impossible to write them by hand, as I have shown, but generally it is regarded as better writing a grammar and then let the generator create the scanner and the parser for you.</p>
<p>Compilers are very interesting both in theory and in their implementations. Because it is such a large subject you will probably not find this enough. That is why I am planning to write more articles about compilers and techniques that can be used while writing one.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Parsing using Packrat]]></title>
<link>http://spacelylinux.wordpress.com/2008/08/28/parsing-using-packrat/</link>
<pubDate>Thu, 28 Aug 2008 22:11:06 +0000</pubDate>
<dc:creator>spacelylinux</dc:creator>
<guid>http://spacelylinux.wordpress.com/2008/08/28/parsing-using-packrat/</guid>
<description><![CDATA[Working on the PEG (Parsing Expresion Grammar) for my thesis and it has been a fun but steep learnin]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Working on the PEG (Parsing Expresion Grammar) for my thesis and it has been a fun but steep learning curve. Currently working on a subset of a Toy programming language to show that Packrat can be of advantage to merge two different packrats together to ensure that there composibility. I intend to post of my code listings online and hope to keep track of my progress and also to aid anyone in future. Keep checking.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Reflection și obiecte dinamice]]></title>
<link>http://vladr.wordpress.com/2008/05/31/reflection-%c8%99i-obiecte-dinamice/</link>
<pubDate>Sat, 31 May 2008 09:43:49 +0000</pubDate>
<dc:creator>vladr</dc:creator>
<guid>http://vladr.wordpress.com/2008/05/31/reflection-%c8%99i-obiecte-dinamice/</guid>
<description><![CDATA[În cele ce urmează vreau să prezint un exemplu de lucru cu obiecte dinamice folosind Reflection. Nu ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>În cele ce urmează vreau să prezint un exemplu de lucru cu obiecte dinamice folosind Reflection. Nu ține atât de mult de compilatoare cât de interpretoare, unde, pe baza unor șiruri de caractere, instanțiem obiecte și facem apeluri de metode.</p>
<p>Avem clasa System.Type care încapsulează informații despre tipuri, precum și clasele ConstructorInfo și MethodInfo derivate din MethodBase care încapsulează informații despre constructori, respectiv metode, clase pe care le găsim în namespace-ul System.Reflection.</p>
<p>Pentru a crea de exemplu o instanță a clasei StringBuilder și a concatena două șiruri de caractere, avem următoarele linii de cod:</p>
<p><code>ConstructorInfo ci = Type.GetType("System.Text.StringBuilder").GetConstructor (Type.EmptyTypes);</code><br />
<code>object test = ci.Invoke(null);</code></p>
<p><code>MethodInfo mi = test.GetType().GetMethod("Append", new Type[] { typeof(string) });</code><br />
<code>mi.Invoke(test, new object[] { "Hello " });</code><br />
<code>mi.Invoke(test, new object[] { "World!" });</code></p>
<p><code>Console.WriteLine(test);</code></p>
<p>Se observă că, din punct de vedere al compilatorului de C#, StringBuilder nu apare decât într-un șir de caractere iar obiectul utilizat este de tipul de bază object. Prima instrucțiune întoarce o instanță ConstructorInfo ce corespunde constructorului fără parametri a clasei StringBuilder. Metoda statică Type.GetType returnează instanța System.Type corespunzătoare tipului identificat printr-un șir de caractere. GetConstructor primește ca parametrii un vector de tipuri care reprezintă tipurile argumentelor &#8211; în cazul nostru nu avem argumente așa că folosim Type.EmptyTypes care este, de fapt, echivalent cu <code>new Type[0]</code> dar ne scutește de instanțiere.</p>
<p>Invoke apelează metoda cu o listă de argumente, null în cazul nostru și întoarce un obiect (System.Object). Am creat astfel dinamic o instanță StringBuilder.</p>
<p>Similar, luăm instanța System.Type corespunzătoare obiectului &#8211; test.GetType() - și apelăm GetMethod care primește un nume de metodă și o listă de argumente. Căutăm metoda Append cu un singur argument de tip string.</p>
<p>Aici, la apelul Invoke trebuie să precizăm și instanța cu care apelăm metoda (obiectul test) și argumentele.</p>
<p>Ultima linie va afișa pe ecran &#8220;Hello World!&#8221;.</p>
<p>Dacă snippet-ul de mai sus pare încă destul de hard-coded, putem, în locul lui, introduce următoarele:<br />
un dicționar care să rețină instanțele pe care le-am creat, o metodă pentru a construi obiecte și o metodă pentru apeluri astfel:</p>
<p><code>private static Dictionary objects = new Dictionary();</code></p>
<p><code>public static void Create(string name, string type)</code><br />
<code>{</code><br />
<code>    ConstructorInfo ci = Type.GetType(type).GetConstructor(Type.EmptyTypes);</code><br />
<code>    object obj = ci.Invoke(null);</code></p>
<p><code>    objects.Add(name, obj);</code><br />
<code>}</code></p>
<p><code>public static void Call(string name, string method, params string[] arguments)</code><br />
<code>{</code><br />
<code>    // Aici construim tipurile pe baza argumentelor</code><br />
<code>    Type[] args = new Type[arguments.Length];</code></p>
<p><code>    for (int i = 0; i &#60; args.Length; i++)</code><br />
<code>    {</code><br />
<code>        // Doar tipul string</code><br />
<code>        args[i] = Type.GetType("System.String");</code><br />
<code>    }</code></p>
<p><code>    MethodInfo mi = objects[name].GetType().GetMethod(method, args);</code><br />
<code>    mi.Invoke(objects[name], arguments);</code><br />
<code>}</code></p>
<p>Metoda Create primește ca argumente un nume de variabilă și un tip și apelează constructorul fără parametri al tipului, metoda Call primește numele variabilei, numele metodei și o listă de argumente de tip string. M-am limitat în exemplu la constructori fără parametri și metode ce primesc argumente string nu pentru că Reflection nu mi-ar permite mai mult, doar că, pentru a determina alte tipuri doar pe baza unor string-uri am avea nevoie de un parser (care să determine, de exemplu, că &#8220;10.5&#8243; e de tip float).</p>
<p>Acum putem scrie &#8220;Hello World!&#8221; astfel:<br />
 <br />
<code>static void Main(string[] args)</code><br />
<code>{</code><br />
<code>    Create("test", "System.Text.StringBuilder");</code><br />
<code>    Call("test", "Append", "Hello ");</code><br />
<code>    Call("test", "Append", "World!");</code></p>
<p><code>    Console.WriteLine(objects["test"]);</code><br />
<code>}</code></p>
<p>Și nu numai:</p>
<p><code>static void Main(string[] args)</code><br />
<code>{</code><br />
<code>    Create("test", "System.Text.StringBuilder");</code><br />
<code>    Call("test", "AppendFormat", "{0} {1}!", "Hello", "World");</code></p>
<p><code>    Console.WriteLine(objects["test"]);</code><br />
<code>}</code></p>
<p>Astfel se crează obiecte și se apelează metode dinamic utilizând Reflection. Desigur, se pot face multe altele &#8211; de exemplu putem seta valori la diferite atribute ale obiectelor instanțiate. Un dezavantaj ar fi timpul de execuție &#8211; codul compilat (MSIL) rulează mult mai repede decât apelurile Invoke dar pentru un interpretor aceasta ar fi una din posibilitățile de implementare.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Jos stilourile]]></title>
<link>http://vladr.wordpress.com/2008/05/22/jos-stilourile/</link>
<pubDate>Thu, 22 May 2008 14:54:04 +0000</pubDate>
<dc:creator>vladr</dc:creator>
<guid>http://vladr.wordpress.com/2008/05/22/jos-stilourile/</guid>
<description><![CDATA[Astăzi am terminat de făcut ultimele modificări la lucrarea de licenţă. Pentru cine vrea să citească]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Astăzi am terminat de făcut ultimele modificări la lucrarea de licenţă. Pentru cine vrea să citească pe scurt despre construirea compilatoarelor sau doar să vadă un model de lucrare de licenţă, îi dau drumul pe internet: <a href="http://vladr.files.wordpress.com/2008/05/licenta.pdf" target="_blank">Generarea de cod executabil pe platforma .NET</a></p>
<p>Conţinut: teoria pe scurt (expresii regulate, automate finite, gramatici, parsere, tabele de simboluri, arbori abstracţi de sintaxă, optimizări, generare de cod), despre .NET Framework (platforma, CLR, assembly, metadata, MSIL, Reflection, Reflection.Emit) şi descrierea aplicaţiei cu snippet-uri de cod. Nu e detaliat pentru că ţinta a fost 60 de pagini, nu să scriu propriul Dragon Book. Despre punctele mai interesante pe care le-am identificat în faza de R&#38;D am scris şi aici câteva posturi.</p>
<p>Introducerea şi concluziile sunt abureli că deh, aşa trebuie. Dacă ar fi fost să fiu cinstit, motivaţia a fost să văd cum se face şi dacă pot să fac. Am învăţat că nu e imposibil şi, pentru că a trebuit să peticesc în diferite locuri, am să ştiu data viitoare să fac mai bine. Dezvoltare ulterioară nu va fi &#8211; eventual mă apuc de altul de la zero.</p>
<p>Codul sursă îl voi pune pe net undeva, cândva. Deocamdată am observat că WordPress nu mă lasă să fac upload decât la un număr limitat de tipuri de fişiere.</p>
<p>Sper să fie de folos cuiva.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Două tehnici de optimizare]]></title>
<link>http://vladr.wordpress.com/2008/05/13/doua-tehnici-de-optimizare/</link>
<pubDate>Tue, 13 May 2008 08:24:35 +0000</pubDate>
<dc:creator>vladr</dc:creator>
<guid>http://vladr.wordpress.com/2008/05/13/doua-tehnici-de-optimizare/</guid>
<description><![CDATA[Am să vorbesc puțin despre optimizări, mai exact optimizări independente de mașină. Domeniul optimiz]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Am să vorbesc puțin despre optimizări, mai exact optimizări independente de mașină. Domeniul optimizărilor este foarte vast și aceste optimizări fac de obicei diferența dintre un compilator bun și unul foarte bun. După cum spuneam într-un post anterior, problema optimizării e NP completă și se utilizează algoritmi care produc cod relativ bun într-un timp rezonabil.</p>
<p>Compilatorul pe care îl dezvolt efectuează doar două astfel de optimizări: constant folding și dead code elimination.</p>
<p>Constant folding presupune înlocuirea expresiilor cu operanzi constanți (expresii ce pot fi calculate în timpul compilării) cu rezultatul lor. De exemplu, expresiei</p>
<p><code>i = (2 + 3) * 5</code></p>
<p>îi corespunde în arborele abstract de sintaxă un nod <em>expresie binară</em> cu operatorul * vând copii (operanzi) un nod <em>expresie binară</em> cu operatorul + și un nod <em>constantă întreagă</em> cu valoarea 5. Nodul <em>expresie binară</em> cu operatorul + are copii două noduri <em>constantă întreagă</em> cu valorile 2, respectiv 3.</p>
<p>Parcurgând arborele în postordine, putem procesa nodurile <em>expresie binară</em> cu regula &#8211; dacă ambii operanzi sunt constante, înlocuiește nodul <em>expresie binară</em> cu nodul <em>constantă întreagă</em> cu valoarea egală cu rezultatul operației. Astfel, ajungând la nodul cu operatorul +, acesta se înlocuiește cu nodul <em>constantă întreagă</em> având valoarea 5 (2 + 3). Din moment ce arborele e parcurs în postordine, nodul cu operația * este procesat ulterior, iar în momentul în care e procesat, și acesta are operanzi două constante astfel că expresia se reduce la un singur nod <em>constantă întreagă</em> cu valoarea 25.</p>
<p><code>i = 25</code></p>
<p>Desigur, operațiile ce se pot evalua la compile-time nu sunt neapărat aritmetice. Pot fi concatenări de string-uri, operații logice, egalități etc.</p>
<p>Pe lângă nodurile <em>expresie binară</em>, compilatorul mai procesează în același mod și nodurile <em>expresie unară</em> (expresii cu un singur operand ca minus unar și negare logică), precum și nodurile <em>typecast</em>. Un nod <em>typecast</em> conține tipul rezultat în urma cast-ului, având un singur copil (operand), ce poate fi o constantă, o expresie etc. Expresiei</p>
<p><code>(int)10.2</code></p>
<p>îi corespunde nodul <em>typecast</em> ce conține tipul int și un copil, nodul <em>constantă rațională</em> 10.2. Aceste două noduri pot fi înlocuite cu nodul <em>constantă întreagă</em> rezultat în urma evaluării cast-ului. Astfel, în urma unei singure parcurgeri a arborelui, toate expresiile cu operanzi constanți sunt înlocuite cu câte o singură constantă. În implementarea mea, parcurgerea arborelui nu se face exclusiv pentru optimizare astfel că, în același pas, se execută și alte evaluări. Desigur, această optimizare se poate face și pe alte tipuri de reprezentări intermediare.</p>
<p>Alte optimizări (pe care nu le-am implementat) ce merg mână în mână cu constant folding sunt constant propagation și utilizarea identităților algebrice. Constant propagation presupune identificarea variabilelor a căror valoare, într-un anumit punct, poate fi determinată la compile time. De exemplu, pentru</p>
<p><code>i = 2</code><br />
<code>j = i + 5</code></p>
<p>putem determina că valoarea lui i este 2 în momentul efectuării adunării, astfel că i poate fi înlocuit cu constanta întreagă 2, constant folding reducând expresia la</p>
<p><code>j = 7</code></p>
<p>eliminând astfel referirea unei variabile și o operație de adunare. Utilizarea identităților algebrice presupune transformarea expresiilor în expresii echivalente ce presupun mai puține operații, de exemplu pentru</p>
<p><code>j = 2 + i + 4</code></p>
<p>unde i <span style="text-decoration:underline;">nu</span> este constant, nodurile din arborele abstract de sinatxă ar fi un nod <em>expresie binară</em> cu operatorul + având copii un nod <em>constantă întreagă</em> 2 și un nod <em>expresie binară</em> cu operatorul + având copii un nod <em>referire la variabilă</em> (i) și un nod <em>constantă întreagă</em> cu valoarea 4. Din moment ce valoarea lui i nu poate fi determinată, constant propagation nu se aplică iar constant folding nu poate identifica nici o expresie având ambii operanzi constanți. Expresia se poate însă rescrie ca</p>
<p><code>j = i + 2 + 4</code></p>
<p>care se poate reduce la</p>
<p><code>j = i + 6</code></p>
<p>O altă optimizare implementată este, după cum ziceam, dead code elimination. Cea mai evidentă optimizare a procesului este eliminarea din arbore a propozițiilor ce apar după un return. Evaluarea se face la nivel de bloc de cod, unde un bloc de cod este mulțimea propozițiilor cuprinse între două acolade, între <code>begin</code> și <code>end</code> etc. Trebuie avut în vedere însă că nu orice instrucțiune return din cod va fi întotdeauna executată. Dacă aceasta se găsește de exemplu în cadrul unui loop while, se poate întâmpla să nu se îndeplinească condiția de execuție a loop-ului niciodată, deci codul de după loop va fi executat chiar dacă există un return. Codul din interiorul loop-ului ce urmează instrucțiunea return poate fi însă eliminat. Astfel, parcurgând arborele în postordine, se marchează ca noduri ce ies din funcție instrucțiunile return, nodurile ce reprezintă blocuri ce conțin o astfel de instrucțiune și nodurile ce reprezintă construcții branching (<code>if-else</code>), unde e întâlnită o instrucțiune return pe ambele branch-uri. Când se procesează părinții acestor noduri, dacă părinții sunt noduri <em>bloc</em> (noduri ce au ca și copii propoziții), se elimină din arbore toate nodurile care urmează după un nod propoziție marcat ca nod ce iese din funcție. De exemplu</p>
<p><code>{</code><br />
<code>    if (a == b)</code><br />
<code>        return a;</code><br />
<code>    else</code><br />
<code>        return b;</code><br />
<code>    a = b + 5;</code><br />
<code>    Console.WriteLine(a);</code><br />
<code>}</code></p>
<p>poate fi echivalat cu</p>
<p><code>{</code><br />
<code>    if (a == b)</code><br />
<code>        return a;</code><br />
<code>    else</code><br />
<code>        return b;</code><br />
<code>}</code></p>
<p>Alte optimizări dead code elimination sunt înlocuirea unei construcții <code>if-else</code>, în cazul în care expresia ce reprezintă condiția poate fi evaluată la compile time, cu ramura if (dacă expresia e evaluată la compile time ca adevărată), cu ramura else (dacă e evaluată ca falsă). În cazul în care expresia e evaluată ca falsă și nu există o ramură else, se elimină din arbore toată construcția. Pentru loop-urile <code>while</code>, unde condiția poate fi evaluată la compile time ca falsă, se elimină din arbore întreg loop-ul. Pentru loop-urile <code>do-while</code>, unde condiția poate fi evaluată la compile time ca falsă, se înlocuiește loop-ul cu corpul său (eliminându-se astfel verificarea condiției) &#8211; deoarce se știe sigur că acesta va fi executat o singură dată.</p>
<p><code>do</code><br />
<code>{</code><br />
<code>    a = a + 1;</code><br />
<code>} while (0);</code></p>
<p>devine</p>
<p><code>a = a + 1;</code></p>
<p>Există multe alte optimizări, cum ar fi common subexpression elimination, loop invariant code motion, function inlining etc. despre care nu voi vorbi aici. Un punct bun de start este <a href="http://www.amazon.com/Compilers-Principles-Techniques-Tools-2nd/dp/0321486811/" target="_blank">Dragon Book</a>.</p>
<p>Îmi cer scuze că am prezentat structurile arborescente în cuvinte și nu cu desene dar în ultimele zile am desenat o mulțime de arbori pentru lucrarea de licență și mi-a ajuns <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Abstract Syntax Trees]]></title>
<link>http://vladr.wordpress.com/2008/03/23/abstract-syntax-trees/</link>
<pubDate>Sun, 23 Mar 2008 09:28:49 +0000</pubDate>
<dc:creator>vladr</dc:creator>
<guid>http://vladr.wordpress.com/2008/03/23/abstract-syntax-trees/</guid>
<description><![CDATA[După ce am scris despre tabelele de simboluri, am să scriu şi despre restul arborelui şi tipurile de]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>După ce am scris despre tabelele de simboluri, am să scriu şi despre restul arborelui şi tipurile de noduri care apar. În primă instanţă, nodurile se împart în două categorii: noduri declarative şi non-declarative. În momentul generării codului, pe baza nodurilor declarative se generează metadata iar pe baza nodurilor non-declarative se generează instrucţiuni IL.</p>
<p>Tabelele de simboluri conţin doar noduri declarative. Nodurile declarative sunt noduri care descriu, de exemplu, o clasă (nume, părinte, interfeţe implementate, vizibilitate etc.) sau o metodă (nume, parametri, tip întors, modificatori gen <em>virtual</em>, <em>static</em> etc.). Dacă pentru generarea codului se foloseşte Reflection.Emit, acestor noduri le corespund obiecte de tipul TypeBuilder, MethodBuilder şi aşa mai departe. Nodurile declarative pot conţine atât alte noduri declarative (un nod care descrie o clasă conţine noduri care descriu membrii clasei) cât şi noduri non-declarative (un nod care descrie o metodă conţine noduri care descriu instrucţiunile din corpul metodei). Tabelele de simboluri rezolvă referinţele căutând în nodurile declarative pe care le conţin.</p>
<p>Nodurile non-declarative reprezintă instrucţiunile din corpurile metodelor. Folosind Reflection.Emit, aceste noduri folosesc un ILGenerator pentru a emite instrucţiuni. Nodurile se împart la rândul lor în două categorii: noduri <em>statement</em> şi noduri <em>expression</em>. Nodurile statement nu întorc valori, cele expression întorc întotdeauna o valoare. De exemplu, dacă în codul pe care vrem să-l compilăm avem</p>
<p><code>x = 100 + 5;</code></p>
<p>partea din AST corespondentă expresiei 100 + 5 este formată din trei noduri de tip expresie. Un nod expresie este de tipul BinaryExpression (expresie cu 2 termeni), care descrie operaţia (adunare) şi conţine două noduri expresie, câte unul pentru fiecare operand. În cazul nostru, operanzii sunt de tip IntLiteral, adică o expresie constantă care întoarce o valoare de tip întreg. La nivelul expresiilor se face type-checking şi se construiesc conversiile implicite. De exemplu, pentru</p>
<p><code>x = 100 + 0.5;</code></p>
<p>Avem o constantă de tip int şi una de tip double. Atunci adăugăm în AST un nod, între nodul BinaryExpression şi nodul IntLiteral, care se ocupă de conversia din int în double. Apare întrebarea de ce să folosim trei noduri pentru o expresie atât de simplă? Păi expresia a fost doar un exemplu pe când tipurile de noduri rămân aceleaşi. Pentru expresia</p>
<p><code>100 + 5 + 10</code></p>
<p>avem nodul BinaryExpression care descrie prima adunare şi cei doi operanzi: IntLiteral (100) şi BinaryExpression (+) care conţine la rândul lui două noduri IntLiteral (5 şi 10). După cum vedem, astfel se pot reprezenta expresii oricât de complexe. Parserul se asigură că arborele va fi construit ţinând cont de prioritatea operatorilor (înmulţiri înainte de adunări, etc.). Exemplu de tip de expresii sunt: literale (constante literale), expresii unare (expresii care au doar un operand: negarea logică, minus unar), expresii binare (expresii cu doi operanzi: adunări, scăderi, comparaţii, <em>şi</em> logic, <em>sau</em> logic etc.), apeluri de metode (metodele care întorc void sunt excepţii, în rest toate metodele întorc o valoare deci sunt considerate expresii), indexeri aplicaţi matricilor şamd.</p>
<p>Pornind de la o clasă abstractă Expression, derivăm toate tipurile de noduri ce descriu expresii.</p>
<p><code>abstract class Expression </code><br />
<code>{</code><br />
<code>    public Type returnType;</code><br />
<code>    public abstract void Evaluate();</code><br />
<code>    public abstract void Emit(ILGenerator ilGen);</code><br />
<code>}</code></p>
<p>Avantajul acestei reprezentări este că fiecare expresie conţine noduri Expression, deci nu este nici o problemă dacă un parametru al unei metode este o constantă, o împărţire sau un apel la o altă metodă, cât timp moşteneşte clasa Expression. Arborele este parcurs de două ori: prima oară se face o evaluare, apelând recursiv metoda Evaluate (aici se verifică referinţele şi compatibilitatea tipurilor), apoi se emite codul, apelând recursiv metoda Emit. Parametrul <em>ilGen</em> este dat de nodul declarativ al metodei, folosind MethodBuilder.GetILGenerator(). Dacă avem de exemplu un tip de nod care descrie o adunare (simplific aici, de obicei acest tip de nod descrie toate operaţiile binare), AddExpression:</p>
<p><code>class AddExpression : Expression</code><br />
<code>{</code><br />
<code>    public Expression leftOperand;</code><br />
<code>    public Expression rightOperand;</code><br />
<code></code><br />
<code>    public override void Evaluate()</code><br />
<code>    {</code><br />
<code>        leftOperand.Evaluate();</code><br />
<code>        rightOperand.Evaluate();</code></p>
<p><code>        if (leftOperand.returnType != rightOperand.returnType)</code><br />
<code>            ...</code><br />
<code>    } </code><br />
<code></code><br />
<code>    public override void Emit(ILGenerator ilGen)</code><br />
<code>    {</code><br />
<code>        leftOperand.Emit(ilGen);</code><br />
<code>        rightOperand.Emit(ilGen);</code><br />
<code>        ilGen.Emit(OpCodes.Add);</code><br />
<code>    }</code><br />
<code>}</code></p>
<p>După cum se vede, operanzii pot fi orice fel de expresie, atât timp cât tipurile returnate sunt compatibile. După cum scriam şi într-un post mai vechi, .NET foloseşte o stivă pentru a evalua expresiile, şi astfel ne asigurăm că stiva este echilibrată. leftOperand.Emit lasă o valoare de tip leftOperand.returnType pe stivă. rightOperand.Emit lasă la rândul lui o valoare de tip rightOperand.returnType. Instrucţiunea <em>add</em> consumă cele două valori şi pune pe stivă rezultatul adunării. Astfel AST-ul poate fi construit incremental, adaugându-se diferite tipuri de noduri pentru diferite tipuri de expresii rând pe rând până când putem evalua orice expresie ce poate să apară în limbajul nostru.</p>
<p>Celălalt tip de noduri, <em>statement</em>, se deosebeşte de expresii prin faptul că nu întoarce o valoare. Statement sunt toate construcţiile limbajului diferite de expresii. De exemplu construcţia condiţională <em>if-else</em> este reprezentată ca</p>
<p><code>if (<em>expression</em>) <em>statement</em> else <em>statement</em></code></p>
<p>Practic, nodul conţine un nod de tip expresie şi două noduri de tip statement. La fel şi construcţia while:</p>
<p><code>while (<em>expression</em>) <em>statement</em></code></p>
<p>De fapt şi blocurile de cod sunt tot statements: un nod de tip statement care conţine o listă de noduri de tip statement. Avân ca părinte comun clasa abstractă Statement, avem din nou avantajul de a putea trata în acelaşi fel o construcţie de tip</p>
<p><code>if (<em>expression</em>)</code><br />
<code>{</code><br />
<code>    <em>statement</em>;</code><br />
<code>    <em>statement</em>;</code><br />
<code>    <em>statement</em>;</code><br />
<code>}</code></p>
<p>şi una de tip</p>
<p><code>if (<em>expression</em>) <em>statement</em>;</code></p>
<p>Practic, orice construcţie a unui limbaj poate fi considerată fie expresie, fie propoziţie. Există câteva excepţii, construcţii ce pot fi atât expresie, cât şi propoziţie. Un apel de funcţie, de exemplu</p>
<p><code>Console.ReadLine();</code></p>
<p>lasă pe stivă o valoare doar că, în unele cazuri, valoarea nu se consumă. Dat fiind tipul de nod CallExpression care apelează o funcţie şi îi întoarce valoarea, soluţia este construirea unui tip de nod CallStatement care conţine un nod CallExpression. În momentul generării codului, CallStatement apelează metoda de generare a codului ce corespunde nodului CallExpression şi mai adaugă instrucţiunea <em>pop</em>, pentru a goli stiva.</p>
<p>Un alt exemplu sunt atribuirle care, la unele limbaje pot fi considerate expresii. În Pascal avem</p>
<p><code>x := 10;</code></p>
<p>statement, care nu poate fi folosit ca expresie. În alte limbaje, precum C sau C#, avem, pe lângă</p>
<p><code>x = 10;</code></p>
<p>ca statement, expresii ca</p>
<p><code>if ((x = Console.ReadLine()) == "")</code></p>
<p>Aceste expresii se tratează în mod diferit deoarece .NET, la nivelul IL, nu se lasă nimic pe stivă după o atribuire. În acest caz, dat fiind tipul de nod AssignementStatement, construim nodul de tip AssignementExpression care adaugă instrucţiunea <em>dup</em> după evaluarea expresiei din dreapta semnului &#8220;=&#8221;. <em>Dup</em> duplică valoarea din vârful stivei astfel încât, după ce este consumată odată de atribuire, valoarea rămâne pe vârful stivei pentru următoarea expresie.</p>
<p>Cam aşa ar trebui să arate un AST. Evaluarea şi generarea codului se fac recursiv, pornind de la tabela de simboluri, evaluând şi generând nodurile declarative, apoi nodurile non-declarative.</p>
<p>Happy compiling!</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Symbol Tables]]></title>
<link>http://vladr.wordpress.com/2008/03/12/symbol-tables/</link>
<pubDate>Wed, 12 Mar 2008 13:54:27 +0000</pubDate>
<dc:creator>vladr</dc:creator>
<guid>http://vladr.wordpress.com/2008/03/12/symbol-tables/</guid>
<description><![CDATA[Abstract Syntax Trees sunt folosiţi pentru reprezentarea intermediară a codului despre care vorbeam ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Abstract Syntax Trees sunt folosiţi pentru reprezentarea intermediară a codului despre care vorbeam în postul trecut. Menţionez că există şi alte modele de reprezentare intermediară şi că tipul de AST pe care îl prezint este cel folosit de mine dar în nici un caz bătut în cuie.</p>
<p>În primul rând, există tabelele de simboluri. Tabelele de simboluri conţin declaraţii de clase, metode, variabile etc. din codul sursă, toate acestea fiind considerate simboluri. O tabelă de simboluri este sociată fiecărui <em>scope</em>. Un scope este o porţiune de program care poate conţine astfel de declaraţii. În C# de exemplu, un namespace are un scope care conţine declaraţii de clase, structuri, interfeţe etc. Clasele au de asemenea un scope care conţine declaraţii de metode, câmpuri etc. Metodele au la rândul lor un scope unde sunt declaraţi parametrii şi variabilele locale. Scope este şi zona cuprinsă între &#8220;{&#8221; şi &#8220;}&#8221;, deoarece o variabilă declarată acolo nu mai poate fi referită după &#8220;}&#8221;. În momentul construirii AST-ului (în timpul parsingului), de fiecare dată când se identifică un scope, se crează o nouă tabelă de simboluri apoi toate declaraţiile din scope-ul respectiv sunt introduse în tabelă. Tabelele conţin şi o referinţă la tabela imediat superioară (tabela asociată unei metode de exemplu are o referinţă spre tabela asociată clasei).</p>
<p>Cum sunt folosite tabelele de simboluri? Pentru a rezolva o referinţă, de exemplu</p>
<p><code>int a = 2;<br />
Console.WriteLine(a);</code></p>
<p>atât pentru apelul Console.WriteLine cât şi pentru variabila a este cerută referinţa de la tabela de simboluri asociată scope-ului (şi metodele şi variabilele sunt simboluri). În exemplul de mai sus, a este rezolvat imediat deoarece există în tabela de simboluri asociată blocului de cod. Ce se întamplă cu apelul, din momente ce Console.WriteLine nu este declarat aici? În caz că tabela nu poate rezolva referinţa, se foloseşte de referinţa spre tabela superioară, cerându-i acesteia să o rezolve. Cererea se propagă în sus până este rezolvată sau se ajunge la un nod care nu are referinţă spre un nod superior (cel mai &#8220;de sus&#8221;). Dacă nici ultimul nod nu conţine simbolul, înseamnă că referinţa este invalidă.</p>
<p>Desigur, nu toate tabelele de simboluri pot conţine toate tipurile de declaraţii, de exemplu tabela de simboluri asociată unui bloc de cod cuprins între &#8220;{&#8221; şi &#8220;}&#8221; nu poate conţine declaraţii de clase dar expune metodele pentru a rezolva o referinţă la o clasă şi trimite pur şi simplu cererea la tabelul superior.</p>
<p>Nodul care stă la bază (care nu mai are referinţă spre o altă tabelă superioară), expune aceleaşi metode de rezolvare a referinţelor dar nu conţine declaraţii. În schimb, acest nod caută simbolurile în assembly-urile externe referite de program. În exemplul de mai sus, Console.WriteLine se află în namespace-ul System din assembly-ul mscorlib.dll. Desigur, compilatorul trebuie să ştie ce assembly-uri externe sunt folosite.</p>
<p>Practic, avem o clasă abstractă care reprezintă o tabelă de simboluri cu metodele pentru a rezolva referinţe:</p>
<p><code>abstract class Scope<br />
{<br />
  public Scope parent; <br />
  public abstract Symbol Solve(Reference reference);<br />
}</code></p>
<p>şi clase derivate din ea care implementează metodele de rezolvare şi conţin declaraţii.</p>
<p><code>class GlobalScope : Scope<br />
{<br />
  private Assembly[] referencedAssemblies;</code><code>  </code></p>
<p><code>  public GlobalScope(Assembly[] referencedAssemblies)<br />
  {<br />
    parent = null;<br />
    this.referencedAssemblies = referencedAssemblies;<br />
  }</code><code>  </code></p>
<p><code>  public override Symbol Solve(Reference reference)<br />
  {<br />
    // Căutare în referinţe<br />
    ...<br />
  }<br />
}</code><code> </code></p>
<p><code></code><code>class SomeScope : Scope<br />
{<br />
  private List&#60;Symbol&#62; symbols;</code><code> </code><code>  </code></p>
<p><code>  public SomeScope(Scope parentScope)<br />
  {<br />
    parent = parentScope;<br />
  }</code><code>  </code></p>
<p><code>  public void AddSymbol(Symbol symbol)<br />
  {<br />
    // Adăugare simbol<br />
    ...<br />
  }</code></p>
<p><code>  </code><code>public override Symbol Solve(Reference reference)<br />
  {<br />
    // Căutare în symbols<br />
    ...<br />
    if (result != null)<br />
      return result;<br />
    else<br />
      return parent.Solve(reference);<br />
  }<br />
} </code></p>
<p>Desigur, codul este schematic, dar cam aşa ar trebui să arate tabelele de simboluri care stau, de fapt, la &#8220;rădăcina&#8221; AST-ului.</p>
<p>Aşa se explică şi vizibilitatea variabilelor, pentru întrebările de la cursul de C gen</p>
<p><code>int a;</code></p>
<p><code></code><code>void test(int a)<br />
{<br />
  printf("%d", a);<br />
}</code></p>
<p>Care a e referit? E referit primul a mergând de jos în sus şi căutând în tabelele de simboluri &#8211; aici e argumentul, deoarece acesta aparţine scope-ului asociat funcţiei pe când variabila globală aparţine scope-ului asociat fişierului.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Compilatoare 101]]></title>
<link>http://vladr.wordpress.com/2008/03/08/compilatoare-101/</link>
<pubDate>Sat, 08 Mar 2008 18:31:26 +0000</pubDate>
<dc:creator>vladr</dc:creator>
<guid>http://vladr.wordpress.com/2008/03/08/compilatoare-101/</guid>
<description><![CDATA[Dacă tot m-am apucat să scriu despre compilatoare, voi scrie câte ceva şi despre lucrurile de bază. ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Dacă tot m-am apucat să scriu despre compilatoare, voi scrie câte ceva şi despre lucrurile de bază. Începând cu începutul, compilatorul este un program care &#8220;traduce&#8221; un limbaj într-un alt limbaj. Asta presupune, în primul rând, analiza unui <em>text</em> (set de comenzi, instrucţiuni etc.) scrise în limbajului sursă şi, în al doilea rând, emiterea <em>textului</em> echivalent în limbajul destinaţie.</p>
<p>De fapt, privit la un nivel înalt, compilatorul este format din două părţi: front-end şi back-end. Front-end-ul se ocupă cu procesarea input-ului, back-end-ul cu emiterea output-ului. Există şi o reprezentare intermediară, independentă de limbajele de intrare şi ieşire, care păstrează doar semantica (înţelesul) input-ului şi din care se generează output-ul.</p>
<p>Concret, front-end-ul analizează input-ul din punct de vedere lexical, sintactic şi semantic. Analiza lexicală presupune descompunerea textului sursă în unităţi atomice numite tokens. Pentru snippet-ul de cod</p>
<p><code>public class Program { }</code></p>
<p>token-ii sunt &#8220;public&#8221;, &#8220;class&#8221;, &#8220;Program&#8221;, &#8220;{&#8221; şi &#8220;}&#8221;. Totuşi, analiza lexicală nu înseamnă doar &#8220;spargerea&#8221; textului după spaţii. De exemplu în textul</p>
<p><code>Console.WriteLine("Hello World!");</code></p>
<p>&#8220;Hello World!&#8221; este un singur token. Treburile se complică dacă luăm un string care conţine în caracterul &#8220;, cum ar fi <code>"Let's start with \"Hello World!\""</code>, care este, de fapt, tot un singur token. În plus, tot analizatorul lexical &#8220;aruncă&#8221; comentariile din cod, care nu necesită o procesare ulterioară. Token-ii aceptaţi sunt definiţi riguros, (de obicei cu ajutorul expressilor regulate). Dacă întâlnim un caracter ilegal în codul sursă, de exemplu §, analizatorul lexical semnalizează o eroare. Analizatorul lexical se mai numeşte şi <em>lexer</em>. De fapt, ne putem gândi la procesul efectuat ca la identificarea tuturor cuvintelor dintr-o propoziţie şi verificarea că aceste cuvinte sunt corecte.</p>
<p>Problema este că, din punct de vedere al lexer-ului, următorul snippet este perfect corect:</p>
<p><code>class } Program public {</code></p>
<p>Acesta poate fi spart în tokens, chiar dacă nu exprimă o construcţie validă a limbajului. Cuvintele există, chiar dacă formează o propoziţie fără subiect şi fără predicat. Aici vine rândul analizatorului sintactic, care se mai numeşte şi <em>parser</em>. Limbajele de intrare au întotdeauna o gramatică, adică diferite construcţii specifice care sunt acceptate, restul fiind identificate ca greşite. Parserul ştie că &#8220;public&#8221; este un modificator de vizibilitate care poate să apară doar înaintea anumitor construcţii (declaraţii de clase, de metode etc.) şi nu oriunde (de exemplu în corpul unei metode). Despre cum funcţionează exact un parser nu voi vorbi aici deoarece sunt foarte multe de spus, destul de reţinut că, după analiza sintactică, ajungem la reprezentarea intermediară. Construcţia</p>
<p><code>public class Program { }</code></p>
<p>va fi reprezentată intern ca &#8220;<em>Declaraţie de clasă, cu numele Program, vizibilitate publică şi fără conţinut</em>&#8220;, deci se păstrează sensul, dar token-ii nu mai sunt relevanţi. &#8220;{&#8221; de exemplu ajută parserul să înţeleagă unde începe conţinutul clasei dar nu are nici un înţeles semantic. Ultima analiză efectuată este cea semantică. De exemplu construcţia</p>
<p><code>public class A : A { }</code></p>
<p>este formulată corect din punct de vedere sintactic, doar că nu are sens din punct de vedere logic. O analogie ar fi o propoziţie formulată corect, cu subiect şi predicat, dar care nu are sens. Analiza semantică asigură că input-ul este bun şi din acest punct de vedere, deci se poate traduce în limbajul de output. Aici intră o mulţime de verificări, de exemplu dacă se execută operaţii doar între tipuri compatibile de date, dacă funcţiile întorc întotdeauna un rezultat, dacă nu se folosesc variabile înainte de a fi iniţializate etc. După analiza semantică avem o reprezentare internă a input-ului validat şi aici se încheie treaba front-end-ului.</p>
<p>Back-end-ul preia forma internă şi o transformă în limbajul destinaţie. Mai mult, optimizează codul rezultat. Optimizările sunt de două feluri &#8211; independente de limbaj şi dependente de limbaj. Un exemplu de optimizare ar fi constant folding. De exemplu expresia</p>
<p><code>a = 2 * 3.14 * r</code></p>
<p>care presupune două operaţii de înmulţire poate fi transformată în</p>
<p><code>a = 6.28 * r</code></p>
<p>care presupune o singură operaţie de înmulţire. Compilatorul determină care expresii pot fi calculate static (adică nu depind de variabile a căror valoare este necunoscută în momentul respectiv) şi le înlocuieşte cu rezultatul expresiei. Un alt exemplu ar fi înlocuirea subexpressilor comune. De exemplu</p>
<p><code>c = a + b * x<br />
d = a + b * y</code></p>
<p>se poate înlocui cu</p>
<p><code>t = a + b<br />
c = t * x<br />
d = t * y</code></p>
<p>reducând din nou numărul de operaţii necesare. Problema optimizării este NP-Completă, adică nu se poate dezvolta un algoritm (deocamdată <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ) care să garanteze că pentru orice input, output-ul rezultat este optim. După efectuarea acestor optimizări, se emite codul şi se aplică optimizările dependente de limbaj. Un exemplu, în CIL, ar fi instrucţiunea</p>
<p><code>ldc_i4 0</code></p>
<p><em>ldc_i4</em> pune pe stivă întregul (pe 32 de biţi) specificat. Instrucţiunea în sine are 8 biţi plus întregul specificat 32 de biţi (chiar dacă este 0), deci 40 de biţi. Aceasta poate fi înlocuită cu</p>
<p><code>ldc_i4_0</code></p>
<p>instrucţiune care pune întregul 0 pe stivă, aceasta din urmă ocupând doar 8 biţi. Într-adevăr, pe platforma .NET nu sunt necesare multe optimizări dependente de cod deoarece runtime-ul are grijă de asta în momentul rulării.</p>
<p>Aceştia sunt paşii făcuţi de un compilator pentru generarea codului şi, de fiecare dată când apelaţi &#8220;build&#8221; sau &#8220;run&#8221;, codul sursă trece prin toate aceste transformări până se transformă în executabil.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[CLR, Metadata și IL]]></title>
<link>http://vladr.wordpress.com/2008/03/06/clr-metadata-%c8%99i-il/</link>
<pubDate>Thu, 06 Mar 2008 09:05:39 +0000</pubDate>
<dc:creator>vladr</dc:creator>
<guid>http://vladr.wordpress.com/2008/03/06/clr-metadata-%c8%99i-il/</guid>
<description><![CDATA[Am să încerc să explic, pe scurt, cum funcționează CLR-ul (Common Language Runtime). Se știe că un a]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Am să încerc să explic, pe scurt, cum funcționează CLR-ul (Common Language Runtime). Se știe că un assembly .NET (executabil sau bibliotecă) conține metadata și instrucțiuni IL &#8211; eu cel puțin am auzit asta la toate prezentările de .NET Framework la care am asistat &#8211; doar că nu se prea știe cu ce se mănâncă cele două.</p>
<p>Metadata e strâns legată de partea declarativă a aplicațiilor. Orice tip, metodă, variabilă etc. are o intrare în tabelul de metadata. Acestea pot fi descoperite folosind Reflection. De exemplu, clasa MethodInfo, reprezintă metadata asociată unei metode. Pentru a vedea metodele unei clase, de exemplu System.Console, folosind Reflection, avem:<br />
<code><br />
using System;<br />
using System.Reflection;<br />
class Program<br />
{<br />
  public static void Main()<br />
  {<br />
    Type consoleType = Type.GetType("System.Console");</code></p>
<p><code>    </code><code>foreach (MethodInfo methodInfo in</code><code> ConsoleType.GetMethods())<br />
    {<br />
      Console.WriteLine(methodInfo.Name);<br />
    }<br />
  }<br />
}</code></p>
<p><code></code>Metadata pentru o metodă are informații despre nume, atribute, parametri, return type și multe altele.</p>
<p>IL &#8211; Intermediate Language &#8211; sunt instrucțiunile executate de runtime. Setul de instrucțiuni este destul de mic (în jur de 200 de instrucțiuni) și lucrează cu o stivă. Orice instrucțiune consumă un număr de elemente de pe stivă și adaugă un număr de elemente pe stivă. Această caracteristică se numește delta-stack. În cazul în care un program încearcă să consume de pe stivă mai multe elemente decât există, sau lasă pe stivă elemente când aceasta ar trebui să fie goală, CLR-ul termină aplicația cu excepția InvalidProgramException. Unele instrucțiuni așteaptă și un metadata token. Un apel de funcție, de exemplu, așteaptă, după instrucțiunea <em>call</em>, token-ul funcției. Token-ul este de fapt adresa din tabela de metadata a funcției. Compilat, codul devine bytecode &#8211; instrucțiunile sunt reprezentate de intregi pe 8 sau 16 biți.</p>
<p>Să luăm de exemplu următoarea linie de cod C#:<br />
<code>Console.WriteLine("Hello World");</code></p>
<p>Tradus în limbaj de asamblare, linia arată astfel:<br />
<code>ldstr "Hello World"<br />
call void [mscorlib]System.Console::WriteLine(string)</code></p>
<p>ldstr pune pe stivă string-ul ”Hello World”. call folosește token-ul pentru a ști ce funcție să apeleze &#8211; în cazul nostru WriteLine care așteaptă un string. WriteLine consumă string-ul de pe stivă și, la ieșire, lasă stiva goală.</p>
<p>Dacă vrem să adăugăm și un ReadLine după, avem<br />
<code>Console.WriteLine("Hello World");<br />
Console.ReadLine();</code></p>
<p>În limbaj de asamblare, putem încerca:<br />
<code>ldstr "Hello World"<br />
call void [mscorlib]System.Console::WriteLine(string)<br />
call string [mscorlib]System.Console::ReadLine()</code></p>
<p>Dacă rulăm codul de mai sus ne vom trezi cu un InvalidProgramException. De ce? Păi ReadLine pune pe stivă un string, chiar dacă noi îl folosim doar ca să așteptăm un ENTER. String-ul respectiv rămâne acolo și dezechilibrează stiva. Ce trebuie făcut în astfel de situații? Folosim instrucțiunea <em>pop</em>. Pop ”aruncă” ultimul element de pe stivă.<br />
<code>ldstr "Hello World"<br />
call void [mscorlib]System.Console::WriteLine(string)<br />
call string [mscorlib]System.Console::ReadLine()<br />
pop</code></p>
<p>O carte foarte bună despre acest subiect este <a target="_blank" href="http://www.amazon.com/Expert-NET-2-0-IL-Assembler/dp/1590596463">Expert .NET 2.0 IL Assembler</a> (eu lucrez cu .NET 2.0, nu am trecut încă la 3.5 <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ). E clar că oricine are de gând să scrie un compilator având ca target .NET trebuie să înțeleagă ce este metadata, care sunt instrucțiunile IL și la ce să se aștepte de la ele.</p>
<p>O altă unealtă grozavă este <em>ildasm</em>, care vine cu .NET Framework. ildasm înseamnă IL Disassembler, cu care se pot dezasambla diferite programe și se pot vedea instrucțiunile generate de compilatoare.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Signature matching]]></title>
<link>http://vladr.wordpress.com/2008/03/05/signature-matching/</link>
<pubDate>Wed, 05 Mar 2008 10:48:16 +0000</pubDate>
<dc:creator>vladr</dc:creator>
<guid>http://vladr.wordpress.com/2008/03/05/signature-matching/</guid>
<description><![CDATA[O problemă interesantă de care m-am lovit lucrând la compilator e signature matching. Mai exact, det]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>O problemă interesantă de care m-am lovit lucrând la compilator e signature matching. Mai exact, determinarea funcției care va fi apelată de o expresie tip function call. Ce înseamnă asta? Păi în .NET avem method overloading, deci același nume de funcție poate, pentru diferiți parametri, să facă diferite lucruri. Funcții extrem de overloaded sunt, de exemplu, Console.WriteLine (19 funcții în una). Când eu compilez System.Console.WriteLine(”Hello World!”), trebuie să știu să aleg din cele 19 funcții pe cea care ia ca parametru un string. Când vorbesc de signature matching mă refer la a decide care dintre n funcții cu același nume trebuie apelată, nu la a găsi funcțiile cu numele respectiv.</p>
<p>Primul lucru pe care îl putem face este să egalăm tipul parametrilor pe care îi pasăm funcției față de tipul așteptat &#8211; adică e pasat (string), se așteaptă (string) &#8211; avem match. Acesta este exact match &#8211; odată întâlnit, nu mai trebuie testate celelalte funcții. Totuși, un algoritm de signature matching trebuie să țină cont și de: typecast implicit, upcast, typecast implicit definit de programator.</p>
<p>Typecast implicit: avem funcția (double), îi facem un apel (20) &#8211; unde 20 este integer literal, adică int. Deci trebuie să decidem dacă apelul (int) e OK pentru funcția (double). Tipul int poate fi convertit implicit în double, deci apelul e corect, trebuie doar adăugat typecastul (compilatorul adaugă întotdeauna typecast-urile implicite). Deci vom transforma (20) în ((double)20). Dacă găsim și o semnătură (int), desigur o vom considera mai bună, dar dacă nu, merge și (double).</p>
<p>Upcast: avem funcția (object), îi facem un apel (”Hello world”) &#8211; adică (string). Din moment ce string <em>este</em> un object, apelul este corect. Mai mult, dacă avem A derivat din object și B derivat din A, facem un apel (B) și găsim semnăturile (object) și (A), trebuie să luăm funcția cu semnătura (A) - adică cea mai de jos clasă din ierarhie.</p>
<p>Typecast implicit definit de utilizator: în multe limbaje, se pot defini typecast-uri implicite. De exemplu în C#, pentru clasa mea A, pot defini un typecast implicit în int astfel:<br />
<code>class A<br />
{<br />
  public static implicit operator int(A instance)<br />
  {<br />
    return 0;<br />
  }<br />
}</code></p>
<p>Metoda de mai sus transformă implicit un obiect de tip A în int (în zero, dar asta e neesențial). Deci pentru un apel (A), dacă găsim o funcție (int), există o conversie implicită &#8211; ((int)A).</p>
<p>Problema ce poate să apară este apelul ambiguu, adică: nu se poate decide, pentru un apel (int, int), între semnăturile (int, double) și (double, int). La fel și (int, int, int), pentru (int, double, double) și (double, int, int). De observat că, deși a doua funcție este mai apropiată de apel, necesitând transformarea unui singur parametru, apelul rămâne ambiguu. De fapt regula este următoarea:</p>
<p>Pentru fiecare parametru, se verifică transformările în ordinea în care le-am prezentat mai sus (typecast implicit, upcast, typecast implicit definit de utilizator). </p>
<p>O funcție este preferată față de alte funcții dacă, pentru fiecare parametru, necesită cel mult același număr de transformări ca celelalte funcții și are cel puțin un parametru care necesită mai puține transformări.</p>
<p>Tocmai de aceea nu se poate decide între (int, double, double) și (double, int, int) pentru apelul (int, int, int). Deși a doua funcție necesită mai puține transformări (de fapt nu necesită transformări) pentru parametrii int, necesită o transformare pentru primul parametru, pe care funcția (int, double, double) nu îl necesită.</p>
<p> Cam asta ar fi filozofia din spatele signature matching-ului.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[CIL - Compiler construction]]></title>
<link>http://rogeralsing.com/2008/03/03/cil-compiler-construction/</link>
<pubDate>Mon, 03 Mar 2008 18:10:53 +0000</pubDate>
<dc:creator>Roger Alsing</dc:creator>
<guid>http://rogeralsing.com/2008/03/03/cil-compiler-construction/</guid>
<description><![CDATA[I&#8217;ve created a little sample on how to make your own .NET compiler. The compiler uses Gold par]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I&#8217;ve created a little sample on how to make your own .NET compiler.<br />
The compiler uses Gold parser for parsing and Reflection.Emit to generate the compiled .exe file.</p>
<p>Initially I intended to make a sample on how to use Gold parser to parse and then compile Linq expressions, thus the name GoldLinq, however, Linq have now been replaced with Reflection.Emit.</p>
<p><strong>Links:<br />
</strong>My compiler source: <a href="http://www.puzzleframework.com/Roger/GoldLinq.zip">http://www.puzzleframework.com/Roger/GoldLinq.zip</a><br />
(C# VS.NET 2008 solution)</p>
<p>Gold parser: <a href="http://www.devincook.com/goldparser/">http://www.devincook.com/goldparser/</a><br />
Grammar: <a href="http://www.devincook.com/goldparser/grammars/index.htm">http://www.devincook.com/goldparser/grammars/index.htm</a></p>
<p><strong>How it works:</strong></p>
<ul>
<li>
<div>Gold parser &#8211; Calitha engine is used to parse the source code into a parse tree</div>
</li>
<li>
<div>The parse tree is transformed into a typed AST</div>
</li>
<li>
<div>The AST is verified using visitor pattern, the verifier handles type inferrence and auto casts.</div>
</li>
<li>
<div>The AST is optimized using visitor pattern, the optimizer replaces constant expressions and statements.</div>
</li>
<li>
<div>The AST is compiled into CIL/MSIL using visitor pattern.</div>
</li>
<li>
<div>If successful, the compiler will generate a file called &#8220;output.exe&#8221; in the same folder as the compiler</div>
</li>
</ul>
<p><strong>Samples:</strong></p>
<p>Hello world </p>
<pre>display 'Hello World!'</pre>
<p> Have a nice day:</p>
<pre>Display 'What is your name?' Read Name
Display 'Hello, ' &#38; Name &#38; '. Have a nice day!'</pre>
<p>Blastoff: </p>
<pre>assign n = 10
while n &#62;= 1 do
    display n
    assign n = n - 1
end
display 'Blast off!'</pre>
<p>Miles and kilometers: </p>
<pre>Display
'Do you want to convert 1) Miles to Kilometers or 2) Kilometers to Miles?'
Read Choice        

if Choice == 1 then
    Display 'Please enter the number of miles' Read Miles
    Display Miles &#38; ' Miles = ' &#38; (Miles * 1.609)  &#38; ' Kilometers'
else
    Display 'Please enter the number of kilometers' Read Kilometers
    Display Kilometers &#38; ' Kilometers = ' &#38; (Kilometers / 1.609)  &#38; ' Miles'
end</pre>
<p>Secret number: </p>
<pre>Assign SecretNumber = 64 

Display 'Please guess the secret number'
Read Guess          

While Guess &#60;&#62; SecretNumber Do
    If Guess &#60; SecretNumber Then
        Display 'Your guess was too LOW. Try again.' Read Guess
    End    
If Guess &#62; SecretNumber Then
        Display 'Your guess was too HIGH. Try again.' Read Guess
    End
End     

Display 'Correct!'</pre>
<p><strong>How to compile the samples:</strong></p>
<p>First you need a source file to compile, just create a normal textfile and paste one of the samples above into it.<br />
Once you have the code file you can compile it using the compiler:</p>
<pre>c:whatever\bin\debug&#62; GoldSample.exe mysource.txt</pre>
<p>When the compiler is done, you can start the compiled application with:</p>
<pre>c:\whatever\bin\debug&#62; output.exe</pre>
<p>The code is somewhat too big to cover in a blog post, so if you have any questions feel free to ask in the comment section.</p>
<p>//Roger</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Compiler Construction]]></title>
<link>http://netjistinfotech.wordpress.com/2007/11/29/compiler-construction/</link>
<pubDate>Thu, 29 Nov 2007 15:16:51 +0000</pubDate>
<dc:creator>editornetjist</dc:creator>
<guid>http://netjistinfotech.wordpress.com/2007/11/29/compiler-construction/</guid>
<description><![CDATA[You are invited to post your queries and articles related to the field. However, certain topics are ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>You are invited to post your queries and articles related to the field. However, certain topics are being marked here for just reference :</p>
<ul>
<li>automated syntax error correction</li>
<li>code generation</li>
<li>object programs</li>
<li>source programs</li>
</ul>
<p><a href="http://www.netjist.com" target="_blank">www.netjist.com</a></p>
</div>]]></content:encoded>
</item>

</channel>
</rss>
