Beispiel #1
0
 public Parser(Lexer lex)
 {
     if (lex == null) throw new ArgumentNullException("lex");
     this.lex = lex;
     this.tok = null;
 }
Beispiel #2
0
 public ListExpr(Token start, Token end, params SExpr[] items)
     : base(SExprKind.List, start, end)
 {
     Items = items;
 }
Beispiel #3
0
 public NullExpr(Token token)
     : base(SExprKind.Null, token, token)
 {
     if (token.Type != TokenType.Null) throw new ArgumentException("token must be of type Null for a NullExpr");
 }
Beispiel #4
0
 public InvocationExpr(Token start, Token end, IdentifierExpr identifier, params SExpr[] parameters)
     : base(SExprKind.Invocation, start, end)
 {
     Identifier = identifier;
     Parameters = parameters;
 }
Beispiel #5
0
        public Token Next()
        {
            // Only read the first char on the first call to Next():
            if (c == -2) c = Read();

            do
            {
                // EOF:
                if (c == -1 || c == 0) return new Token(pos, TokenType.EOF, null);

                // Skip whitespace (commas are whitespace too):
                if (c == ' ' || c == '\t' || c == ',' || c == '\n' || c == '\r')
                {
                    c = Read();
                    continue;
                }

                // TODO(jsd): comments!

                // Curlies and parens are equivalent in this LISP:
                if (c == (int)'(' || c == (int)'{')
                {
                    var tok = new Token(lpos, TokenType.ParenOpen, ((char)c).ToString());
                    c = Read();
                    return tok;
                }
                else if (c == (int)')' || c == (int)'}')
                {
                    var tok = new Token(lpos, TokenType.ParenClose, ((char)c).ToString());
                    c = Read();
                    return tok;
                }
                // Square brackets denote plain lists of data, not to be eval'd:
                else if (c == (int)'[')
                {
                    var tok = new Token(lpos, TokenType.BracketOpen, ((char)c).ToString());
                    c = Read();
                    return tok;
                }
                else if (c == (int)']')
                {
                    var tok = new Token(lpos, TokenType.BracketClose, ((char)c).ToString());
                    c = Read();
                    return tok;
                }
                // Punctuation:
                else if (c == (int)'~')
                {
                    var tok = new Token(lpos, TokenType.Quote, ((char)c).ToString());
                    c = Read();
                    return tok;
                }
                else if (c == '.')
                {
                    var tok = new Token(lpos, TokenType.Dot, ((char)c).ToString());
                    c = Read();
                    return tok;
                }
                else if (c == '/')
                {
                    var tok = new Token(lpos, TokenType.Slash, ((char)c).ToString());
                    c = Read();
                    return tok;
                }
                // Keywords or unquoted strings:
                else if (Char.IsLetter((char)c) || c == '_')
                {
                    // Parse an unquoted string ([A-Za-z_][A-Za-z0-9\-_]*):
                    int spos = lpos;

                    var sb = new StringBuilder(10);
                    do
                    {
                        sb.Append((char)c);
                        c = Read();
                        if (c == -1) break;
                    } while (Char.IsLetterOrDigit((char)c) || c == '-' || c == '_');

                    var ident = sb.ToString();
                    if (String.Equals(ident, "true"))
                        return new Token(spos, TokenType.Boolean, ident);
                    else if (String.Equals(ident, "false"))
                        return new Token(spos, TokenType.Boolean, ident);
                    else if (String.Equals(ident, "null"))
                        return new Token(spos, TokenType.Null, ident);
                    else
                        return new Token(spos, TokenType.Identifier, sb.ToString());
                }
                // Quoted string literals:
                else if (c == (int)'\'')
                {
                    int spos = lpos;
                    var sb = new StringBuilder(10);

                    do
                    {
                        c = Read();
                        if (c == -1) return new Token(pos, TokenType.Error, "Unexpected end");
                        else if (c == '\'') break;
                        else if (c == '\\')
                        {
                            c = Read();
                            if (c == -1) return new Token(pos, TokenType.Error, "Unexpected end");
                            else if (c == '\'') sb.Append('\'');
                            else if (c == '\\') sb.Append('\\');
                            else if (c == 'n') sb.Append('\n');
                            else if (c == 'r') sb.Append('\r');
                            else if (c == 't') sb.Append('\t');
                            else return new Token(pos, TokenType.Error, "Unknown backslash escape character '{0}'".F((char)c));
                        }
                        else sb.Append((char)c);
                    } while (true);

                    c = Read();
                    return new Token(spos, TokenType.String, sb.ToString());
                }
                // Raw string literals:
                else if (c == (int)'`')
                {
                    int spos = lpos;
                    var sb = new StringBuilder(10);

                    do
                    {
                        c = Read();
                        if (c == -1) return new Token(pos, TokenType.Error, "Unexpected end");
                        // TODO(jsd): Any escape sequences?
                        else if (c == '`') break;
                        else sb.Append((char)c);
                    } while (true);

                    c = Read();
                    return new Token(spos, TokenType.String, sb.ToString());
                }
                // Numerics:
                else if (Char.IsDigit((char)c) || c == '-')
                {
                    // Simple/stupid numeric parser [0-9]+(\.[0-9]+)?:
                    int spos = lpos;
                    bool hasDecimal = false;

                    var sb = new StringBuilder(10);
                    do
                    {
                        sb.Append((char)c);

                        c = Read();
                        if (c == -1) break;
                        if (c == '.')
                            hasDecimal = true;
                    } while (Char.IsDigit((char)c) || c == '.');

                    // Determine the type of number by suffix or presence of decimal point:
                    var type = TokenType.Integer;
                    if (c == 'd')
                    {
                        c = Read();
                        type = TokenType.Double;
                    }
                    else if (c == 'f')
                    {
                        c = Read();
                        type = TokenType.Float;
                    }
                    else if (hasDecimal)
                    {
                        // Default to decimal type if have a decimal point:
                        type = TokenType.Decimal;
                    }

                    return new Token(spos, type, sb.ToString());
                }
                else
                {
                    return new Token(lpos, TokenType.Error, "Unexpected character '{0}'".F((char)c));
                }
            } while (c != -1);

            return new Token(pos, TokenType.EOF, null);
        }
Beispiel #6
0
 public ParserError(Token where, string message)
     : base(SExprKind.Error, where, where)
 {
     Message = message;
 }
Beispiel #7
0
 public ScopedIdentifierExpr(Token ident)
     : base(SExprKind.ScopedIdentifier, ident, ident)
 {
     Name = ident;
 }
Beispiel #8
0
 public FloatExpr(Token token, float value)
     : base(SExprKind.Float, token, token)
 {
     if (token.Type != TokenType.Float) throw new ArgumentException("token must be of type Float for a FloatExpr");
     Value = value;
 }
Beispiel #9
0
 protected IdentifierExpr(SExprKind kind, Token start, Token end)
     : base(kind, start, end)
 {
 }
Beispiel #10
0
 public StringExpr(Token token)
     : base(SExprKind.String, token, token)
 {
     if (token.Type != TokenType.String) throw new ArgumentException("token must be of type String for a StringExpr");
     Value = token.Text;
 }
Beispiel #11
0
 public DoubleExpr(Token token, double value)
     : base(SExprKind.Double, token, token)
 {
     if (token.Type != TokenType.Double) throw new ArgumentException("token must be of type Double for a DoubleExpr");
     Value = value;
 }
Beispiel #12
0
 public StaticMemberIdentifierExpr(Token[] @typeName, Token ident)
     : base(SExprKind.StaticMemberIdentifier, @typeName[0], ident)
 {
     TypeName = @typeName;
     Name = ident;
 }
Beispiel #13
0
 public DecimalExpr(Token token, decimal value)
     : base(SExprKind.Decimal, token, token)
 {
     if (token.Type != TokenType.Decimal) throw new ArgumentException("token must be of type Decimal for a DecimalExpr");
     Value = value;
 }
Beispiel #14
0
 protected SExpr(SExprKind kind, Token start, Token end)
 {
     Kind = kind;
     StartToken = start;
     EndToken = end;
 }
Beispiel #15
0
 public BooleanExpr(Token token, bool value)
     : base(SExprKind.Boolean, token, token)
 {
     if (token.Type != TokenType.Boolean) throw new ArgumentException("token must be of type Boolean for a BooleanExpr");
     Value = value;
 }
Beispiel #16
0
 public InstanceMemberIdentifierExpr(Token dot, Token ident)
     : base(SExprKind.InstanceMemberIdentifier, dot, ident)
 {
     Name = ident;
 }
Beispiel #17
0
        void Next()
        {
            if (hold)
            {
                hold = false;
                return;
            }
            tok = lex.Next();

            if (tok.Type == TokenType.EOF) next = new ParserError(tok, "Unexpected end");
            else if (tok.Type == TokenType.Error) next = new ParserError(tok, tok.Text);
            else next = tok;
        }
Beispiel #18
0
 public IntegerExpr(Token token, long value)
     : base(SExprKind.Integer, token, token)
 {
     if (token.Type != TokenType.Integer) throw new ArgumentException("token must be of type Integer for an IntegerExpr");
     Value = value;
 }
Beispiel #19
0
 public ParserException(Token tok, string message)
     : base("MiniLISP error(pos {0}): {1}".F(tok.Position, message))
 {
     Token = tok;
 }
Beispiel #20
0
 public QuoteExpr(Token start, Token end, SExpr sexpr)
     : base(SExprKind.Quote, start, end)
 {
     SExpr = sexpr;
 }