Singularity/Assets/Plugins/ImaginationOverflow/UniversalDeepLinking/Editor/Xcode/PBX/Parser.cs

168 lines
4.5 KiB
C#
Raw Normal View History

2024-05-06 14:45:45 -04:00
using System;
using System.Collections.Generic;
namespace ImaginationOverflow.UniversalDeepLinking.Editor.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 UnityModule.iOS.Xcode