string fromTokens(List<Token> tokens, Scope s)
 {
     StringBuilder sb = new StringBuilder();
     foreach (Token t in tokens)
         sb.Append(fromToken(t, s));
     return sb.ToString();
 }
        string fromToken(Token t, Scope s)
        {
            StringBuilder sb = new StringBuilder();
            int cnt = 0;
            bool shortComment = false;
            int i = 0;
            foreach (Token t2 in t.Leading)
            {
                if (t2.Type == TokenType.LongComment
                    || t2.Type == TokenType.ShortComment
                    || t2.Type == TokenType.DocumentationComment)
                {
                    sb.Append(t2.Data);
                    cnt++;
                    if (t2.Type == TokenType.ShortComment || t2.Type == TokenType.DocumentationComment || (t.Leading.Count >= i + 1 && (t.Leading[i + 1].Type == TokenType.WhitespaceR || t.Leading[i + 1].Type == TokenType.WhitespaceN)))
                    {
                        shortComment = true;
                        sb.Append(options.EOL);
                    }
                }
                i++;
            }
            if (cnt > 0)
            {
                if (shortComment && (sb[sb.Length - 1] != '\r' || sb[sb.Length - 1] != '\n'))
                {
                    sb.Append(options.EOL);
                    sb.Append(writeIndent());
                }
                else
                {
                    sb.Insert(0, " ");
                    sb.Append(" ");
                }
            }

            if (t.Type == TokenType.DoubleQuoteString)
                sb.Append("\"" + t.Data + "\"");
            else if (t.Type == TokenType.SingleQuoteString)
                sb.Append("'" + t.Data + "'");
            else if (t.Type == TokenType.Ident)
            {
                Variable v = s.GetOldVariable(t.Data);
                if (v != null)
                    sb.Append(v.Name);
                else
                    sb.Append(t.Data);
            }
            else
                sb.Append(t.Data);


            if (t.FollowingEoSToken != null && t.FollowingEoSToken.Type == TokenType.EndOfStream)
                sb.Append(fromToken(t.FollowingEoSToken, s));
            return sb.ToString();
        }
Exemple #3
0
        AnonymousFunctionExpr ParseExprFunctionArgsAndBody(Scope scope)
        {
            AnonymousFunctionExpr func = new AnonymousFunctionExpr();
            func.Scope = new Scope(scope);

            if (reader.ConsumeSymbol('(') == false)
                error("'(' expected");

            // arg list
            List<Variable> arglist = new List<Variable>();
            bool isVarArg = false;
            while (reader.ConsumeSymbol(')') == false)
            {
                if (reader.Is(TokenType.Ident))
                {
                    Variable arg = new Variable();
                    arg.Name = reader.Get().Data;
                    func.Scope.AddLocal(arg);
                    arglist.Add(arg);
                    if (!reader.ConsumeSymbol(','))
                    {
                        if (reader.ConsumeSymbol(')'))
                            break;
                        else
                            error("')' expected");
                        break;
                    }
                }
                else if (reader.ConsumeSymbol("..."))
                {
                    isVarArg = true;
                    if (!reader.ConsumeSymbol(')'))
                        error("'...' must be the last argument of a function");
                    break;
                }
                else
                {
                    error("Argument name or '...' expected");
                    break;
                }
            }

            // body
            List<Statement> body = ParseStatementList(func.Scope);
            // end
            if (!reader.ConsumeKeyword("end"))
                error("'end' expected after function body");

            //nodeFunc.AstType = AstType.Function;
            func.Arguments = arglist;
            func.Body = body;
            func.IsVararg = isVarArg;

            return func;
        }
        string fromToken(Token t, Scope s)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < t.Leading.Count; i++)
            {
                Token t2 = t.Leading[i];
                if (t2.Type == TokenType.WhitespaceTab && options.TabsToSpaces)
                    sb.Append(options.Tab);
                else if (t2.Type == TokenType.WhitespaceR || t2.Type == TokenType.WhitespaceN)
                {
                    if (options.ConvertNewLines)
                    {
                        string nLine = options.EOL;
                        if (t2.Type == TokenType.WhitespaceR && t.Leading.Count > i + 1 && t.Leading[i + 1].Type == TokenType.WhitespaceN)
                        {
                            // \r\n new line
                            i++;
                            sb.Append(options.EOL);
                        }
                        else
                            // \n or \r new line
                            sb.Append(nLine);
                    }
                    else
                        sb.Append(t2.Data);
                }
                else
                    sb.Append(t2.Data);
            }
            if (t.Type == TokenType.DoubleQuoteString)
                sb.Append("\"" + t.Data + "\"");
            else if (t.Type == TokenType.SingleQuoteString)
                sb.Append("'" + t.Data + "'");
            else if (t.Type == TokenType.Ident)
            {
                Variable v = s.GetOldVariable(t.Data);
                if (v != null)
                    sb.Append(v.Name);
                else
                    sb.Append(t.Data);
            }
            else
                sb.Append(t.Data);


            if (t.FollowingEoSToken != null && t.FollowingEoSToken.Type == TokenType.EndOfStream)
                sb.Append(fromToken(t.FollowingEoSToken, s));
            return sb.ToString();
        }
        internal string DoExpr(Expression e, Scope s)
        {
            int startP = index;
            index += e.ParenCount;

            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(fromToken(tok[index++], s)); // <end>

                ret = sb.ToString();
            }
            else if (e is BinOpExpr)
            {
                //int i = 0;
                string left = DoExpr((e as BinOpExpr).Lhs, s);
                string op = fromToken(tok[index++], s);
                string right = DoExpr((e as BinOpExpr).Rhs, 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, s) // <base>
                          + fromToken(tok[index++], s)); // '('
                for (int i = 0; i < c.Arguments.Count; i++)
                {
                    sb.Append(DoExpr(c.Arguments[i], 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, s), DoExpr(sc.Arguments[0], s));
            }
            else if (e is TableCallExpr)
            {
                TableCallExpr sc = e as TableCallExpr;
                ret = string.Format("{0} {1}", DoExpr(sc.Base, s), DoExpr(sc.Arguments[0], s));
            }
            else if (e is IndexExpr)
            {
                IndexExpr i = e as IndexExpr;
                ret = string.Format("{0}{1}{2}{3}", DoExpr(i.Base, s), fromToken(tok[index++], s), DoExpr(i.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], 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, s)
                    + fromToken(tok[index++], s)
                    + " "
                    + fromToken(tok[index++], s)
                    + " "
                    + DoExpr(t.Value, s);
            }
            else if (e is MemberExpr)
            {
                MemberExpr m = e as MemberExpr;
                ret = DoExpr(m.Base, 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, s); // value
            }
            else if (e is TableConstructorExpr)
            {
                TableConstructorExpr t = e as TableConstructorExpr;
                StringBuilder sb = new StringBuilder();
                sb.Append(fromToken(tok[index++], s)); // '{'
                sb.Append(" ");
                bool needNewLines = false;
                if (t.EntryList.Count > 4)
                    needNewLines = true;
                for (int i = 0; i < t.EntryList.Count; i++)
                {
                    string tmp = DoExpr(t.EntryList[i], s);
                    if (tmp.Length > 10)
                        needNewLines = true;
                    sb.Append(tmp);
                    
                    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, s);
            }
            else if (e is TableConstructorValueExpr)
                ret = DoExpr(((TableConstructorValueExpr)e).Value, 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");
        }
Exemple #6
0
 public Chunk(Scope s)
 {
     Scope = s;
 }
        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)); // ')'

                sb.Append(DoChunk(f.Body));

                //sb.Append(fromToken(tok[tok.Count - 1], s)); // <end>
                string str = fromToken(tok[tok.Count - 1], s);
                sb.Append(str);

                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(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)); // ','
                }
                if (ife.IsVararg)
                    sb.Append(fromToken(tok[index++], s)); // '...'
                sb.Append(fromToken(tok[index++], s)); // '|'
                sb.Append(fromToken(tok[index++], s)); // '->'
                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)); // ','
                }
                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 += fromToken(tok[index++], s); // '='
                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)); // '{'
                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(fromToken(tok[index++], s)); // '}'
                ret = sb.ToString();
            }
            else if (e is UnOpExpr)
            {
                string sc = fromToken(tok[index++], s);
                ret = sc + DoExpr((e as UnOpExpr).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");
        }
Exemple #8
0
 public Scope(Scope parent)
 {
     Parent = parent;
     Parent.Children.Add(this);
 }
Exemple #9
0
        Statement ParseStatement(Scope scope)
        {
            int startP = reader.p;
            int startLine = reader.Peek().Line;
            Statement stat = null;
            // print(tok.Peek().Print())
            if (reader.ConsumeKeyword("if"))
            {
                //setup
                IfStmt _if = new IfStmt();

                //clauses
                do
                {
                    int sP = reader.p;
                    Expression nodeCond = ParseExpr(scope);

                    if (!reader.ConsumeKeyword("then"))
                        error("'then' expected");

                    List<Statement> nodeBody = ParseStatementList(scope);

                    List<Token> range = new List<Token>();
                    range.Add(reader.tokens[sP - 1]);
                    range.AddRange(reader.Range(sP, reader.p));

                    _if.Clauses.Add(new ElseIfStmt(scope)
                    {
                        Condition = nodeCond,
                        Body = nodeBody,
                        ScannedTokens = range
                    });
                }
                while (reader.ConsumeKeyword("elseif"));

                // else clause
                if (reader.ConsumeKeyword("else"))
                {
                    int sP = reader.p;
                    List<Statement> nodeBody = ParseStatementList(scope);
                    List<Token> range = new List<Token>();
                    range.Add(reader.tokens[sP - 1]);
                    range.AddRange(reader.Range(sP, reader.p));

                    _if.Clauses.Add(new ElseStmt(scope)
                    {
                        Body = nodeBody,
                        ScannedTokens = range
                    });
                }

                // end
                if (!reader.ConsumeKeyword("end"))
                    error("'end' expected");

                stat = _if;
            }
            else if (reader.ConsumeKeyword("while"))
            {
                WhileStatement w = new WhileStatement(scope);

                // condition
                Expression nodeCond = ParseExpr(scope);

                // do
                if (!reader.ConsumeKeyword("do"))
                    error("'do' expected");

                // body
                List<Statement> body = ParseStatementList(scope);

                //end
                if (!reader.ConsumeKeyword("end"))
                    error("'end' expected");


                // return
                w.Condition = nodeCond;
                w.Body = body;
                stat = w;
            }
            else if (reader.ConsumeKeyword("do"))
            {
                // do block
                List<Statement> b = ParseStatementList(scope);

                if (!reader.ConsumeKeyword("end"))
                    error("'end' expected");

                stat = new DoStatement(scope) { Body = b };
            }
            else if (reader.ConsumeKeyword("for"))
            {
                //for block
                if (!reader.Is(TokenType.Ident))
                    error("<ident> expected");

                Token baseVarName = reader.Get();
                if (reader.ConsumeSymbol('='))
                {
                    //numeric for
                    NumericForStatement forL = new NumericForStatement(scope);
                    Variable forVar = new Variable() { Name = baseVarName.Data };
                    forL.Scope.AddLocal(forVar);

                    Expression startEx = ParseExpr(scope);

                    if (!reader.ConsumeSymbol(','))
                        error("',' expected");

                    Expression endEx = ParseExpr(scope);

                    Expression stepEx = null;
                    if (reader.ConsumeSymbol(','))
                    {
                        stepEx = ParseExpr(scope);
                    }
                    if (!reader.ConsumeKeyword("do"))
                        error("'do' expected");


                    List<Statement> body = ParseStatementList(forL.Scope);

                    if (!reader.ConsumeKeyword("end"))
                        error("'end' expected");


                    forL.Variable = forVar;
                    forL.Start = startEx;
                    forL.End = endEx;
                    forL.Step = stepEx;
                    forL.Body = body;
                    stat = forL;
                }
                else
                {
                    // generic for
                    GenericForStatement forL = new GenericForStatement(scope);

                    List<Variable> varList = new List<Variable> { forL.Scope.CreateLocal(baseVarName.Data) };
                    while (reader.ConsumeSymbol(','))
                    {
                        if (!reader.Is(TokenType.Ident))
                            error("for variable expected");

                        varList.Add(forL.Scope.CreateLocal(reader.Get().Data));
                    }
                    if (!reader.ConsumeKeyword("in"))
                        error("'in' expected");

                    List<Expression> generators = new List<Expression>();
                    Expression first = ParseExpr(scope);

                    generators.Add(first);
                    while (reader.ConsumeSymbol(','))
                    {
                        Expression gen = ParseExpr(scope);
                        generators.Add(gen);
                    }
                    if (!reader.ConsumeKeyword("do"))
                        error("'do' expected");

                    List<Statement> body = ParseStatementList(forL.Scope);

                    if (!reader.ConsumeKeyword("end"))
                        error("'end' expected");

                    forL.VariableList = varList;
                    forL.Generators = generators;
                    forL.Body = body;
                    stat = forL;
                }
            }
            else if (reader.ConsumeKeyword("repeat"))
            {
                List<Statement> body = ParseStatementList(scope);

                if (!reader.ConsumeKeyword("until"))
                    error("'until' expected");

                Expression cond = ParseExpr(scope);

                RepeatStatement r = new RepeatStatement(scope);
                r.Condition = cond;
                r.Body = body;
                stat = r;
            }
            else if (reader.ConsumeKeyword("function"))
            {
                if (!reader.Is(TokenType.Ident))
                    error("function name expected");

                Expression name = ParseSuffixedExpr(scope, true);
                // true: only dots and colons

                FunctionStatement func = ParseFunctionArgsAndBody(scope);

                func.IsLocal = false;
                func.Name = name;
                stat = func;
            }
            else if (reader.ConsumeKeyword("local"))
            {
                if (reader.Is(TokenType.Ident))
                {
                    List<string> varList = new List<string> { reader.Get().Data };
                    while (reader.ConsumeSymbol(','))
                    {
                        if (!reader.Is(TokenType.Ident))
                            error("local variable name expected");
                        varList.Add(reader.Get().Data);
                    }

                    List<Expression> initList = new List<Expression>();
                    if (reader.ConsumeSymbol('='))
                    {
                        do
                        {
                            Expression ex = ParseExpr(scope);
                            initList.Add(ex);
                        } while (reader.ConsumeSymbol(','));
                    }

                    //now patch var list
                    //we can't do this before getting the init list, because the init list does not
                    //have the locals themselves in scope.
                    List<Expression> newVarList = new List<Expression>();
                    for (int i = 0; i < varList.Count; i++)
                    {
                        Variable x = scope.CreateLocal(varList[i]);
                        newVarList.Add(new VariableExpression { Var = x });
                    }

                    AssignmentStatement l = new AssignmentStatement();
                    l.Lhs = newVarList;
                    l.Rhs = initList;
                    l.IsLocal = true;
                    stat = l;
                }
                else if (reader.ConsumeKeyword("function"))
                {
                    if (!reader.Is(TokenType.Ident))
                        error("Function name expected");
                    string name = reader.Get().Data;
                    Variable localVar = scope.CreateLocal(name);

                    FunctionStatement func = ParseFunctionArgsAndBody(scope);

                    func.Name = new VariableExpression { Var = localVar };
                    func.IsLocal = true;
                    stat = func;
                }
                else
                    error("local variable or function definition expected");
            }
#if !VANILLA_LUA
            else if (reader.ConsumeSymbol("::"))
            {
                if (!reader.Is(TokenType.Ident))
                    error("label name expected");

                string label = reader.Get().Data;
                if (!reader.ConsumeSymbol("::"))
                    error("'::' expected");

                LabelStatement l = new LabelStatement();
                l.Label = label;
                stat = l;
            }
#endif
            else if (reader.ConsumeKeyword("return"))
            {
                List<Expression> exprList = new List<Expression>();
                if (!reader.IsKeyword("end") && !reader.IsEof())
                {
                    Expression firstEx = ParseExpr(scope);
                    exprList.Add(firstEx);
                    while (reader.ConsumeSymbol(','))
                    {
                        Expression ex = ParseExpr(scope);
                        exprList.Add(ex);
                    }
                }
                ReturnStatement r = new ReturnStatement();
                r.Arguments = exprList;
                stat = r;
            }
            else if (reader.ConsumeKeyword("break"))
            {
                stat = new BreakStatement();
            }
            else if (reader.ConsumeKeyword("continue"))
            {
                stat = new ContinueStatement();
            }
#if !VANILLA_LUA
            else if (reader.ConsumeKeyword("goto"))
            {
                if (!reader.Is(TokenType.Ident))
                    error("label expected");

                string label = reader.Get().Data;
                GotoStatement g = new GotoStatement();
                g.Label = label;
                stat = g;
            }
            else if (reader.ConsumeKeyword("using"))
            {
                // using <a, b = 1, x()> do <statements> end
                UsingStatement us = new UsingStatement(scope);
                us.Scope = new Scope(scope);

                List<Expression> lhs = new List<Expression> { ParseExpr(us.Scope) };
                while (reader.ConsumeSymbol(','))
                {
                    lhs.Add(ParseSuffixedExpr(us.Scope, true));
                }

                // equals
                if (!reader.ConsumeSymbol('='))
                    error("'=' expected");

                //rhs
                List<Expression> rhs = new List<Expression>();
                rhs.Add(ParseExpr(us.Scope));
                while (reader.ConsumeSymbol(','))
                {
                    rhs.Add(ParseExpr(scope));
                }

                AssignmentStatement a = new AssignmentStatement();
                a.Lhs = lhs;
                a.Rhs = rhs;
                a.IsLocal = true;

                if (!reader.ConsumeKeyword("do"))
                    error("'do' expected");

                List<Statement> block = ParseStatementList(us.Scope);

                if (!reader.ConsumeKeyword("end"))
                    error("'end' expected");

                us.Vars = a;
                us.Body = block;
                stat = us;
            }
#endif
            else
            {
                // statementParseExpr
                Expression suffixed = ParseSuffixedExpr(scope);
                // assignment or call?
                if (reader.IsSymbol(',') || reader.IsSymbol('='))
                {
                    // check that it was not parenthesized, making it not an lvalue
                    if (suffixed.ParenCount > 0)
                        error("Can not assign to parenthesized expression, it is not an lvalue");

                    // more processing needed
                    List<Expression> lhs = new List<Expression> { suffixed };
                    while (reader.ConsumeSymbol(','))
                    {
                        lhs.Add(ParseSuffixedExpr(scope));
                    }

                    // equals
                    if (!reader.ConsumeSymbol('='))
                        error("'=' expected");

                    //rhs
                    List<Expression> rhs = new List<Expression>();
                    rhs.Add(ParseExpr(scope));
                    while (reader.ConsumeSymbol(','))
                    {
                        rhs.Add(ParseExpr(scope));
                    }

                    AssignmentStatement a = new AssignmentStatement();
                    a.Lhs = lhs;
                    a.Rhs = rhs;
                    stat = a;
                }
#if !VANILLA_LUA
                else if (isAugmentedAssignment(reader.Peek()))
                {
                    AugmentedAssignmentStatement aas = new AugmentedAssignmentStatement();
                    Expression left = suffixed;
                    Expression right = null;
                    string augmentedOp = reader.Get().Data;
                    right = ParseExpr(scope);
                    BinOpExpr nRight = new BinOpExpr();
                    nRight.Lhs = left;
                    nRight.Op = augmentedOp.Substring(0, augmentedOp.Length - 1); // strip the '='
                    nRight.Rhs = right;

                    aas.Lhs = new List<Expression> { left };
                    aas.Rhs = new List<Expression> { nRight };
                    stat = aas;
                }
#endif
                else if (suffixed is CallExpr ||
                       suffixed is TableCallExpr ||
                       suffixed is StringCallExpr)
                {
                    //it's a call statement
                    CallStatement c = new CallStatement();
                    c.Expression = suffixed;
                    stat = c;
                }
                else
                    error("assignment statement expected");
            }

            stat.ScannedTokens = reader.Range(startP, reader.p);
            if (reader.Peek().Data == ";" && reader.Peek().Type == TokenType.Symbol)
            {
                stat.HasSemicolon = true;
                stat.SemicolonToken = reader.Get();
            }
            if (stat.Scope == null)
                stat.Scope = scope;
            stat.LineNumber = startLine;
            return stat;
        }
Exemple #10
0
 Expression ParseExpr(Scope scope)
 {
     return ParseSubExpr(scope, 0);
 }
Exemple #11
0
        Expression ParseSubExpr(Scope scope, int level)
        {
            // base item, possibly with unop prefix
            Expression exp = null;
            if (isUnOp(reader.Peek().Data) &&
                (reader.Peek().Type == TokenType.Symbol || reader.Peek().Type == TokenType.Keyword))
            {
                string op = reader.Get().Data;
                exp = ParseSubExpr(scope, unopprio);
                exp = new UnOpExpr { Rhs = exp, Op = op };
            }
            else
                exp = ParseSimpleExpr(scope);

            if (exp is InlineFunctionExpression)
                return exp; // inline functions cannot have any extra parts

            // next items in chain
            while (true)
            {
                priority_ prio = getpriority(reader.Peek().Data);
                if (prio != null && prio.l > level)
                {
                    string op = reader.Get().Data;
                    Expression rhs = ParseSubExpr(scope, prio.r);

                    BinOpExpr binOpExpr = new BinOpExpr();
                    binOpExpr.Lhs = exp;
                    binOpExpr.Op = op;
                    binOpExpr.Rhs = rhs;
                    exp = binOpExpr;
                }
                else
                    break;
            }
            return exp;
        }
Exemple #12
0
        Expression ParseSimpleExpr(Scope scope)
        {
            if (reader.Is(TokenType.Number))
                return new NumberExpr { Value = reader.Get().Data };
            else if (reader.Is(TokenType.DoubleQuoteString) || reader.Is(TokenType.SingleQuoteString) || reader.Is(TokenType.LongString))
            {
                StringExpr s = new StringExpr
                {
                    Value = reader.Peek().Data,
                    StringType = reader.Peek().Type
                };
                reader.Get();
                return s;
            }
            else if (reader.ConsumeKeyword("nil"))
                return new NilExpr();
            else if (reader.IsKeyword("false") || reader.IsKeyword("true"))
                return new BoolExpr { Value = reader.Get().Data == "true" };
            else if (reader.ConsumeSymbol("..."))
                return new VarargExpr();
            else if (reader.ConsumeSymbol('{'))
            {
                TableConstructorExpr v = new TableConstructorExpr();
                while (true)
                {
                    if (reader.IsSymbol('['))
                    {
                        // key
                        reader.Get(); // eat '['
                        Expression key = ParseExpr(scope);

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

                        if (!reader.ConsumeSymbol('='))
                        {
                            error("'=' Expected");
                            break;
                        }

                        Expression value = ParseExpr(scope);

                        v.EntryList.Add(new TableConstructorKeyExpr
                        {
                            Key = key,
                            Value = value,
                        });
                    }
                    else if (reader.Is(TokenType.Ident))
                    {
                        // value or key
                        Token lookahead = reader.Peek(1);
                        if (lookahead.Type == TokenType.Symbol && lookahead.Data == "=")
                        {
                            // we are a key
                            Token key = reader.Get();
                            if (!reader.ConsumeSymbol('='))
                                error("'=' Expected");

                            Expression value = ParseExpr(scope);

                            v.EntryList.Add(new TableConstructorStringKeyExpr
                            {
                                Key = key.Data,
                                Value = value,
                            });
                        }
                        else
                        {
                            // we are a value
                            Expression val = ParseExpr(scope);

                            v.EntryList.Add(new TableConstructorValueExpr
                            {
                                Value = val
                            });

                        }
                    }
#if !VANILLA_LUA
                    else if (reader.ConsumeKeyword("function"))
                    {
                        if (reader.Peek().Type != TokenType.Ident)
                            error("function name expected");
                        string name = reader.Get().Data;
                        FunctionStatement fs = ParseFunctionArgsAndBody(scope);
                        fs.IsLocal = false;
                        fs.Name = new StringExpr(name);
                        v.EntryList.Add(new TableConstructorNamedFunctionExpr
                        {
                            Value = fs
                        });
                    }
#endif
                    else if (reader.ConsumeSymbol('}'))
                        break;
                    else
                    {
                        //value
                        Expression value = ParseExpr(scope);
                        v.EntryList.Add(new TableConstructorValueExpr
                        {
                            Value = value
                        });
                    }

                    if (reader.ConsumeSymbol(';') || reader.ConsumeSymbol(','))
                    {
                        // I could have used just an empty statement (';') here, instead of { }
                        // but that leaves a warning, which clutters up the output
                        // other than that, all is good
                    }
                    else if (reader.ConsumeSymbol('}'))
                        break;
                    else
                    {
                        error("'}' or table entry Expected");
                        break;
                    }
                }
                return v;
            }
            else if (reader.ConsumeKeyword("function"))
            {
                AnonymousFunctionExpr func = ParseExprFunctionArgsAndBody(scope);
                //func.IsLocal = true;
                return func;
            }
#if !VANILLA_LUA
            else if (reader.ConsumeSymbol('|'))
            {
                // inline function... |<arg list>| -> <expr>, <expr>
                InlineFunctionExpression func = new InlineFunctionExpression();
                func.Scope = new Scope(scope);
                // arg list
                List<Variable> arglist = new List<Variable>();
                bool isVarArg = false;
                while (reader.ConsumeSymbol('|') == false)
                {
                    if (reader.Is(TokenType.Ident))
                    {
                        Variable arg = new Variable();
                        arg.Name = reader.Get().Data;
                        func.Scope.AddLocal(arg);
                        arglist.Add(arg);
                        if (!reader.ConsumeSymbol(','))
                        {
                            if (reader.ConsumeSymbol('|'))
                            {
                                break;
                            }
                            else
                            {
                                error("'|' expected");
                                break;
                            }
                        }
                    }
                    else if (reader.ConsumeSymbol("..."))
                    {
                        isVarArg = true;
                        if (!reader.ConsumeSymbol('|'))
                            error("'...' must be the last argument of a function");
                        break;
                    }
                    else
                    {
                        error("Argument name or '...' expected");
                        break;
                    }
                }
                if (!reader.ConsumeSymbol("->"))
                    error("'->' expected");
                // body
                List<Expression> body = new List<Expression> { ParseExpr(func.Scope) };
                while (reader.ConsumeSymbol(','))
                    body.Add(ParseExpr(func.Scope));
                // end

                //nodeFunc.AstType = AstType.Function;
                func.Arguments = arglist;
                func.Expressions = body;
                func.IsVararg = isVarArg;

                return func;
            }
#endif
            else
                return ParseSuffixedExpr(scope);
        }
Exemple #13
0
        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;
        }
Exemple #14
0
        Expression ParsePrimaryExpr(Scope c)
        {
            //Console.WriteLine(tok.Peek().Type + " " + tok.Peek().Data);
            if (reader.ConsumeSymbol('('))
            {
                Expression ex = ParseExpr(c);
                if (!reader.ConsumeSymbol(')'))
                    error("')' expected");

                // save the information about parenthesized expressions somewhere
                ex.ParenCount = ex.ParenCount + 1;
                return ex;
            }
            else if (reader.Is(TokenType.Ident))
            {
                Token id = reader.Get();
                VariableExpression v = new VariableExpression();
                Variable var = c.GetLocal(id.Data);
                if (var == null)
                {
                    var = c.GetGlobal(id.Data);
                    if (var == null)
                    {
                        v.Var = c.CreateGlobal(id.Data);
                    }
                    else
                    {
                        v.Var = var;
                        v.Var.References++;
                    }
                }
                else
                {
                    v.Var = var;
                    v.Var.References++;
                }
                return v;
            }
            else
                error("primary expression expected");

            return null; // satisfy the C# compiler, but this will never happen
        }
Exemple #15
0
 public Chunk Parse()
 {
     Scope s = new Scope();
     return new Chunk
     {
         Body = ParseStatementList(s),
         Scope = s,
         ScannedTokens = reader.tokens
     };
 }
Exemple #16
0
        List<Statement> ParseStatementList(Scope scope)
        {
            List<Statement> c = new List<Statement>();

            while (!isClosing(reader.Peek().Data) && !reader.IsEof())
            {
                Statement nodeStatement = ParseStatement(scope);
                //stats[#stats+1] = nodeStatement
                c.Add(nodeStatement);
            }
            return c;
        }