Example #1
0
        void readNumber(Token.Pos tp, char first)
        {
            var seenDot = first == '.';

            while (pos < len)
            {
                var c = code[pos];
                if (c >= '0' && c <= '9')
                {
                    pos++;
                }
                else if (c == '.')
                {
                    if (seenDot)
                    {
                        break;
                    }
                    seenDot = true;
                    pos++;
                }
                else
                {
                    break;
                }
            }
            add(new Token.Number(tp, slice(tp.pos, pos)));
        }
Example #2
0
 public For(Token.Pos tp, Node init, Node cond, Node post, Node loop) : base(tp)
 {
     this.init = init;
     this.cond = cond;
     this.post = post;
     this.loop = loop;
 }
Example #3
0
 /// <summary>
 /// Reading `<` or `<=` accordingly
 /// </summary>
 void readCmpOp(Token.Pos tp, Token.BinOpType opEq, Token.BinOpType op)
 {
     if (pos < len && code[pos] == '=')
     {
         pos++;
         add(new Token.BinOp(tp, opEq));
     }
     else
     {
         add(new Token.BinOp(tp, op));
     }
 }
Example #4
0
 public Source(string _name, string _code)
 {
     name  = _name;
     code  = _code;
     start = new Token.Pos(this, 0, 0, 0);
     {
         var row          = 0;
         int np           = 0;
         var lastRowStart = 0;
         while ((np = _code.IndexOf('\n', np)) != -1)
         {
             lastRowStart = np++;
             row++;
         }
         end = new Token.Pos(this, _code.Length, row, _code.Length - lastRowStart);
     };
 }
Example #5
0
 public If(Token.Pos tp, Node @if, Node then, Node @else) : base(tp)
 {
     this.@if   = @if;
     this.then  = then;
     this.@else = @else;
 }
Example #6
0
 public UnOp(Token.Pos tp, Token.UnOpType type, Node node) : base(tp)
 {
     this.type = type;
     this.node = node;
 }
Example #7
0
 public Call(Token.Pos tp, Node node) : base(tp)
 {
     this.node = node;
 }
Example #8
0
 public Return(Token.Pos tp, Node node) : base(tp)
 {
     this.node = node;
 }
Example #9
0
 public ArrayLiteral(Token.Pos tp) : base(tp)
 {
 }
Example #10
0
 public ArrayAccess(Token.Pos tp, Node node, Node index) : base(tp)
 {
     this.node = node; this.index = index;
 }
Example #11
0
 public Var(Token.Pos tp, string name, Node value) : base(tp)
 {
     this.name  = name;
     this.value = value;
 }
Example #12
0
        public List <Token> parse(Source _source)
        {
            tokens = new List <Token>();
            source = _source;
            pos    = 0;
            len    = _source.code.Length;
            code   = _source.code + "\x1B";
            //
            var rowStart = 0;
            var row      = 0;

            while (pos < len)
            {
                var start = pos;
                var tp    = new Token.Pos(_source, pos, row, pos - rowStart);
                switch (code[pos++])
                {
                case ' ':
                case '\t':
                case '\r': break;

                case '\n':
                    row++;
                    rowStart = pos;
                    break;

                case '(': add(new Token.ParOpen(tp)); break;

                case ')': add(new Token.ParClose(tp)); break;

                case '[': add(new Token.SquareOpen(tp)); break;

                case ']': add(new Token.SquareClose(tp)); break;

                case '{': add(new Token.CurlyOpen(tp)); break;

                case '}': add(new Token.CurlyClose(tp)); break;

                case ';': add(new Token.Semico(tp)); break;

                case ',': add(new Token.Comma(tp)); break;

                case '+': readBinOp(tp, Token.BinOpType.Add); break;

                case '-': readBinOp(tp, Token.BinOpType.Subtract); break;

                case '%': readBinOp(tp, Token.BinOpType.Modulo); break;

                case '~': add(new Token.UnOp(tp, Token.UnOpType.BitNot)); break;

                case '*':
                    if (code[pos] == '*')
                    {
                        pos++;
                        readBinOp(tp, Token.BinOpType.Power);
                    }
                    else
                    {
                        readBinOp(tp, Token.BinOpType.Multiply);
                    }
                    break;

                case '/':
                    if (code[pos] == '*')
                    {
                        pos += 1;
                        while (pos < len - 1)
                        {
                            if (code[pos] == '*' && code[pos + 1] == '/')
                            {
                                pos += 2;
                                break;
                            }
                            else
                            {
                                pos += 1;
                            }
                        }
                    }
                    else if (code[pos] == '/')                                 // comment!
                    {
                        while (pos < len)
                        {
                            if (code[pos] == '\n')
                            {
                                break;
                            }
                            pos += 1;
                        }
                    }
                    else
                    {
                        readBinOp(tp, Token.BinOpType.Divide);
                    }
                    break;

                case '<':
                    if (code[pos] == '<')
                    {
                        pos++;
                        readBinOp(tp, Token.BinOpType.BitShiftLeft);
                    }
                    else
                    {
                        readCmpOp(tp, Token.BinOpType.LessThanOrEqual, Token.BinOpType.LessThan);
                    }
                    break;

                case '>':
                    if (code[pos] == '>')
                    {
                        pos++;
                        readBinOp(tp, Token.BinOpType.BitShiftRight);
                    }
                    else
                    {
                        readCmpOp(tp, Token.BinOpType.GreaterThanOrEqual, Token.BinOpType.GreaterThan);
                    }
                    break;

                case '=':
                    if (code[pos] == '=')
                    {
                        pos++;
                        add(new Token.BinOp(tp, Token.BinOpType.Equals));
                    }
                    else
                    {
                        add(new Token.SetOp(tp, Token.BinOpType.Set));
                    }
                    break;

                case '!':
                    if (code[pos] == '=')
                    {
                        pos++;
                        add(new Token.BinOp(tp, Token.BinOpType.NotEquals));
                    }
                    else
                    {
                        add(new Token.UnOp(tp, Token.UnOpType.Not));
                    }
                    break;

                case '"':                         // a string! with escape characters!
                    var sb       = new StringBuilder();
                    var strFound = false;
                    while (pos < len)
                    {
                        var c = code[pos++];
                        if (c == '"')
                        {
                            strFound = true;
                            add(new Token.CString(tp, sb.ToString()));
                            break;
                        }
                        else if (c == '\\')
                        {
                            switch (code[pos++])
                            {
                            case 'r': sb.Append('\r'); break;

                            case 'n': sb.Append('\n'); break;

                            case 't': sb.Append('\t'); break;

                            case 'b': sb.Append('\b'); break;

                            case '"': sb.Append('"'); break;

                            case 'x':
                                var hc = (char)int.Parse(code.Substring(pos, 2), System.Globalization.NumberStyles.HexNumber);
                                sb.Append(hc);
                                pos += 2;
                                break;

                            case '\\': sb.Append('\\'); break;

                            case var c1: sb.Append(c1); break;
                            }
                        }
                        else
                        {
                            sb.Append(c);
                        }
                    }
                    if (!strFound)
                    {
                        throw new Exception($"Unclosed string starting at ${tp}");
                    }
                    break;

                case '.':                         // . or .1
                    if (code[pos] >= '0' && code[pos] <= '9')
                    {
                        readNumber(tp, '.');
                    }
                    else
                    {
                        add(new Token.Period(tp));
                    }
                    break;

                case var c when c == '0' && code[pos] == 'x':                         // hex literal!
                    pos++;
                    while (pos < len)
                    {
                        c = code[pos];
                        if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F')
                        {
                            pos++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    add(new Token.Number(tp, slice(start, pos)));
                    break;

                case var c when c >= '0' && c <= '9':                         // decimal!
                    readNumber(tp, c);
                    break;

                case var c when c == '_' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z':                         // words!
                    while (pos < len)
                    {
                        c = code[pos];
                        if (c == '_' || c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
                        {
                            pos++;
                        }
                        else
                        {
                            break;
                        }
                    }
                    //
                    var word = slice(start, pos);
                    if (keywordMap.TryGetValue(word, out var fn))
                    {
                        add(fn(tp, word));
                    }
                    else
                    {
                        add(new Token.Ident(tp, word));
                    }
                    break;

                case var c: throw new Exception($"Unknown character `{c}`");
                }
            }
            add(new Token.EOF(_source.end));
            return(tokens);
        }
Example #13
0
 public While(Token.Pos tp, Node cond, Node loop) : base(tp)
 {
     this.cond = cond;
     this.loop = loop;
 }
Example #14
0
 public Break(Token.Pos tp) : base(tp)
 {
 }
Example #15
0
 public Field(Token.Pos tp, Node node, string field) : base(tp)
 {
     this.field = field;
     this.node  = node;
 }
Example #16
0
 public Local(Token.Pos tp, string text) : base(tp, text)
 {
 }
Example #17
0
 public Ident(Token.Pos tp, string text) : base(tp, text)
 {
 }
Example #18
0
 public CString(Token.Pos tp, string text) : base(tp, text)
 {
 }
Example #19
0
 public Number(Token.Pos tp, string text) : base(tp, text)
 {
 }
Example #20
0
 public DoWhile(Token.Pos tp, Node loop, Node cond) : base(tp)
 {
     this.loop = loop;
     this.cond = cond;
 }
Example #21
0
 public Node(Token.Pos tp)
 {
     pos = tp;
 }
Example #22
0
 public Continue(Token.Pos tp) : base(tp)
 {
 }
Example #23
0
 public SetOp(Token.Pos tp, Token.BinOpType type, Node left, Node right) : base(tp)
 {
     this.type  = type;
     this.left  = left;
     this.right = right;
 }
Example #24
0
 public Literal(Token.Pos tp, string value) : base(tp)
 {
     this.value = value;
 }
Example #25
0
 public Block(Token.Pos tp) : base(tp)
 {
 }