Ejemplo n.º 1
0
        /// <summary>
        /// Parse a single .proto file.
        /// Return true if successful/no errors.
        /// </summary>
        public static void Parse(string path, ProtoCollection p)
        {
            //Preparation for parsing
            //Real parsing is done in ParseMessages
            lastComment.Clear();

            //Read entire file and pass it into a TokenReader
            string t = "";
            using (TextReader reader = new StreamReader(path, Encoding.UTF8))
            {
                while (true)
                {
                    string line = reader.ReadLine();
                    if (line == null)
                        break;

                    t += line + "\n";
                }
            }
            TokenReader tr = new TokenReader(t, path);

            try
            {
                ParseMessages(tr, p);
            }
            catch (EndOfStreamException)
            {
                return;
            }
        }
Ejemplo n.º 2
0
        static void ParseEnum(TokenReader tr, ProtoMessage parent, string package)
        {
            ProtoEnum me = new ProtoEnum(parent, package);

            LocalParser.ParseComments(me, lastComment, tr);
            me.ProtoName = tr.ReadNext();

            parent.Enums.Add(me.ProtoName, me); //must be after .ProtoName is read

            if (tr.ReadNext() != "{")
                throw new ProtoFormatException("Expected: {", tr);

            while (true)
            {
                string name = tr.ReadNext();

                if (ParseComment(name))
                    continue;

                if (name == "}")
                    return;

                //Ignore options
                if (name == "option")
                {
                    ParseOption(tr, null);
                    lastComment.Clear();
                    continue;
                }

                ParseEnumValue(tr, me, name);
            }
        }
Ejemplo n.º 3
0
        public static void ParseComments(IComment message, List<string> comments, TokenReader tr)
        {
            message.Comments = "";
            foreach (string s in comments)
            {
                if (s.StartsWith(":"))
                {
                    try
                    {
                        string line = s.Substring(1);

                        //Remove comments after "//"
                        int cpos = line.IndexOf("//");
                        if (cpos >= 0)
                            line = line.Substring(0, cpos);

                        string[] parts = line.Split('=');
                        if (parts.Length > 2)
                            throw new ProtoFormatException("Bad option format, at most one '=', " + s, tr);
                        string key = parts[0].Trim().ToLowerInvariant();
                        if (parts.Length == 1)
                        {
                            //Parse flag
                            if (message is ProtoMessage)
                                ParseMessageFlags((ProtoMessage)message, key);
                            else if (message is Field)
                                ParseFieldFlags((Field)message, key);
                            else
                                throw new NotImplementedException();

                            continue;
                        }
                        else
                        {
                            string value = (parts.Length == 2) ? parts[1].Trim() : null;

                            if (message is ProtoMessage)
                                ParseMessageOption((ProtoMessage)message, key, value);
                            else if (message is Field)
                                ParseFieldOption((Field)message, key, value);
                            else
                                throw new NotImplementedException();

                            continue;
                        }
                    }
                    catch (Exception e)
                    {
                        throw new ProtoFormatException(e.Message, e, tr);
                    }
                }
                else
                {
                    message.Comments += s + "\n";
                }
            }
            message.Comments = message.Comments.Trim(new char[] { '\n' }).Replace("\n", "\r\n");
            comments.Clear();
        }
Ejemplo n.º 4
0
        static void ParseMessages(TokenReader tr, ProtoCollection p)
        {
            string package = "Example";

            while (true)
            {
                string token = tr.ReadNextComment();
                if (ParseComment(token))
                    continue;

                try
                {
                    switch (token)
                    {
                        case ";":
                            break;
                        case "message":
                            ParseMessage(tr, p, package);
                            break;
                        case "enum":
                            ParseEnum(tr, p, package);
                            break;
                        case "option":
                            //Save options
                            ParseOption(tr, p);
                            break;
                        case "import":
                            ParseImport(tr, p);
                            break;
                        case "package":
                            package = tr.ReadNext();
                            tr.ReadNextOrThrow(";");
                            break;
                        case "syntax": //This is not a supported protobuf keyword, used in Google internally
                            tr.ReadNextOrThrow("=");
                            tr.ReadNext();
                            tr.ReadNextOrThrow(";");
                            break;
                        case "extend":
                            ParseExtend(tr, p, package);
                            break;
                        default:
                            throw new ProtoFormatException("Unexpected/not implemented: " + token, tr);
                    }
                    lastComment.Clear();
                }
                catch (EndOfStreamException)
                {
                    throw new ProtoFormatException("Unexpected EOF", tr);
                }
            }
        }
Ejemplo n.º 5
0
        static bool ParseField(TokenReader tr, ProtoMessage m)
        {
            string rule = tr.ReadNext();
            while (true)
            {
                if (ParseComment(rule) == false)
                    break;
                rule = tr.ReadNext();
            }

            Field f = new Field(tr);

            //Rule
            switch (rule)
            {
                case ";":
                    lastComment.Clear();
                    return true;
                case "}":
                    lastComment.Clear();
                    return false;
                case "required":
                    f.Rule = FieldRule.Required;
                    break;
                case "optional":
                    f.Rule = FieldRule.Optional;
                    break;
                case "repeated":
                    f.Rule = FieldRule.Repeated;
                    break;
                case "option":
                    //Save options
                    ParseOption(tr, m);
                    return true;
                case "message":
                    ParseMessage(tr, m, m.Package + "." + m.ProtoName);
                    return true;
                case "enum":
                    ParseEnum(tr, m, m.Package + "." + m.ProtoName);
                    return true;
                case "extensions":
                    ParseExtensions(tr, m);
                    return true;
                default:
                    throw new ProtoFormatException("unknown rule: " + rule, tr);
            }

            //Field comments
            LocalParser.ParseComments(f, lastComment, tr);

            //Type
            f.ProtoTypeName = tr.ReadNext();

            //Name
            f.ProtoName = tr.ReadNext();

            //ID
            tr.ReadNextOrThrow("=");
            f.ID = int.Parse(tr.ReadNext());
            if (19000 <= f.ID && f.ID <= 19999)
                throw new ProtoFormatException("Can't use reserved field ID 19000-19999", tr);
            if (f.ID > (1 << 29) - 1)
                throw new ProtoFormatException("Maximum field id is 2^29 - 1", tr);

            //Add Field to message
            m.Fields.Add(f.ID, f);

            //Determine if extra options
            string extra = tr.ReadNext();
            if (extra == ";")
                return true;

            //Field options
            if (extra != "[")
                throw new ProtoFormatException("Expected: [ got " + extra, tr);

            ParseFieldOptions(tr, f);
            return true;
        }
Ejemplo n.º 6
0
 static void ParseExtensions(TokenReader tr, ProtoMessage m)
 {
     //extensions 100 to max;
     tr.ReadNext(); //100
     tr.ReadNextOrThrow("to");
     tr.ReadNext(); //number or max
     tr.ReadNextOrThrow(";");
 }
Ejemplo n.º 7
0
 public Field(TokenReader tr)
 {
     Source = new SourcePath(tr);
 }
Ejemplo n.º 8
0
 public SourcePath(TokenReader tr)
 {
     this.Path = System.IO.Path.GetFullPath(tr.Path);
     this.Line = tr.Parsed.Split('\n').Length - 1;
     this.Column = tr.Parsed.Length - tr.Parsed.LastIndexOf('\n') + 1;
 }
Ejemplo n.º 9
0
        static void ParseMessage(TokenReader tr, ProtoMessage parent, string package)
        {
            var msg = new ProtoMessage(parent, package);
            LocalParser.ParseComments(msg, lastComment, tr);
            msg.ProtoName = tr.ReadNext();

            tr.ReadNextOrThrow("{");

            try
            {
                while (ParseField(tr, msg))
                    continue;
            }
            catch (Exception e)
            {
                throw new ProtoFormatException(e.Message, e, tr);
            }

            parent.Messages.Add(msg.ProtoName, msg);
        }
Ejemplo n.º 10
0
        static int ParseInt(TokenReader tr)
        {
            string text = tr.ReadNext();

            int val;

            //Decimal
            if (int.TryParse(text, out val))
                return val;

            //Hex
            if (text.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase))
            {
                var hex = text.Substring(2);

                if (int.TryParse(hex, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
                    return val;
            }

            throw new ProtoFormatException("Unknown integer format: " + text, tr);
        }
Ejemplo n.º 11
0
        static void ParseImport(TokenReader tr, ProtoCollection collection)
        {
            string path = tr.ReadNext();
            bool publicImport = path == "public";
            if (publicImport)
                path = tr.ReadNext();
            tr.ReadNextOrThrow(";");

            if (publicImport)
                collection.ImportPublic.Add(path);
            else
                collection.Import.Add(path);
        }
Ejemplo n.º 12
0
 public ProtoFormatException(string message, Exception innerException, TokenReader tr)
     : base(message, innerException)
 {
     this.SourcePath = new SourcePath(tr);
 }
Ejemplo n.º 13
0
 public SourcePath(TokenReader tr)
 {
     this.Path   = System.IO.Path.GetFullPath(tr.Path);
     this.Line   = tr.Parsed.Split('\n').Length - 1;
     this.Column = tr.Parsed.Length - tr.Parsed.LastIndexOf('\n') + 1;
 }
Ejemplo n.º 14
0
        static bool ParseField(TokenReader tr, ProtoMessage m)
        {
            string rule = tr.ReadNext();

            while (true)
            {
                if (ParseComment(rule) == false)
                {
                    break;
                }
                rule = tr.ReadNext();
            }

            Field f = new Field(tr);

            //Rule
            switch (rule)
            {
            case ";":
                lastComment.Clear();
                return(true);

            case "}":
                lastComment.Clear();
                return(false);

            case "required":
                f.Rule = FieldRule.Required;
                break;

            case "optional":
                f.Rule = FieldRule.Optional;
                break;

            case "repeated":
                f.Rule = FieldRule.Repeated;
                break;

            case "option":
                //Save options
                ParseOption(tr, m);
                return(true);

            case "message":
                ParseMessage(tr, m, m.Package + "." + m.ProtoName);
                return(true);

            case "enum":
                ParseEnum(tr, m, m.Package + "." + m.ProtoName);
                return(true);

            case "extensions":
                ParseExtensions(tr, m);
                return(true);

            default:
                throw new ProtoFormatException("unknown rule: " + rule, tr);
            }

            //Field comments
            LocalParser.ParseComments(f, lastComment, tr);

            //Type
            f.ProtoTypeName = tr.ReadNext();

            //Name
            f.ProtoName = tr.ReadNext();

            //ID
            tr.ReadNextOrThrow("=");
            f.ID = int.Parse(tr.ReadNext());
            if (19000 <= f.ID && f.ID <= 19999)
            {
                throw new ProtoFormatException("Can't use reserved field ID 19000-19999", tr);
            }
            if (f.ID > (1 << 29) - 1)
            {
                throw new ProtoFormatException("Maximum field id is 2^29 - 1", tr);
            }

            //Add Field to message
            m.Fields.Add(f.ID, f);

            //Determine if extra options
            string extra = tr.ReadNext();

            if (extra == ";")
            {
                return(true);
            }

            //Field options
            if (extra != "[")
            {
                throw new ProtoFormatException("Expected: [ got " + extra, tr);
            }

            ParseFieldOptions(tr, f);
            return(true);
        }
Ejemplo n.º 15
0
        static void ParseMessages(TokenReader tr, ProtoCollection p)
        {
            string package = "Example";

            while (true)
            {
                string token = tr.ReadNext();
                if (ParseComment(token))
                {
                    continue;
                }

                try
                {
                    switch (token)
                    {
                    case ";":
                        lastComment.Clear();
                        continue;

                    case "message":
                        ParseMessage(tr, p, package);
                        break;

                    case "enum":
                        ParseEnum(tr, p, package);
                        break;

                    case "option":
                        //Save options
                        ParseOption(tr, p);
                        break;

                    case "import":     //Ignored
                        tr.ReadNext();
                        tr.ReadNextOrThrow(";");
                        break;

                    case "package":
                        package = tr.ReadNext();
                        tr.ReadNextOrThrow(";");
                        break;

                    case "syntax":     //This is not a supported protobuf keyword, used in Google internally
                        tr.ReadNextOrThrow("=");
                        tr.ReadNext();
                        tr.ReadNextOrThrow(";");
                        break;

                    case "extend":
                        ParseExtend(tr, p, package);
                        break;

                    default:
                        throw new ProtoFormatException("Unexpected/not implemented: " + token, tr);
                    }
                }
                catch (EndOfStreamException)
                {
                    throw new ProtoFormatException("Unexpected EOF", tr);
                }
            }
        }
Ejemplo n.º 16
0
 public Field(TokenReader tr)
 {
     Source = new SourcePath(tr);
 }
Ejemplo n.º 17
0
        static void ParseFieldOptions(TokenReader tr, Field f)
        {
            while (true)
            {
                string key = tr.ReadNext();
                tr.ReadNextOrThrow("=");
                string val = tr.ReadNext();

                ParseFieldOption(key, val, f);
                string optionSep = tr.ReadNext();
                if (optionSep == "]")
                    break;
                if (optionSep == ",")
                    continue;
                throw new ProtoFormatException(@"Expected "","" or ""]"" got " + tr.NextCharacter, tr);
            }
            tr.ReadNextOrThrow(";");
        }
Ejemplo n.º 18
0
 public ProtoFormatException(string message, Exception innerException, TokenReader tr)
     : base(message, innerException)
 {
     this.SourcePath = new SourcePath(tr);
 }
Ejemplo n.º 19
0
        /// <summary>
        /// File or Message options
        /// </summary>
        static void ParseOption(TokenReader tr, ProtoMessage m)
        {
            //Read name
            string key = tr.ReadNext();
            if (tr.ReadNext() != "=")
                throw new ProtoFormatException("Expected: = got " + tr.NextCharacter, tr);
            //Read value
            string value = tr.ReadNext();
            if (tr.ReadNext() != ";")
                throw new ProtoFormatException("Expected: ; got " + tr.NextCharacter, tr);

            //null = ignore option
            if (m == null)
                return;

            switch (key)
            {
                //None at the moment
                //case "namespace":
                //    m.OptionNamespace = value;
                //    break;
                default:
                    Console.WriteLine("Warning: Unknown option: " + key + " = " + value);
                    break;
            }
        }
Ejemplo n.º 20
0
        static void ParseMessages(TokenReader tr, ProtoCollection p)
        {
            string package = "Example";

            while (true)
            {
                string token = tr.ReadNext();
                if (ParseComment(token))
                    continue;

                try
                {
                    switch (token)
                    {
                        case ";":
                            lastComment.Clear();
                            continue;
                        case "message":
                            ParseMessage(tr, p, package);
                            break;
                        case "enum":
                            ParseEnum(tr, p, package);
                            break;
                        case "option":
                        //Save options
                            ParseOption(tr, p);
                            break;
                        case "import": //Ignored
                            tr.ReadNext();
                            tr.ReadNextOrThrow(";");
                            break;
                        case "package":
                            package = tr.ReadNext();
                            tr.ReadNextOrThrow(";");
                            break;
                        case "extend":
                            ParseExtend(tr, p, package);
                            break;
                        default:
                            throw new ProtoFormatException("Unexpected/not implemented: " + token, tr);
                    }
                } catch (EndOfStreamException)
                {
                    throw new ProtoFormatException("Unexpected EOF", tr);
                }
            }
        }
Ejemplo n.º 21
0
        static void ParseEnumValue(TokenReader tr, ProtoEnum parent, string name)
        {
            if (tr.ReadNext() != "=")
                throw new ProtoFormatException("Expected: =", tr);

            int id = int.Parse(tr.ReadNext());

            var value = new ProtoEnumValue(name, id, lastComment);
            parent.Enums.Add(value);

            string extra = tr.ReadNext();

            if (extra == ";")
                return;

            if (extra != "[")
                throw new ProtoFormatException("Expected: ; or [", tr);

            ParseEnumValueOptions(tr, value);
        }
Ejemplo n.º 22
0
        public static void ParseComments(IComment message, List <string> comments, TokenReader tr)
        {
            message.Comments = "";
            foreach (string s in comments)
            {
                if (s.StartsWith(":"))
                {
                    try
                    {
                        string line = s.Substring(1);

                        //Remove comments after "//"
                        int cpos = line.IndexOf("//");
                        if (cpos >= 0)
                        {
                            line = line.Substring(0, cpos);
                        }

                        string[] parts = line.Split('=');
                        if (parts.Length > 2)
                        {
                            throw new ProtoFormatException("Bad option format, at most one '=', " + s, tr);
                        }
                        string key = parts [0].Trim().ToLowerInvariant();
                        if (parts.Length == 1)
                        {
                            //Parse flag
                            if (message is ProtoMessage)
                            {
                                ParseMessageFlags((ProtoMessage)message, key);
                            }
                            else if (message is Field)
                            {
                                ParseFieldFlags((Field)message, key);
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }

                            continue;
                        }
                        else
                        {
                            string value = (parts.Length == 2) ? parts [1].Trim() : null;

                            if (message is ProtoMessage)
                            {
                                ParseMessageOption((ProtoMessage)message, key, value);
                            }
                            else if (message is Field)
                            {
                                ParseFieldOption((Field)message, key, value);
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }

                            continue;
                        }
                    } catch (Exception e)
                    {
                        throw new ProtoFormatException(e.Message, e, tr);
                    }
                }
                else
                {
                    message.Comments += s + "\n";
                }
            }
            message.Comments = message.Comments.Trim(new char[] { '\n' }).Replace("\n", "\r\n");
            comments.Clear();
        }