예제 #1
0
파일: Parser.cs 프로젝트: hvp/Gemgine
        public static ScriptObject ParseChar(ParseState state)
        {
            var result = new GenericScriptObject("@type", "char", "@start", state.start, "@source", state);
            var token = "";

            state.Advance(); //skip opening '
            while (!state.AtEnd())
            {
                if (state.Next() == '\\')
                {
                    state.Advance();
                    if (state.Next() == 'n') token += "\n";
                    if (state.Next() == 't') token += "\t";
                    if (state.Next() == 'r') token += "\r";
                    else token += state.Next();
                }
                else if (state.Next() == '\'')
                {
                    result["@end"] = state.start;
                    result["@token"] = token;
                    state.Advance();
                    return result;
                }
                else
                {
                    token += state.Next();
                    state.Advance();
                }
            }

            result["@end"] = state.start;
            result["@token"] = token;
            return result;
        }
예제 #2
0
파일: Parser.cs 프로젝트: Blecki/BMud
 public static int ParseComment(ParseState state)
 {
     var start = state.start;
     state.Advance(2);
     while (!state.AtEnd() && !state.MatchNext("*/")) state.Advance();
     state.Advance(2);
     return state.start - start;
 }
예제 #3
0
파일: Parser.cs 프로젝트: Blecki/BMud
        public static ParseNode ParseExpression(ParseState state)
        {
            ParseNode result = null;
            var prefix = ParsePrefix(state);
            if (state.Next() == '[') //Dictionary Entry
            {
                result = ParseNode(state, "[", "]");
                result.type = NodeType.DictionaryEntry;
            }
            else if (state.Next() == '"')
            {
                result = ParseStringExpression(state);
                //if (prefix == Prefix.Quote)
                //    result = new ParseNode(NodeType.String, result.start, state)
                //    {
                //        token = state.source.Substring(result.start + 1, result.end - result.start - 2)
                //    };
            }
            else if (state.Next() == '(')
            {
                result = ParseNode(state);
            }
            else if ("-0123456789".Contains(state.Next()))
            {
                result = ParseNumber(state);
            }
            //else if (!state.AtEnd() && " \t\r\n".Contains(state.Next())) //prefix followed by space??
            //{
            //    if (prefix != Prefix.None) //rewind prefix
            //    {
            //        prefix = Prefix.None;
            //        state.start -= 1;
            //    }
            //    result = ParseToken(state);
            //}
            else
            {
                result = ParseToken(state);
            }

            if (state.Next() == '.' || state.Next() == ':')
            {
                var final_result = new ParseNode(NodeType.MemberAccess, result.start, state);
                final_result.childNodes.Add(result);
                final_result.token = new String(state.Next(), 1);
                state.Advance();
                final_result.childNodes.Add(ParseExpression(state));
                result = final_result;
            }

            result.prefix = prefix;
            if (!PrefixCheck.CheckPrefix(result))
                throw new ParseError("Illegal prefix on expression of type " + result.type, state.currentLine);
            return result;
        }
예제 #4
0
파일: Parser.cs 프로젝트: Blecki/BMud
 public static void DevourWhitespace(ParseState state)
 {
     while (!state.AtEnd() && " \t\r\n".Contains(state.Next())) state.Advance();
 }
예제 #5
0
파일: Parser.cs 프로젝트: Blecki/BMud
        public static ParseNode ParseStringExpression(ParseState state, bool isRoot = false)
        {
            var result = new ParseNode(NodeType.StringExpression, state.start, state);
            if (!isRoot) state.Advance(); //Skip opening quote
            string piece = "";
            int piece_start = state.start;
            while (!state.AtEnd())
            {
                if (state.Next() == '(')
                {
                    if (piece.Length > 0) result.childNodes.Add(new ParseNode(NodeType.String, piece_start, state) {
                        token = state.source.Substring(piece_start, state.start - piece_start) });
                    result.childNodes.Add(ParseNode(state));
                    piece = "";
                }
                else if (state.Next() == '\\')
                {
                    if (piece.Length == 0) piece_start = state.start;
                    state.Advance(); //skip the slash.
                    piece += "\\" + state.Next();
                    state.Advance();
                }
                else if (!isRoot && state.Next() == '"')
                {
                    if (piece.Length > 0) result.childNodes.Add(new ParseNode(NodeType.String, piece_start, state) {
                        token = state.source.Substring(piece_start, state.start - piece_start) });
                    state.Advance();
                    result.end = state.start;
                    if (result.childNodes.Count == 1 && result.childNodes[0].type == NodeType.String)
                        return result.childNodes[0];
                    return result;
                }
                else
                {
                    if (piece.Length == 0) piece_start = state.start;
                    piece += state.Next();
                    state.Advance();
                }

            }

            if (isRoot)
            {
                if (piece.Length > 0) result.childNodes.Add(new ParseNode(NodeType.String, piece_start, state)
                {
                    token = state.source.Substring(piece_start, state.start - piece_start)
                });

                if (result.childNodes.Count == 1) return result.childNodes[0];
                return result;
            }

            throw new ParseError("Unexpected end of script inside string expression.", state.currentLine);
        }
예제 #6
0
파일: Parser.cs 프로젝트: Blecki/BMud
 public static ParseNode ParseToken(ParseState state)
 {
     var result = new ParseNode(NodeType.Token, state.start, state);
     while (!state.AtEnd() && !(" \t\r\n:.)]".Contains(state.Next()))) state.Advance();
     result.end = state.start;
     result.token = state.source.Substring(result.start, result.end - result.start);
     if (String.IsNullOrEmpty(result.token)) throw new ParseError("Empty token", state.currentLine);
     return result;
 }
예제 #7
0
파일: Parser.cs 프로젝트: Blecki/BMud
 public static Prefix ParsePrefix(ParseState state)
 {
     Prefix result = Prefix.None;
     if (state.Next() == '*')
         result = Prefix.Quote;
     else if (state.Next() == '^')
         result = Prefix.List;
     else if (state.Next() == '$')
         result = Prefix.Expand;
     else if (state.Next() == '#')
         result = Prefix.Lookup;
     else if (state.Next() == ':')
         result = Prefix.Evaluate;
     if (result != Prefix.None)
         state.Advance();
     return result;
 }
예제 #8
0
파일: Parser.cs 프로젝트: Blecki/BMud
        public static ParseNode ParseRoot(String script, String filename)
        {
            var commentFree = "";
            var state = new ParseState { start = 0, end = script.Length, source = script, filename = filename };
            while (!state.AtEnd())
            {
                if (state.MatchNext("/*"))
                    commentFree += (new String(' ',ParseComment(state)));
                else
                {
                    commentFree += state.Next();
                    state.Advance();
                }
            }

            return ParseStringExpression(new ParseState { start = 0, end = commentFree.Length, source = commentFree, filename = filename }, true);
        }
예제 #9
0
파일: Parser.cs 프로젝트: Blecki/BMud
 public static ParseNode ParseNode(ParseState state, String start = "(", String end = ")")
 {
     var result = new ParseNode(NodeType.Node, state.start, state);
     if (!state.MatchNext(start)) throw new ParseError("Expected " + start, state.currentLine);
     state.Advance(start.Length);
     while (!state.MatchNext(end))
     {
         DevourWhitespace(state);
         if (!state.MatchNext(end))
         {
             var expression = ParseExpression(state);
             if (expression.type == NodeType.MemberAccess) expression = ReorderMemberAccessNode(expression);
             result.childNodes.Add(expression);
         }
         DevourWhitespace(state);
     }
     state.Advance(end.Length);
     return result;
 }
예제 #10
0
파일: Parser.cs 프로젝트: Blecki/BMud
        public static ParseNode ParseNumber(ParseState state)
        {
            var result = new ParseNode(NodeType.Number, state.start, state);
            bool foundDot = false;

            while (!state.AtEnd())
            {
                if (state.Next() == '-')
                {
                    if (result.start != state.start) break;
                    state.Advance();
                    continue;
                }
                if (state.Next() >= '0' && state.Next() <= '9')
                {
                    state.Advance();
                    continue;
                }
                else if (state.Next() == '.')
                {
                    if (foundDot) break;
                    foundDot = true;
                    state.Advance();
                    continue;
                }
                break;
            }

            result.end = state.start;
            result.token = state.source.Substring(result.start, result.end - result.start);
            return result;
        }
예제 #11
0
파일: Parser.cs 프로젝트: hvp/Gemgine
 public static ScriptObject ParseNode(ParseState state, String start = "(", String end = ")")
 {
     var result = new GenericScriptObject("@type", "node", "@start", state.start, "@source", state);
     if (!state.MatchNext(start)) throw new ParseError("Expected " + start, state.currentLine);
     state.Advance(start.Length);
     while (!state.AtEnd() && !state.MatchNext(end))
     {
         DevourWhitespace(state);
         if (state.Next() == '}')
             return result;
         if (!state.AtEnd() && !state.MatchNext(end))
         {
             var expression = ParseExpression(state);
             if (isType(expression, "memberaccess")) expression = ReorderMemberAccessNode(expression);
             children(result).Add(expression);
         }
         DevourWhitespace(state);
     }
     if (end != null) state.Advance(end.Length);
     return result;
 }
예제 #12
0
        public static ScriptObject ParseStringExpression(ParseState state, bool isRoot = false)
        {
            var result = new GenericScriptObject("@type", "stringexpression", "@start", state.start, "@source", state);

            if (!isRoot)
            {
                state.Advance();          //Skip opening quote
            }
            string piece       = "";
            int    piece_start = state.start;

            while (!state.AtEnd())
            {
                if (state.Next() == '}' && piece.Length == 0)
                {
                    state.Advance(1);
                }
                else if (state.Next() == '(')
                {
                    if (piece.Length > 0)
                    {
                        children(result).Add(
                            new GenericScriptObject("@type", "string", "@start", piece_start, "@source", state,
                                                    "@token", state.source.Substring(piece_start, state.start - piece_start)));
                    }
                    children(result).Add(ParseNode(state));
                    piece = "";
                }
                else if (state.Next() == '\\')
                {
                    if (piece.Length == 0)
                    {
                        piece_start = state.start;
                    }
                    state.Advance(); //skip the slash.
                    piece += state.Next();
                    state.Advance();
                }
                else if (!isRoot && state.Next() == '"')
                {
                    if (piece.Length > 0)
                    {
                        children(result).Add(
                            new GenericScriptObject("@type", "string", "@start", piece_start, "@source", state,
                                                    "@token", state.source.Substring(piece_start, state.start - piece_start)));
                    }
                    state.Advance();
                    result["@end"] = state.start;
                    if (children(result).Count == 1 && isType(children(result)[0] as ScriptObject, "string"))
                    {
                        return(child(result, 0) as ScriptObject);
                    }
                    return(result);
                }
                else
                {
                    if (piece.Length == 0)
                    {
                        piece_start = state.start;
                    }
                    piece += state.Next();
                    state.Advance();
                }
            }

            if (isRoot)
            {
                if (piece.Length > 0)
                {
                    children(result).Add(new GenericScriptObject("@type", "string", "@start", piece_start,
                                                                 "@source", state, "@token", state.source.Substring(piece_start, state.start - piece_start)));
                }
                if (children(result).Count == 1)
                {
                    return(child(result, 0) as ScriptObject);
                }
                return(result);
            }

            throw new ParseError("Unexpected end of script inside string expression.", state.currentLine);
        }
예제 #13
0
파일: Parser.cs 프로젝트: hvp/Gemgine
 public static ScriptObject ParseToken(ParseState state)
 {
     var result = new GenericScriptObject("@type", "token", "@start", state.start, "@source", state);
     while (!state.AtEnd() && !(" \t\r\n:.)]}".Contains(state.Next()))) state.Advance();
     result["@end"] = state.start;
     result["@token"] = state.source.Substring(asInt(result["@start"]),
         asInt(result["@end"]) - asInt(result["@start"]));
     if (String.IsNullOrEmpty(result.gsp("@token"))) throw new ParseError("Empty token", state.currentLine);
     return result;
 }
예제 #14
0
파일: Parser.cs 프로젝트: hvp/Gemgine
        public static ScriptObject ParseStringExpression(ParseState state, bool isRoot = false)
        {
            var result = new GenericScriptObject("@type", "stringexpression", "@start", state.start, "@source", state);
            if (!isRoot) state.Advance(); //Skip opening quote
            string piece = "";
            int piece_start = state.start;
            while (!state.AtEnd())
            {
                if (state.Next() == '}' && piece.Length == 0)
                {
                    state.Advance(1);
                }
                else if (state.Next() == '(')
                {
                    if (piece.Length > 0) children(result).Add(
                        new GenericScriptObject("@type", "string", "@start", piece_start, "@source", state,
                            "@token", state.source.Substring(piece_start, state.start - piece_start)));
                    children(result).Add(ParseNode(state));
                    piece = "";
                }
                else if (state.Next() == '\\')
                {
                    if (piece.Length == 0) piece_start = state.start;
                    state.Advance(); //skip the slash.
                    piece += state.Next();
                    state.Advance();
                }
                else if (!isRoot && state.Next() == '"')
                {
                    if (piece.Length > 0) children(result).Add(
                        new GenericScriptObject("@type", "string", "@start", piece_start, "@source", state,
                            "@token", state.source.Substring(piece_start, state.start - piece_start)));
                    state.Advance();
                    result["@end"] = state.start;
                    if (children(result).Count == 1 && isType(children(result)[0] as ScriptObject, "string"))
                        return child(result, 0) as ScriptObject;
                    return result;
                }
                else
                {
                    if (piece.Length == 0) piece_start = state.start;
                    piece += state.Next();
                    state.Advance();
                }

            }

            if (isRoot)
            {
                if (piece.Length > 0) children(result).Add(new GenericScriptObject("@type", "string", "@start", piece_start,
                    "@source", state, "@token", state.source.Substring(piece_start, state.start - piece_start)));
                if (children(result).Count == 1) return child(result, 0) as ScriptObject;
                return result;
            }

            throw new ParseError("Unexpected end of script inside string expression.", state.currentLine);
        }
예제 #15
0
파일: Parser.cs 프로젝트: hvp/Gemgine
        public static ScriptObject ParseRoot(String script, String filename)
        {
            var commentFree = new StringBuilder();
            var state = new ParseState { start = 0, end = script.Length, source = script, filename = filename };
            while (!state.AtEnd())
            {
                if (state.MatchNext("/*"))
                    commentFree.Append(new String(' ',ParseComment(state)));
                else
                {
                    commentFree.Append(state.Next());
                    state.Advance();
                }
            }

            var r = ParseNode(
                new ParseState { start = 0, end = commentFree.Length, source = commentFree.ToString(), filename = filename },
                "", null);
            if (r._children.Count == 1) return r._child(0) as ScriptObject;
            r.SetProperty("@type", "root");
            return r;
        }
예제 #16
0
파일: Parser.cs 프로젝트: hvp/Gemgine
 public static String ParsePrefix(ParseState state)
 {
     var next = state.Next();
     if (next == '*' || next == '^' || next == '$' || next == '.' || next == ':')
     {
         state.Advance();
         return new String(next, 1);
     }
     return "";
 }
예제 #17
0
파일: Parser.cs 프로젝트: hvp/Gemgine
        public static ScriptObject ParseNumber(ParseState state)
        {
            var result = new GenericScriptObject("@type", "number", "@start", state.start, "@source", state);
            bool foundDot = false;

            while (!state.AtEnd())
            {
                if (state.Next() == '-')
                {
                    if (asInt(result["@start"]) != state.start) break;
                    state.Advance();
                    continue;
                }
                if (state.Next() >= '0' && state.Next() <= '9')
                {
                    state.Advance();
                    continue;
                }
                else if (state.Next() == '.')
                {
                    if (foundDot) break;
                    foundDot = true;
                    state.Advance();
                    continue;
                }
                break;
            }

            result["@end"] = state.start;
            result["@token"] = state.source.Substring(asInt(result["@start"]), asInt(result["@end"]) - asInt(result["@start"]));
            return result;
        }
예제 #18
0
파일: Parser.cs 프로젝트: hvp/Gemgine
        public static ScriptObject ParseExpression(ParseState state)
        {
            ScriptObject result = null;
            var prefix = ParsePrefix(state);
            if (state.Next() == '"')
            {
                result = ParseStringExpression(state);
            }
            else if (state.Next() == '(')
            {
                result = ParseNode(state);
            }
            else if (state.Next() == '\'')
            {
                result = ParseChar(state);
            }
            else if ("-0123456789".Contains(state.Next()))
            {
                result = ParseNumber(state);
                if (result["@token"].ToString() == "-") //A lone - sign is not a valid number. Interpret it as a token.
                    result["@type"] = "token";
            }
            else
            {
                if (" \t\r\n:.)}".Contains(state.Next())
                    && !String.IsNullOrEmpty(prefix))
                {
                    //The prefix is a token.
                    result = new GenericScriptObject("@type", "token", "@start", state.start - 1, "@source", state);
                    result["@end"] = state.start;
                    result["@token"] = prefix;
                    prefix = "";
                }
                else
                    result = ParseToken(state);
            }

            if (!state.AtEnd() && (state.Next() == '.' || state.Next() == ':'))
            {
                var final_result = new GenericScriptObject("@type", "memberaccess", "@start", result["@start"],
                    "@source", state);
                children(final_result).Add(result);
                final_result["@token"] = new String(state.Next(), 1);
                state.Advance();
                children(final_result).Add(ParseExpression(state));
                result = final_result;
            }

            result["@prefix"] = prefix;
            if (!PrefixCheck.CheckPrefix(result))
                throw new ParseError("Illegal prefix on expression of type " + result["@type"], state.currentLine);
            return result;
        }
예제 #19
0
        public static ScriptObject ParseExpression(ParseState state)
        {
            ScriptObject result = null;
            var          prefix = ParsePrefix(state);

            if (state.Next() == '"')
            {
                if (prefix == "$")
                {
                    prefix = "";
                    result = ParseBasicString(state);
                }
                else
                {
                    result = ParseStringExpression(state);
                }
            }
            else if (state.Next() == '(')
            {
                result = ParseNode(state);
            }
            else if (state.Next() == '\'')
            {
                result = ParseChar(state);
            }
            else if ("-0123456789".Contains(state.Next()))
            {
                result = ParseNumber(state);
                if (result["@token"].ToString() == "-") //A lone - sign is not a valid number. Interpret it as a token.
                {
                    result["@type"] = "token";
                }
            }
            else
            {
                if (" \t\r\n:.)}".Contains(state.Next()) &&
                    !String.IsNullOrEmpty(prefix))
                {
                    //The prefix is a token.
                    result           = new GenericScriptObject("@type", "token", "@start", state.start - 1, "@source", state);
                    result["@end"]   = state.start;
                    result["@token"] = prefix;
                    prefix           = "";
                }
                else
                {
                    result = ParseToken(state);
                }
            }

            if (!state.AtEnd() && (state.Next() == '.' || state.Next() == ':'))
            {
                var final_result = new GenericScriptObject("@type", "memberaccess", "@start", result["@start"],
                                                           "@source", state);
                children(final_result).Add(result);
                final_result["@token"] = new String(state.Next(), 1);
                state.Advance();
                children(final_result).Add(ParseExpression(state));
                result = final_result;
            }

            result["@prefix"] = prefix;
            if (!PrefixCheck.CheckPrefix(result))
            {
                throw new ParseError("Illegal prefix on expression of type " + result["@type"], state.currentLine);
            }
            return(result);
        }