コード例 #1
0
 public override void Visit(IndexExpr expr)
 {
     if (expr.Target == null)
     {
         _needsAsync = true;
     }
 }
コード例 #2
0
 /// <summary>
 /// Visits the function call expression tree
 /// </summary>
 /// <param name="exp"></param>
 public object VisitIndex(IndexExpr exp)
 {
     _callBackOnNodeStart(exp);
     _callBackOnNodeStart(exp.VarExp);
     _callBackOnNodeStart(exp.IndexExp);
     return(null);
 }
コード例 #3
0
        /// <summary>
        /// Evaluate object[index]
        /// </summary>
        /// <returns></returns>
        public object VisitIndex(IndexExpr expr)
        {
            var ndxVal     = expr.IndexExp.Evaluate(this);
            var listObject = expr.VarExp.Evaluate(this);

            // Check for empty objects.
            ExceptionHelper.NotNull(expr, listObject, "indexing");
            ExceptionHelper.NotNull(expr, ndxVal, "indexing");

            var lobj = (LObject)listObject;

            // CASE 1. Access
            //      e.g. Array: users[0]
            //      e.g. Map:   users['total']
            if (!expr.IsAssignment)
            {
                var result = EvalHelper.AccessIndex(Ctx.Methods, expr, lobj, (LObject)ndxVal);
                return(result);
            }

            // CASE 2.  Assignment
            //      e.g. Array: users[0]        = 'john'
            //      e.g. Map:   users['total']  = 200
            // NOTE: In this case of assignment, return back a MemberAccess object descripting what is assign
            var indexAccess = new IndexAccess();

            indexAccess.Instance   = lobj;
            indexAccess.MemberName = (LObject)ndxVal;
            return(indexAccess);
        }
コード例 #4
0
        /// <summary>
        /// Creates an index expression from the parameters supplied.
        /// </summary>
        /// <param name="varExp"></param>
        /// <param name="indexExp"></param>
        /// <param name="isAssignment"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Expr Index(Expr varExp, Expr indexExp, bool isAssignment, TokenData token)
        {
            var exp = new IndexExpr();

            exp.IsAssignment = isAssignment;
            exp.VarExp       = varExp;
            exp.IndexExp     = indexExp;
            SetupContext(exp, token);
            return(exp);
        }
コード例 #5
0
        private Expr ParseIndexExpr(Expr prev)
        {
            var openBracket = Match("[");
            var next        = GetToken();

            Expr projectionFilter = null;

            if (next.Kind == "STRING" && GetToken(1).Kind == "]")
            {
                Match("STRING");
                Match("]");
                projectionFilter = new KeyExpr(GetLocation(next), prev, next.Text);
            }
            else if (next.Kind == "..")
            {
                Match("..");

                next = GetToken();
                if (next.Kind == "]")
                {
                    Match("]");
                    projectionFilter = new SliceExpr(GetLocation(openBracket), prev, null, null);
                }
                else
                {
                    var upperBound = ParseExpr();
                    projectionFilter = new SliceExpr(GetLocation(openBracket), prev, null, upperBound);
                }
            }
            else
            {
                var filter = ParseExpr();
                next = GetToken();

                if (next.Kind == "..")
                {
                    Expr upperBound = null;
                    Match("..");
                    next = GetToken();
                    if (next.Kind != "]")
                    {
                        upperBound = ParseExpr();
                    }
                    Match("]");
                    projectionFilter = new SliceExpr(GetLocation(openBracket), prev, filter, upperBound);
                }
                else
                {
                    Match("]");
                    projectionFilter = new IndexExpr(GetLocation(openBracket), prev, filter);
                }
            }

            return(projectionFilter);
        }
コード例 #6
0
    public override Null Visit(IndexExpr node)
    {
        context = null;
        node.computedType = new ErrorType();
        base.Visit(node);

        if (!(node.obj.computedType is ListType)) {
            log.ErrorTypeMismatch(node.location, new ListType(), node.obj.computedType);
            return null;
        }
        if (!node.index.computedType.IsInt()) {
            log.ErrorTypeMismatch(node.location, new PrimType { kind = PrimKind.Int }, node.index.computedType);
            return null;
        }
        node.computedType = node.obj.computedType.ItemType();

        return null;
    }
コード例 #7
0
ファイル: Minifier.cs プロジェクト: iamjuarez/SharpLua
        internal string DoExpr(Expression e)
        {
            string ret = null;

            if (e is AnonymousFunctionExpr) // function() ... end
            {
                // TODO: optimize into InlineFunctionExpr?

                AnonymousFunctionExpr f  = e as AnonymousFunctionExpr;
                StringBuilder         sb = new StringBuilder();
                sb.Append("function(");
                for (int i = 0; i < f.Arguments.Count; i++)
                {
                    sb.Append(f.Arguments[i].Name);
                    if (i != f.Arguments.Count - 1 || f.IsVararg)
                    {
                        sb.Append(",");
                    }
                }
                if (f.IsVararg)
                {
                    sb.Append("...");
                }
                sb.Append(")");
                sb.Append(DoChunk(f.Body));
                sb.Append(" end");

                ret = sb.ToString();
            }
            else if (e is BinOpExpr)
            {
                string left  = DoExpr((e as BinOpExpr).Lhs);
                string op    = (e as BinOpExpr).Op;
                string right = DoExpr((e as BinOpExpr).Rhs);
                ret = string.Format("{0}{1}{2}", left, op, right);
            }
            else if (e is BoolExpr)
            {
                bool val = (e as BoolExpr).Value;
                ret = val ? "true" : "false";
            }
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr      c  = e as CallExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(DoExpr(c.Base) + "(");
                for (int i = 0; i < c.Arguments.Count; i++)
                {
                    sb.Append(DoExpr(c.Arguments[i]));
                    if (i != c.Arguments.Count - 1)
                    {
                        sb.Append(",");
                    }
                }
                sb.Append(")");
                ret = sb.ToString();
            }
            else if (e is StringCallExpr)
            {
                StringCallExpr s = e as StringCallExpr;
                ret = string.Format("{0}{1}", DoExpr(s.Base), DoExpr(s.Arguments[0]));
            }
            else if (e is TableCallExpr)
            {
                TableCallExpr s = e as TableCallExpr;
                ret = string.Format("{0}{1}", DoExpr(s.Base), DoExpr(s.Arguments[0]));
            }
            else if (e is IndexExpr)
            {
                IndexExpr i = e as IndexExpr;
                ret = string.Format("{0}[{1}]", DoExpr(i.Base), DoExpr(i.Index));
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression ife = e as InlineFunctionExpression;
                StringBuilder            sb  = new StringBuilder();
                sb.Append("|");
                for (int i = 0; i < ife.Arguments.Count; i++)
                {
                    sb.Append(ife.Arguments[i].Name);
                    if (i != ife.Arguments.Count - 1 || ife.IsVararg)
                    {
                        sb.Append(", ");
                    }
                }
                if (ife.IsVararg)
                {
                    sb.Append("...");
                }
                sb.Append("|->");
                for (int i2 = 0; i2 < ife.Expressions.Count; i2++)
                {
                    sb.Append(DoExpr(ife.Expressions[i2]));
                    if (i2 != ife.Expressions.Count - 1)
                    {
                        sb.Append(",");
                    }
                }
                ret = sb.ToString();
            }
            else if (e is TableConstructorKeyExpr)
            {
                TableConstructorKeyExpr t = e as TableConstructorKeyExpr;
                ret = "[" + DoExpr(t.Key) + "]=" + DoExpr(t.Value);
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret = DoExpr(m.Base) + m.Indexer + m.Ident;
            }
            else if (e is NilExpr)
            {
                ret = "nil";
            }
            else if (e is NumberExpr)
            {
                ret = (e as NumberExpr).Value;
            }
            else if (e is StringExpr)
            {
                StringExpr se    = e as StringExpr;
                string     delim = se.StringType == TokenType.SingleQuoteString ? "'" : (se.StringType == TokenType.DoubleQuoteString ? "\"" : "[");
                if (delim == "[")
                {
                    // Long strings keep their [=*[
                    ret = se.Value;
                }
                else
                {
                    ret = delim + se.Value + delim;
                }
            }
            else if (e is TableConstructorStringKeyExpr)
            {
                TableConstructorStringKeyExpr tcske = e as TableConstructorStringKeyExpr;
                ret = tcske.Key + "=" + DoExpr(tcske.Value);
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t  = e as TableConstructorExpr;
                StringBuilder        sb = new StringBuilder();
                sb.Append("{");
                for (int i = 0; i < t.EntryList.Count; i++)
                {
                    sb.Append(DoExpr(t.EntryList[i]));
                    if (i != t.EntryList.Count - 1)
                    {
                        sb.Append(",");
                    }
                }
                sb.Append("}");
                ret = sb.ToString();
            }
            else if (e is UnOpExpr)
            {
                string op = (e as UnOpExpr).Op;
                string s  = op;
                if (s.Length != 1)
                {
                    s += " ";
                }
                ret = s + DoExpr((e as UnOpExpr).Rhs);
            }
            else if (e is TableConstructorValueExpr)
            {
                ret = DoExpr((e as TableConstructorValueExpr).Value);
            }
            else if (e is VarargExpr)
            {
                ret = "...";
            }
            else if (e is VariableExpression)
            {
                ret = (e as VariableExpression).Var.Name;
            }

            if (ret != null)
            {
                return(string.Format("{0}{1}{2}", "(".Repeat(e.ParenCount), ret, ")".Repeat(e.ParenCount)));
            }

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
コード例 #8
0
ファイル: Beautifier.cs プロジェクト: Hengle/SharpLua-1
        internal string DoExpr(Expression e, List <Token> tok, ref int index, Scope s)
        {
            int startP = index;

            for (int i = 0; i < e.ParenCount; i++)
            {
                index++;
            }

            string ret = null;

            if (e is AnonymousFunctionExpr) // function() ... end
            {
                AnonymousFunctionExpr f  = e as AnonymousFunctionExpr;
                StringBuilder         sb = new StringBuilder();

                sb.Append(fromToken(tok[index++], s)); // 'function'
                sb.Append(fromToken(tok[index++], s)); // '('
                for (int i2 = 0; i2 < f.Arguments.Count; i2++)
                {
                    sb.Append(fromToken(tok[index++], s));
                    if (i2 != f.Arguments.Count - 1 || f.IsVararg)
                    {
                        sb.Append(fromToken(tok[index++], s) + " ");
                    }
                }
                if (f.IsVararg)
                {
                    sb.Append(fromToken(tok[index++], s));
                }
                sb.Append(fromToken(tok[index++], s)); // ')'

                if (f.Body.Count > 1)
                {
                    sb.Append(options.EOL);
                    indent++;
                    sb.Append(DoChunk(f.Body));
                    sb.Append(nldedent());
                }
                else if (f.Body.Count == 0)
                {
                    sb.Append(" ");
                }
                else
                {
                    sb.Append(" " + DoStatement(f.Body[0]));
                    sb.Append(" ");
                }

                //sb.Append(DoChunk(f.Body));
                // Ugh.
                sb.Append(fromToken(tok[index++], s)); // <end>

                ret = sb.ToString();
            }
            else if (e is BinOpExpr)
            {
                //int i = 0;
                string left  = DoExpr((e as BinOpExpr).Lhs, tok, ref index, s);
                string op    = fromToken(tok[index++], s);
                string right = DoExpr((e as BinOpExpr).Rhs, tok, ref index, s);
                ret = string.Format("{0} {1} {2}", left, op, right);
            }
            else if (e is BoolExpr)
            {
                ret = fromToken(tok[index++], s);
            }
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr      c  = e as CallExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(DoExpr(c.Base, tok, ref index, s) // <base>
                          + fromToken(tok[index++], s));    // '('
                for (int i = 0; i < c.Arguments.Count; i++)
                {
                    sb.Append(DoExpr(c.Arguments[i], tok, ref index, s));
                    if (i != c.Arguments.Count - 1)
                    {
                        sb.Append(fromToken(tok[index++], s)); // ', '
                        sb.Append(" ");
                    }
                }
                sb.Append(fromToken(tok[index++], s)); // ')'
                ret = sb.ToString();
            }
            else if (e is StringCallExpr)
            {
                StringCallExpr sc = e as StringCallExpr;
                ret = string.Format("{0} {1}", DoExpr(sc.Base, tok, ref index, s), DoExpr(sc.Arguments[0], tok, ref index, s));
            }
            else if (e is TableCallExpr)
            {
                TableCallExpr sc = e as TableCallExpr;
                ret = string.Format("{0} {1}", DoExpr(sc.Base, tok, ref index, s), DoExpr(sc.Arguments[0], tok, ref index, s));
            }
            else if (e is IndexExpr)
            {
                IndexExpr i = e as IndexExpr;
                ret = string.Format("{0}{1}{2}{3}", DoExpr(i.Base, tok, ref index, s), fromToken(tok[index++], s), DoExpr(i.Index, tok, ref index, s), fromToken(tok[index++], s));
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression ife = e as InlineFunctionExpression;
                StringBuilder            sb  = new StringBuilder();
                sb.Append(fromToken(tok[index++], s)); // '|;
                for (int i = 0; i < ife.Arguments.Count; i++)
                {
                    sb.Append(fromToken(tok[index++], s)); // <arg name>
                    if (i != ife.Arguments.Count - 1 || ife.IsVararg)
                    {
                        sb.Append(fromToken(tok[index++], s)); // ','
                        sb.Append(" ");
                    }
                }
                if (ife.IsVararg)
                {
                    sb.Append(fromToken(tok[index++], s)); // '...'
                    sb.Append(" ");
                }
                sb.Append(fromToken(tok[index++], s)); // '|'
                sb.Append(" ");
                sb.Append(fromToken(tok[index++], s)); // '->'
                sb.Append(" ");
                for (int i2 = 0; i2 < ife.Expressions.Count; i2++)
                {
                    sb.Append(DoExpr(ife.Expressions[i2], tok, ref index, s));
                    if (i2 != ife.Expressions.Count - 1)
                    {
                        sb.Append(fromToken(tok[index++], s)); // ','
                        sb.Append(" ");
                    }
                }
                ret = sb.ToString();
            }
            else if (e is TableConstructorKeyExpr)
            {
                TableConstructorKeyExpr t = e as TableConstructorKeyExpr;
                ret =
                    fromToken(tok[index++], s)
                    + DoExpr(t.Key, tok, ref index, s)
                    + fromToken(tok[index++], s)
                    + " "
                    + fromToken(tok[index++], s)
                    + " "
                    + DoExpr(t.Value, tok, ref index, s);
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret = DoExpr(m.Base, tok, ref index, s) + fromToken(tok[index++], s) + fromToken(tok[index++], s);
            }
            else if (e is NilExpr)
            {
                ret = fromToken(tok[index++], s);
            }
            else if (e is NumberExpr)
            {
                ret = fromToken(tok[index++], s);
            }
            else if (e is StringExpr)
            {
                ret = fromToken(tok[index++], s);
            }
            else if (e is TableConstructorStringKeyExpr)
            {
                TableConstructorStringKeyExpr tcske = e as TableConstructorStringKeyExpr;
                ret  = fromToken(tok[index++], s);             // key
                ret += " ";
                ret += fromToken(tok[index++], s);             // '='
                ret += " ";
                ret += DoExpr(tcske.Value, tok, ref index, s); // value
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t  = e as TableConstructorExpr;
                StringBuilder        sb = new StringBuilder();
                sb.Append(fromToken(tok[index++], s)); // '{'
                sb.Append(" ");
                for (int i = 0; i < t.EntryList.Count; i++)
                {
                    sb.Append(DoExpr(t.EntryList[i], tok, ref index, s));
                    if (i != t.EntryList.Count - 1)
                    {
                        sb.Append(fromToken(tok[index++], s)); // ','
                        sb.Append(" ");
                    }
                }
                if (t.EntryList.Count > 0) // empty table constructor is just { }
                {
                    sb.Append(" ");
                }
                sb.Append(fromToken(tok[index++], s)); // '}'
                ret = sb.ToString();
            }
            else if (e is UnOpExpr)
            {
                UnOpExpr u  = e as UnOpExpr;
                string   sc = fromToken(tok[index++], s);
                if (u.Op.Length != 1)
                {
                    sc += " ";
                }
                ret = sc + DoExpr(u.Rhs, tok, ref index, s);
            }
            else if (e is TableConstructorValueExpr)
            {
                ret = DoExpr(((TableConstructorValueExpr)e).Value, tok, ref index, s);
            }
            else if (e is VarargExpr)
            {
                ret = fromToken(tok[index++], s);
            }
            else if (e is VariableExpression)
            {
                ret = fromToken(tok[index++], s);
            }
            else if (e is TableConstructorNamedFunctionExpr)
            {
                ret = DoStatement(((TableConstructorNamedFunctionExpr)e).Value);
            }

            if (ret != null)
            {
                if (e.ParenCount > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < e.ParenCount; i++)
                    {
                        sb.Append(fromToken(tok[startP++], s));
                    }
                    sb.Append(ret);
                    for (int i = 0; i < e.ParenCount; i++)
                    {
                        sb.Append(fromToken(tok[index++], s));
                    }
                    return(sb.ToString());
                }
                else
                {
                    return(ret);
                }
            }
            //return string.Format("{0}{1}{2}", "(".Repeat(e.ParenCount), ret, ")".Repeat(e.ParenCount));

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
コード例 #9
0
        string DoExpr(Expression e)
        {
            string ret = "";

            if (e is AnonymousFunctionExpr) // function() ... end
            {
                AnonymousFunctionExpr f  = e as AnonymousFunctionExpr;
                StringBuilder         sb = new StringBuilder();
                sb.Append("function(");
                for (int i = 0; i < f.Arguments.Count; i++)
                {
                    sb.Append(f.Arguments[i].Name);
                    if (i != f.Arguments.Count - 1 || f.IsVararg)
                    {
                        sb.Append(", ");
                    }
                }
                if (f.IsVararg)
                {
                    sb.Append("...");
                }
                sb.Append(")");
                if (f.Body.Count > 1)
                {
                    sb.Append(EOL);
                    indent++;
                    sb.Append(DoChunk(f.Body));
                    sb.Append(nldedent());
                    sb.Append("end");
                }
                else if (f.Body.Count == 0)
                {
                    sb.Append(" end");
                }
                else
                {
                    sb.Append(" " + DoStatement(f.Body[0]));
                    sb.Append(" end");
                }

                ret = sb.ToString();
            }
            else if (e is BinOpExpr)
            {
                BinOpExpr b     = e as BinOpExpr;
                string    left  = DoExpr(b.Lhs);
                string    op    = b.Op;
                string    right = DoExpr(b.Rhs);
                if (op == "!=")
                {
                    op = "~=";
                }

                if (op == ">>")
                {
                    ret = string.Format("bit.rshift({0}, {1})", left, right);
                }
                else if (op == "<<")
                {
                    ret = string.Format("bit.lshift({0}, {1})", left, right);
                }
                else if (op == "&")
                {
                    ret = string.Format("bit.band({0}, {1})", left, right);
                }
                else if (op == "|")
                {
                    ret = string.Format("bit.bor({0}, {1})", left, right);
                }
                else if (op == "^^")
                {
                    ret = string.Format("bit.bxor({0}, {1})", left, right);
                }
                else
                {
                    ret = string.Format("{0} {1} {2}", left, op, right);
                }
            }
            else if (e is BoolExpr)
            {
                bool val = (e as BoolExpr).Value;
                ret = val ? "true" : "false";
            }
            else if (e is CallExpr && (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr      c  = e as CallExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(DoExpr(c.Base) + "(");
                for (int i = 0; i < c.Arguments.Count; i++)
                {
                    sb.Append(DoExpr(c.Arguments[i]));
                    if (i != c.Arguments.Count - 1)
                    {
                        sb.Append(", ");
                    }
                }
                sb.Append(")");
                ret = sb.ToString();
            }
            else if (e is StringCallExpr)
            {
                StringCallExpr s = e as StringCallExpr;
                ret = string.Format("{0} {1}", DoExpr(s.Base), DoExpr(s.Arguments[0]));
            }
            else if (e is TableCallExpr)
            {
                TableCallExpr s = e as TableCallExpr;
                ret = string.Format("{0} {1}", DoExpr(s.Base), DoExpr(s.Arguments[0]));
            }
            else if (e is IndexExpr)
            {
                IndexExpr i = e as IndexExpr;
                ret = string.Format("{0}[{1}]", DoExpr(i.Base), DoExpr(i.Index));
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression ife = e as InlineFunctionExpression;
                StringBuilder            sb  = new StringBuilder();
                sb.Append("function(");
                for (int i = 0; i < ife.Arguments.Count; i++)
                {
                    sb.Append(ife.Arguments[i].Name);
                    if (i != ife.Arguments.Count - 1 || ife.IsVararg)
                    {
                        sb.Append(", ");
                    }
                }
                if (ife.IsVararg)
                {
                    sb.Append("...");
                }
                sb.Append(") return ");
                for (int i2 = 0; i2 < ife.Expressions.Count; i2++)
                {
                    sb.Append(DoExpr(ife.Expressions[i2]));
                    if (i2 != ife.Expressions.Count - 1)
                    {
                        sb.Append(", ");
                    }
                }
                sb.Append(" end");
                ret = sb.ToString();
            }
            else if (e is TableConstructorKeyExpr)
            {
                TableConstructorKeyExpr t = e as TableConstructorKeyExpr;
                ret = "[" + DoExpr(t.Key) + "] = " + DoExpr(t.Value);
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret = DoExpr(m.Base) + m.Indexer + m.Ident;
            }
            else if (e is NilExpr)
            {
                ret = "nil";
            }
            else if (e is NumberExpr)
            {
                ret = (e as NumberExpr).Value;
                ret = ret.Replace("_", "");
            }
            else if (e is StringExpr)
            {
                StringExpr se    = e as StringExpr;
                string     delim = se.StringType == TokenType.SingleQuoteString ? "'" : se.StringType == TokenType.DoubleQuoteString ? "\"" : "[";
                if (delim == "[")
                {
                    // Long strings keep their [=*[
                    ret = se.Value;
                }
                else
                {
                    ret = delim + se.Value + delim;
                }
            }
            else if (e is TableConstructorStringKeyExpr)
            {
                TableConstructorStringKeyExpr tcske = e as TableConstructorStringKeyExpr;
                ret = tcske.Key + " = " + DoExpr(tcske.Value);
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t  = e as TableConstructorExpr;
                StringBuilder        sb = new StringBuilder();
                sb.Append("{ ");
                for (int i = 0; i < t.EntryList.Count; i++)
                {
                    sb.Append(DoExpr(t.EntryList[i]));
                    if (i != t.EntryList.Count - 1)
                    {
                        sb.Append(", ");
                    }
                }
                sb.Append("} ");
                ret = sb.ToString();
            }
            else if (e is UnOpExpr)
            {
                string op = (e as UnOpExpr).Op;
                if (op == "!")
                {
                    op = "not";
                }
                string s = op;
                if (s == "~")
                {
                    ret = "bit.bnot(" + DoExpr((e as UnOpExpr).Rhs) + ")";
                }
                else if (s == "+")
                {
                    ret = "math.abs(" + DoExpr((e as UnOpExpr).Rhs) + ")";
                }
                else
                {
                    if (s.Length != 1)
                    {
                        s += " ";
                    }
                    ret = s + DoExpr((e as UnOpExpr).Rhs);
                }
            }
            else if (e is TableConstructorValueExpr)
            {
                ret = DoExpr((e as TableConstructorValueExpr).Value);
            }
            else if (e is VarargExpr)
            {
                ret = "...";
            }
            else if (e is VariableExpression)
            {
                ret = (e as VariableExpression).Var.Name;
            }
            else if (e is TableConstructorNamedFunctionExpr)
            {
                TableConstructorNamedFunctionExpr fs = e as TableConstructorNamedFunctionExpr;
                AnonymousFunctionExpr             a  = new AnonymousFunctionExpr();
                a.Arguments = fs.Value.Arguments;
                a.Arguments.Insert(0, new Variable()
                {
                    Name = "self", IsGlobal = false, References = -1
                });
                a.Body     = fs.Value.Body;
                a.IsVararg = fs.Value.IsVararg;
                ret        = DoExpr(fs.Value.Name) + " = " + DoExpr(a);
            }

            return(string.Format("{0}{1}{2}", oparens(e.ParenCount), ret, cparens(e.ParenCount)));

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
コード例 #10
0
ファイル: Parser.cs プロジェクト: icedream/SharpLua
        Expression ParseSuffixedExpr(Scope scope, bool onlyDotColon = false)
        {
            // base primary expression
            Expression prim = ParsePrimaryExpr(scope);

            while (true)
            {
                if (reader.IsSymbol('.') || reader.IsSymbol(':'))
                {
                    string symb = reader.Get().Data; // '.' or ':'
                    // TODO: should we allow keywords? I vote no.
                    if (!reader.Is(TokenType.Ident))
                    {
                        error("<Ident> expected");
                    }

                    Token      id = reader.Get();
                    MemberExpr m  = new MemberExpr();
                    m.Base    = prim;
                    m.Indexer = symb;
                    m.Ident   = id.Data;

                    prim = m;
                }
                else if (!onlyDotColon && reader.ConsumeSymbol('['))
                {
                    int       pass           = 0;
                    const int maxamount      = 100;
                    bool      wasLastNumeric = false;
                    bool      first          = true;
                    bool      hadComma       = false;
                    do
                    {
                        Token tok  = reader.Peek();
                        int   col  = tok.Column;
                        int   line = tok.Line;

                        Expression ex = ParseExpr(scope);
                        //if (!reader.ConsumeSymbol(']'))
                        //error("']' expected");

                        IndexExpr i = new IndexExpr();
                        i.Base  = prim;
                        i.Index = ex;

                        prim = i;

                        if ((first || wasLastNumeric) && ex is NumberExpr && hadComma == false)
                        {
                            tok = reader.Peek();
                            bool cma = reader.ConsumeSymbol(',');
                            if (cma && hadComma == false && first == false)
                            {
                                error("Unexpected ',' in matrice indexing", tok.Line, tok.Column, tok);
                            }
                            //else if (cma == false && hadComma)
                            //    ;
                            hadComma = cma;
                        }
                        else
                        {
                            tok = reader.Peek();
                            bool cma = reader.ConsumeSymbol(',');
                            //if (cma == false)
                            //    break;
                            if (cma && hadComma == false)
                            {
                                error("Unexpected ',' in matrice indexing", -1, -1, tok);
                            }
                            else if (cma == false && ex is NumberExpr == false && wasLastNumeric && hadComma == false)
                            {
                                error("Expected numeric constant in matrice indexing", line, col, tok);
                            }
                            else if (cma == false && hadComma)
                            {
                                if (tok.Type == TokenType.Symbol && tok.Data == "]")
                                {
                                    ;
                                }
                                else
                                {
                                    error("Expected ','", -1, -1, tok);
                                }
                            }
                            else if (cma == false)
                            {
                                break;
                            }
                            else
                            {
                                hadComma = true;
                            }
                            hadComma = cma;
                        }

                        if (pass++ >= maxamount)
                        {
                            error("Maximum index depth reached");
                        }

                        wasLastNumeric = ex is NumberExpr;
                        first          = false;
                    } while (!(reader.Peek().Data == "]"));
                    if (!reader.ConsumeSymbol(']'))
                    {
                        error("']' expected");
                    }
                }
                else if (!onlyDotColon && reader.ConsumeSymbol('('))
                {
                    List <Expression> args = new List <Expression>();
                    while (!reader.ConsumeSymbol(')'))
                    {
                        Expression ex = ParseExpr(scope);

                        args.Add(ex);
                        if (!reader.ConsumeSymbol(','))
                        {
                            if (reader.ConsumeSymbol(')'))
                            {
                                break;
                            }
                            else
                            {
                                error("')' expected");
                            }
                            break;
                        }
                    }
                    CallExpr c = new CallExpr();
                    c.Base      = prim;
                    c.Arguments = args;

                    prim = c;
                }
                else if (!onlyDotColon &&
                         (reader.Is(TokenType.SingleQuoteString) ||
                          reader.Is(TokenType.DoubleQuoteString) ||
                          reader.Is(TokenType.LongString)))
                {
                    //string call

                    StringCallExpr e = new StringCallExpr();
                    e.Base      = prim;
                    e.Arguments = new List <Expression> {
                        new StringExpr(reader.Peek().Data)
                        {
                            StringType = reader.Peek().Type
                        }
                    };
                    reader.Get();
                    prim = e;
                }
                else if (!onlyDotColon && reader.IsSymbol('{'))
                {
                    // table call

                    // Fix for the issue with whole expr being parsed, not just table.
                    // See LuaMinify issue #2 (https://github.com/stravant/LuaMinify/issues/2)
                    //Expression ex = ParseExpr(scope);
                    Expression ex = ParseSimpleExpr(scope);

                    TableCallExpr t = new TableCallExpr();
                    t.Base      = prim;
                    t.Arguments = new List <Expression> {
                        ex
                    };

                    prim = t;
                }
                else
                {
                    break;
                }
            }
            return(prim);
        }
コード例 #11
0
 public override void Visit(IndexExpr expr) => _needsAsyncByItself         = true;
コード例 #12
0
            Expr SpecFuncs(CallExpr ce)
            {
                Expr src, ndx;
                bool forPrev = false, forCell = false;
                int  nMinArgs = 1;

                switch (ce.funcName)
                {
                case "PREVCELL":
                    forCell = true; forPrev = true; break;

                case "PREV":
                    nMinArgs = 0; forPrev = true; break;

                case "INDIRECT":
                    forCell = true; break;

                case nameof(FuncDefs_Xlsx.COLUMN):
                    // avoid COLUMN(args) fixing
                    return(new CallExpr(nameof(FuncDefs_Xlsx.COLUMN), ce.args));

                default:
                    return(ce);
                }
                if (ce.args.Count < nMinArgs)
                {
                    return(ce);
                }

                Expr   arg;
                string name;

                if (ce.args.Count == 0)
                {
                    arg  = null;
                    name = FCurrName;
                }
                else
                {
                    arg = ce.args[0];
                    if (arg.nodeType == ExprType.Reference)
                    {
                        name = ((ReferenceExpr)arg).name;
                        if (IsColumnName(name) || !forPrev && IsFullRelativeCell(CellRange.FromName(name)))
                        {
                            forCell = true;
                        }
                        else
                        {
                            name = OPs.TryAsString(arg, ctxRow) ?? name;
                        }
                    }
                    else
                    {
                        arg  = FixRowExpr(arg);
                        name = OPs.TryAsName(arg, ctxRow);
                    }
                }

                if (name == null)
                {
                    var undefs = string.Join(", ", ctxHdr.NamesOfUndefinedValues().Concat(ctxRow.NamesOfUndefinedValues()));
                    throw new Source.Exception($"Constant expected as value of {ce.args[0]}={arg} // ??? {undefs}");
                }

                if (forCell || IsColumnName(name) || !forPrev && IsFullRelativeCell(CellRange.FromName(name)))
                {
                    if (forPrev)
                    {
                        src = new IndexExpr(PrevValsRef, new ConstExpr(ctxRow.IndexOf(CellValsRef.name)));
                    }
                    else
                    {
                        var re1 = new ReferenceExpr(name);
                        var re2 = FixHdrCellRef(re1);
                        if (re2 != re1)
                        {
                            // ref to header cell
                            return(re2);
                        }
                        else
                        {
                            // ref to row cell
                            src = CellValsRef;
                        }
                    }
                    ndx = new ConstExpr(name);
                }
                else
                {
                    int i = ctxRow.IndexOf(name);
                    if (i < 0 || Generator.Ctx.ctxDepthStep <= i)
                    {
                        throw new Source.Exception($"Value named '{name}' not found in row context");
                    }
                    src = PrevValsRef;
                    ndx = new ConstExpr(i);
                }
                return(new IndexExpr(src, ndx));
            }
コード例 #13
0
ファイル: ExprVisitor.cs プロジェクト: jimdeselms/bifoql
 public virtual void Visit(IndexExpr expr)
 {
 }
コード例 #14
0
        void DoExpr(Expression e, bool setVar = false, int setVarLhsCount = -1, bool onlyCheckConsts = false)
        {
            if (e is AnonymousFunctionExpr) // function() ... end
            {
            }
            else if (e is BinOpExpr)
            {
                BinOpExpr boe = e as BinOpExpr;
                switch (boe.GetOperator())
                {
                case BinaryOperator.Add:
                    binOp("ADD", boe.Lhs, boe.Rhs);
                    return;

                case BinaryOperator.Subtract:
                    binOp("SUB", boe.Lhs, boe.Rhs);
                    return;

                case BinaryOperator.Multiply:
                    binOp("MUL", boe.Lhs, boe.Rhs);
                    return;

                case BinaryOperator.Divide:
                    binOp("DIV", boe.Lhs, boe.Rhs);
                    return;

                case BinaryOperator.Power:
                    binOp("POW", boe.Lhs, boe.Rhs);
                    return;

                case BinaryOperator.Modulus:
                    binOp("MOD", boe.Lhs, boe.Rhs);
                    return;

                case BinaryOperator.Concat:
                    binOp("CONCAT", boe.Lhs, boe.Rhs);
                    return;

                case BinaryOperator.And:
                    break;

                case BinaryOperator.Or:
                    break;

                case BinaryOperator.LessThan:
                    break;

                case BinaryOperator.LessThanOrEqualTo:
                    break;

                case BinaryOperator.GreaterThan:
                    break;

                case BinaryOperator.GreaterThanOrEqualTo:
                    break;

                case BinaryOperator.NotEqual:
                    break;

                case BinaryOperator.ShiftRight:
                    CallExpr ce = new CallExpr();
                    ce.Arguments.Add(boe.Lhs);
                    ce.Arguments.Add(boe.Rhs);
                    ce.Base = new MemberExpr()
                    {
                        Base = new VariableExpression()
                        {
                            Var = new Variable()
                            {
                                Name = "bit", IsGlobal = true
                            }
                        },
                        Ident   = "rshift",
                        Indexer = ".",
                    };
                    DoExpr(ce);
                    return;

                case BinaryOperator.ShiftLeft:
                    ce = new CallExpr();
                    ce.Arguments.Add(boe.Lhs);
                    ce.Arguments.Add(boe.Rhs);
                    ce.Base = new MemberExpr()
                    {
                        Base = new VariableExpression()
                        {
                            Var = new Variable()
                            {
                                Name = "bit", IsGlobal = true
                            }
                        },
                        Ident   = "lshift",
                        Indexer = ".",
                    };
                    DoExpr(ce);
                    return;

                case BinaryOperator.Xor:
                    ce = new CallExpr();
                    ce.Arguments.Add(boe.Lhs);
                    ce.Arguments.Add(boe.Rhs);
                    ce.Base = new MemberExpr()
                    {
                        Base = new VariableExpression()
                        {
                            Var = new Variable()
                            {
                                Name = "bit", IsGlobal = true
                            }
                        },
                        Ident   = "bxor",
                        Indexer = ".",
                    };
                    DoExpr(ce);
                    return;

                case BinaryOperator.BitAnd:
                    ce = new CallExpr();
                    ce.Arguments.Add(boe.Lhs);
                    ce.Arguments.Add(boe.Rhs);
                    ce.Base = new MemberExpr()
                    {
                        Base = new VariableExpression()
                        {
                            Var = new Variable()
                            {
                                Name = "bit", IsGlobal = true
                            }
                        },
                        Ident   = "band",
                        Indexer = ".",
                    };
                    DoExpr(ce);
                    return;

                case BinaryOperator.BitOr:
                    ce = new CallExpr();
                    ce.Arguments.Add(boe.Lhs);
                    ce.Arguments.Add(boe.Rhs);
                    ce.Base = new MemberExpr()
                    {
                        Base = new VariableExpression()
                        {
                            Var = new Variable()
                            {
                                Name = "bit", IsGlobal = true
                            }
                        },
                        Ident   = "bor",
                        Indexer = ".",
                    };
                    DoExpr(ce);
                    return;

                case BinaryOperator.BitNot:
                    ce = new CallExpr();
                    ce.Arguments.Add(boe.Lhs);
                    ce.Arguments.Add(boe.Rhs);
                    ce.Base = new MemberExpr()
                    {
                        Base = new VariableExpression()
                        {
                            Var = new Variable()
                            {
                                Name = "bit", IsGlobal = true
                            }
                        },
                        Ident   = "bnot",
                        Indexer = ".",
                    };
                    DoExpr(ce);
                    return;

                case BinaryOperator.NONE:
                default:
                    throw new Exception("Unknown binary operator '" + boe.Op + "'");
                }
            }
            else if (e is BoolExpr)
            {
                bool        v = ((BoolExpr)e).Value;
                Instruction i = new Instruction("LOADBOOL");
                i.A = block.getreg();
                i.B = v ? 1 : 0;
                i.C = 0;
                emit(i);
                return;
            }
            else if (e is CallExpr)//&& (!(e is StringCallExpr) && !(e is TableCallExpr)))
            {
                CallExpr ce   = e as CallExpr;
                int      breg = ++block.regnum;
                DoExpr(ce.Base);
                bool       isZero   = false;
                bool       isMethod = false;
                Expression ex       = ce.Base;
                while (ex != null)
                {
                    if (ex is IndexExpr)
                    {
                        ex = ((IndexExpr)ex).Index;
                    }
                    else if (ex is MemberExpr)
                    {
                        MemberExpr me = ex as MemberExpr;
                        if (me.Indexer == ":")
                        {
                            isMethod = true;
                            break;
                        }
                        else
                        {
                            break;
                        }
                        //ex = me.Ident;
                    }
                    else
                    {
                        break;
                    }
                }

                foreach (Expression e2 in ce.Arguments)
                {
                    DoExpr(e2);
                    if (e2 is CallExpr || block.Chunk.Instructions[block.Chunk.Instructions.Count - 1].Opcode == Instruction.LuaOpcode.CALL)
                    {
                        isZero = true;
                        Instruction i_ = block.Chunk.Instructions[block.Chunk.Instructions.Count - 1];
                        Debug.Assert(i_.Opcode == Instruction.LuaOpcode.CALL);
                        i_.C = 0;
                    }
                }

                Instruction i = new Instruction("CALL");
                i.A = breg;
                if (isMethod)
                {
                    //i.B++;
                    i.B = isZero ? 2 : (ce.Arguments.Count > 0 ? 2 + ce.Arguments.Count : 2);
                }
                else
                {
                    i.B = isZero ? 0 : (ce.Arguments.Count > 0 ? 1 + ce.Arguments.Count : 1);
                }

                i.C = setVarLhsCount == 0 || setVarLhsCount == -1 ?
                      1 :                 //(isZero ? 0 : 1) :
                      1 + setVarLhsCount; // (isZero ? 0 : 1 + setVarLhsCount);
                //i.C = setVarLhsCount == 0 || setVarLhsCount == -1 ? 1 : 1 + setVarLhsCount;
                emit(i);
                return;
            }
            else if (e is StringCallExpr)
            {
                throw new Exception();
            }
            else if (e is TableCallExpr)
            {
                throw new Exception();
            }
            else if (e is IndexExpr)
            {
                IndexExpr ie     = e as IndexExpr;
                int       regnum = block.regnum;
                DoExpr(ie.Base);
                DoExpr(ie.Index);
                Instruction i = new Instruction("GETTABLE");
                i.A = regnum;
                i.B = regnum;
                i.C = block.regnum - 1;// block.getreg();
                emit(i);
                block.regnum = regnum + 1;
                return;
            }
            else if (e is InlineFunctionExpression) // |<args>| -> <exprs>
            {
                InlineFunctionExpression i  = e as InlineFunctionExpression;
                AnonymousFunctionExpr    af = new AnonymousFunctionExpr();
                af.Arguments = i.Arguments;
                af.IsVararg  = i.IsVararg;
                af.Body      = new List <Statement>()
                {
                    new ReturnStatement
                    {
                        Arguments = i.Expressions
                    }
                };
                DoExpr(af);
            }
            else if (e is MemberExpr)
            {
                MemberExpr me = e as MemberExpr;
                if (me.Indexer == ".")
                {
                    int regnum = block.regnum;
                    DoExpr(me.Base);
                    DoExpr(new StringExpr(me.Ident), false, -1, true);
                    Instruction i = new Instruction("GETTABLE");
                    i.A = regnum;
                    i.B = regnum;
                    i.C = 256 + block.K[me.Ident];
                    //i.C = block.regnum - 1;// block.getreg();
                    emit(i);
                    block.regnum = regnum + 1;
                    return;
                }
                else if (me.Indexer == ":")
                {
                    int regnum = block.regnum;
                    DoExpr(me.Base);
                    DoExpr(new StringExpr(me.Ident), false, -1, true);
                    Instruction i = new Instruction("SELF");
                    i.A = regnum;
                    i.B = regnum;
                    i.C = 256 + block.K[me.Ident];
                    //i.C = block.regnum - 1;// block.getreg();
                    emit(i);
                    block.regnum = regnum + 1;
                    return;
                }
                else
                {
                    throw new Exception("Unknown member indexer '" + me.Indexer + "'");
                }
            }
            else if (e is NilExpr)
            {
                Instruction i = new Instruction("LOADNIL");
                i.A = block.getreg();
                i.B = setVarLhsCount == -1 ? i.A : setVarLhsCount - 1;
                i.C = 0;
                emit(i);
                return;
            }
            else if (e is NumberExpr)
            {
                NumberExpr ne = e as NumberExpr;

                // TODO: this can optimized into a Dictionary to avoid re-parsing numbers each time
                double r;
                int    x = Lua.luaO_str2d(ne.Value.Replace("_", ""), out r);
                if (x == 0)
                {
                    throw new LuaSourceException(line, 0, "Invalid number");
                }

                if (onlyCheckConsts == false)
                {
                    Instruction i = new Instruction("loadk");
                    i.A  = block.getreg();
                    i.Bx = block.K[r];
                    emit(i);
                }
                else
                {
                    block.K.Check(r);
                }
                return;
            }
            else if (e is StringExpr)
            {
                StringExpr se = e as StringExpr;
                string     s  = se.Value;
                if (se.StringType != TokenType.LongString)
                {
                    s = Unescaper.Unescape(s);
                }
                else
                {
                    int i = 1;
                    while (s[i] != '[')
                    {
                        i++;
                    }
                    i++;
                    s = s.Substring(i, s.Length - i - 2);
                }

                if (onlyCheckConsts == false)
                {
                    Instruction i2 = new Instruction("loadk");
                    i2.A  = block.getreg();
                    i2.Bx = block.K[s];
                    emit(i2);
                }
                else
                {
                    block.K.Check(s);
                }
                return;
            }
            else if (e is TableConstructorExpr)
            {
                Instruction i    = new Instruction("NEWTABLE");
                int         tblA = block.regnum;
                i.A = block.getreg();
                i.B = 0;
                i.C = 0;
                emit(i);

                TableConstructorExpr tce = e as TableConstructorExpr;
                if (tce.EntryList.Count == 0)
                {
                    return;
                }

                int  b           = 0;
                bool wasLastCall = false;
                foreach (Expression e2 in tce.EntryList)
                {
                    if (e2 is TableConstructorKeyExpr)
                    {
                        TableConstructorKeyExpr tcke = e2 as TableConstructorKeyExpr;
                        DoExpr(tcke.Key);
                        DoExpr(tcke.Value);
                    }
                    else if (e2 is TableConstructorNamedFunctionExpr)
                    {
                        TableConstructorNamedFunctionExpr tcnfe = e2 as TableConstructorNamedFunctionExpr;
                    }
                    else if (e2 is TableConstructorStringKeyExpr)
                    {
                        TableConstructorStringKeyExpr tcske = e2 as TableConstructorStringKeyExpr;
                        DoExpr(new StringExpr(tcske.Key));
                        DoExpr(tcske.Value);
                    }
                    else if (e2 is TableConstructorValueExpr)
                    {
                        TableConstructorValueExpr tcve = e2 as TableConstructorValueExpr;
                        DoExpr(tcve.Value);
                        if (tcve.Value is VarargExpr || tcve.Value is CallExpr)
                        {
                            wasLastCall = true;
                        }
                        else
                        {
                            wasLastCall = false;
                        }
                    }

                    b++;
                }

                i.B = b;

                i   = new Instruction("SETLIST");
                i.A = tblA;
                if (wasLastCall)
                {
                    i.B = 0;
                }
                else
                {
                    i.B = block.regnum - 1;
                }
                i.C = tblA + 1;
                emit(i);
                block.regnum = tblA;
                return;
            }
            else if (e is UnOpExpr)
            {
                UnOpExpr uoe = e as UnOpExpr;
                switch (uoe.GetOperator())
                {
                case UnaryOperator.Not:
                    unOp("NOT", uoe.Rhs);
                    return;

                case UnaryOperator.Length:
                    unOp("LEN", uoe.Rhs);
                    return;

                case UnaryOperator.BitNot:
                    CallExpr ce = new CallExpr();
                    ce.Arguments.Add(uoe.Rhs);
                    ce.Base = new MemberExpr()
                    {
                        Base = new VariableExpression()
                        {
                            Var = new Variable()
                            {
                                Name = "bit", IsGlobal = true
                            }
                        },
                        Ident   = "bnot",
                        Indexer = ".",
                    };
                    DoExpr(ce);
                    return;

                case UnaryOperator.Negate:
                    unOp("UNM", uoe.Rhs);
                    return;

                case UnaryOperator.UnNegate:
                    ce = new CallExpr();
                    ce.Arguments.Add(uoe.Rhs);
                    ce.Base = new MemberExpr()
                    {
                        Base = new VariableExpression()
                        {
                            Var = new Variable()
                            {
                                Name = "math", IsGlobal = true
                            }
                        },
                        Ident   = "abs",
                        Indexer = ".",
                    };
                    DoExpr(ce);
                    return;

                case UnaryOperator.NONE:
                default:
                    throw new Exception("Unknown unary operator '" + uoe.Op + "'");
                }
            }
            else if (e is VarargExpr)
            {
                if (block.Chunk.Vararg == 0)
                {
                    throw new LuaSourceException(0, 0, "Cannot use varargs (...) outside of a vararg function");
                }
                Instruction i = new Instruction("VARARG");
                i.A = block.getreg();
                if (setVar)
                {
                    i.B = setVarLhsCount == -1 ? 0 : 1 + setVarLhsCount;
                }
                else
                {
                    i.B = 0;
                }
                emit(i);
                return;
            }
            else if (e is VariableExpression)
            {
                VariableExpression ve = e as VariableExpression;
                if (ve.Var.IsGlobal == false)
                { // local
                    if (setVar)
                    {
                        //Instruction i = new Instruction("move");
                        //i.B = block.V[ve.Var.Name]; // moved into here
                        //i.A = block.getreg(); // from here
                        //emit(i);

                        int _TMP_001_ = block.V[ve.Var.Name]; // Should probably just add a Check method in Var2Reg
                        block.CheckLocalName(ve.Var.Name);
                    }
                    else
                    {
                        Instruction i = new Instruction("move");
                        i.B = block.V[ve.Var.Name]; // moved into here
                        i.A = block.getreg();       // from here
                        emit(i);
                    }
                }
                else
                { // global
                    Instruction i = null;
                    if (setVar)
                    {
                        i   = new Instruction("setglobal");
                        i.A = block.regnum - 1; // ret
                    }
                    else
                    {
                        i   = new Instruction("getglobal");
                        i.A = block.getreg(); // ret
                    }

                    i.Bx = block.K[ve.Var.Name]; // const
                    emit(i);
                }
                return;
            }

            throw new NotImplementedException(e.GetType().Name + " is not implemented");
        }
コード例 #15
0
ファイル: Parser.cs プロジェクト: iamjuarez/SharpLua
        Expression ParseSuffixedExpr(Scope scope, bool onlyDotColon = false)
        {
            // base primary expression
            Expression prim = ParsePrimaryExpr(scope);

            while (true)
            {
                if (tok.IsSymbol('.') || tok.IsSymbol(':'))
                {
                    string symb = tok.Get().Data; // '.' or ':'
                    // TODO: should we allow keywords?
                    if (!tok.Is(TokenType.Ident))
                    {
                        error("<Ident> expected");
                    }

                    Token      id = tok.Get();
                    MemberExpr m  = new MemberExpr();
                    m.Base    = prim;
                    m.Indexer = symb;
                    m.Ident   = id.Data;

                    prim = m;
                }
                else if (!onlyDotColon && tok.ConsumeSymbol('['))
                {
                    Expression ex = ParseExpr(scope);

                    if (!tok.ConsumeSymbol(']'))
                    {
                        error("']' expected");
                    }

                    IndexExpr i = new IndexExpr();
                    i.Base  = prim;
                    i.Index = ex;

                    prim = i;
                }
                else if (!onlyDotColon && tok.ConsumeSymbol('('))
                {
                    List <Expression> args = new List <Expression>();
                    while (!tok.ConsumeSymbol(')'))
                    {
                        Expression ex = ParseExpr(scope);

                        args.Add(ex);
                        if (!tok.ConsumeSymbol(','))
                        {
                            if (tok.ConsumeSymbol(')'))
                            {
                                break;
                            }
                            else
                            {
                                error("')' expected");
                            }
                        }
                    }
                    CallExpr c = new CallExpr();
                    c.Base      = prim;
                    c.Arguments = args;

                    prim = c;
                }
                else if (!onlyDotColon &&
                         (tok.Is(TokenType.SingleQuoteString) ||
                          tok.Is(TokenType.DoubleQuoteString) ||
                          tok.Is(TokenType.LongString)))
                {
                    //string call

                    StringCallExpr e = new StringCallExpr();
                    e.Base      = prim;
                    e.Arguments = new List <Expression> {
                        new StringExpr(tok.Peek().Data)
                        {
                            StringType = tok.Peek().Type
                        }
                    };
                    tok.Get();
                    prim = e;
                }
                else if (!onlyDotColon && tok.IsSymbol('{'))
                {
                    // table call
                    Expression ex = ParseExpr(scope);

                    TableCallExpr t = new TableCallExpr();
                    t.Base      = prim;
                    t.Arguments = new List <Expression> {
                        ex
                    };

                    prim = t;
                }
                else
                {
                    break;
                }
            }
            return(prim);
        }