Facebook.Unity.Editor/iOS/PBX/Parser.cs (128 lines of code) (raw):

/** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, * copy, modify, and distribute this software in source code or binary form for use * in connection with the web services and APIs provided by Facebook. * * As with any software that integrates with the Facebook platform, your use of * this software is subject to the Facebook Developer Principles and Policies * [http://developers.facebook.com/policy/]. This copyright notice shall be * included in all copies or substantial portions of the software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System.Collections.Generic; using System.Text.RegularExpressions; using System.IO; using System.Linq; using System; namespace Facebook.Unity.Editor.iOS.Xcode.PBX { class ValueAST {} // IdentifierAST := <quoted string> \ <string> class IdentifierAST : ValueAST { public int value = 0; // token id } // TreeAST := '{' KeyValuePairList '}' // KeyValuePairList := KeyValuePair ',' KeyValuePairList // KeyValuePair ',' // (empty) class TreeAST : ValueAST { public List<KeyValueAST> values = new List<KeyValueAST>(); } // ListAST := '(' ValueList ')' // ValueList := ValueAST ',' ValueList // ValueAST ',' // (empty) class ArrayAST : ValueAST { public List<ValueAST> values = new List<ValueAST>(); } // KeyValueAST := IdentifierAST '=' ValueAST ';' // ValueAST := IdentifierAST | TreeAST | ListAST class KeyValueAST { public IdentifierAST key = null; public ValueAST value = null; // either IdentifierAST, TreeAST or ListAST } class Parser { TokenList tokens; int currPos; public Parser(TokenList tokens) { this.tokens = tokens; currPos = SkipComments(0); } int SkipComments(int pos) { while (pos < tokens.Count && tokens[pos].type == TokenType.Comment) { pos++; } return pos; } // returns new position int IncInternal(int pos) { if (pos >= tokens.Count) return pos; pos++; return SkipComments(pos); } // Increments current pointer if not past the end, returns previous pos int Inc() { int prev = currPos; currPos = IncInternal(currPos); return prev; } // Returns the token type of the current token TokenType Tok() { if (currPos >= tokens.Count) return TokenType.EOF; return tokens[currPos].type; } void SkipIf(TokenType type) { if (Tok() == type) Inc(); } string GetErrorMsg() { return "Invalid PBX project (parsing line " + tokens[currPos].line + ")"; } public IdentifierAST ParseIdentifier() { if (Tok() != TokenType.String && Tok() != TokenType.QuotedString) throw new Exception(GetErrorMsg()); var ast = new IdentifierAST(); ast.value = Inc(); return ast; } public TreeAST ParseTree() { if (Tok() != TokenType.LBrace) throw new Exception(GetErrorMsg()); Inc(); var ast = new TreeAST(); while (Tok() != TokenType.RBrace && Tok() != TokenType.EOF) { ast.values.Add(ParseKeyValue()); } SkipIf(TokenType.RBrace); return ast; } public ArrayAST ParseList() { if (Tok() != TokenType.LParen) throw new Exception(GetErrorMsg()); Inc(); var ast = new ArrayAST(); while (Tok() != TokenType.RParen && Tok() != TokenType.EOF) { ast.values.Add(ParseValue()); SkipIf(TokenType.Comma); } SkipIf(TokenType.RParen); return ast; } // throws on error public KeyValueAST ParseKeyValue() { var ast = new KeyValueAST(); ast.key = ParseIdentifier(); if (Tok() != TokenType.Eq) throw new Exception(GetErrorMsg()); Inc(); // skip '=' ast.value = ParseValue(); SkipIf(TokenType.Semicolon); return ast; } // throws on error public ValueAST ParseValue() { if (Tok() == TokenType.String || Tok() == TokenType.QuotedString) return ParseIdentifier(); else if (Tok() == TokenType.LBrace) return ParseTree(); else if (Tok() == TokenType.LParen) return ParseList(); throw new Exception(GetErrorMsg()); } } } // namespace UnityEditor.iOS.Xcode