From: Jean-Philippe Bruyère Date: Tue, 27 Feb 2018 23:51:17 +0000 (+0100) Subject: change styling grammar for value now enclose in double quote X-Git-Tag: 0.7.3~4^2~37 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=d5cf794076899803b9a34eb46d3b2e34f3e3cfbc;p=jp%2Fcrow.git change styling grammar for value now enclose in double quote --- diff --git a/Crow.csproj b/Crow.csproj index 41e556f8..91b16e31 100644 --- a/Crow.csproj +++ b/Crow.csproj @@ -222,6 +222,7 @@ + diff --git a/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj index b916d716..38adac85 100644 --- a/CrowIDE/CrowIDE.csproj +++ b/CrowIDE/CrowIDE.csproj @@ -110,14 +110,13 @@ - - + diff --git a/CrowIDE/src/Project.cs b/CrowIDE/src/Project.cs index 1cbdecbf..0da5dc19 100644 --- a/CrowIDE/src/Project.cs +++ b/CrowIDE/src/Project.cs @@ -439,10 +439,14 @@ namespace Crow.Coding // } public void GetStyling () { - foreach (ProjectFile pi in flattenNodes.OfType ().Where (pp=>pp.Type == ItemType.EmbeddedResource && pp.Extension == ".style")) { - using (Stream s = new MemoryStream (System.Text.Encoding.UTF8.GetBytes(pi.Source))) { - new StyleReader (solution.Styling, s, pi.ResourceID); + try { + foreach (ProjectFile pi in flattenNodes.OfType ().Where (pp=>pp.Type == ItemType.EmbeddedResource && pp.Extension == ".style")) { + using (Stream s = new MemoryStream (System.Text.Encoding.UTF8.GetBytes(pi.Source))) { + new StyleReader (solution.Styling, s, pi.ResourceID); + } } + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); } foreach (ProjectReference pr in flattenNodes.OfType()) { Project p = solution.Projects.FirstOrDefault (pp => pp.ProjectGuid == pr.ProjectGUID); diff --git a/CrowIDE/src/SourceEditor/BufferParser.cs b/CrowIDE/src/SourceEditor/BufferParser.cs new file mode 100644 index 00000000..87dd779e --- /dev/null +++ b/CrowIDE/src/SourceEditor/BufferParser.cs @@ -0,0 +1,302 @@ +using System; +using System.IO; +using Crow; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace Crow.Coding +{ + /// + /// base class for tokenizing sources + /// + public abstract class BufferParser + { + /// + /// Default tokens, this enum may be overriden in derived parser with the new keyword, + /// see XMLParser for example. + /// + public enum TokenType { + Unknown = 0, + WhiteSpace = 1, + NewLine = 2, + LineComment = 3, + BlockCommentStart = 4, + BlockComment = 5, + BlockCommentEnd = 6, + Type = 7, + Identifier = 8, + Indexer = 9, + OpenBlock = 10, + CloseBlock = 11, + StatementEnding = 12, + UnaryOp = 13, + BinaryOp = 14, + Affectation = 15, + StringLitteralOpening = 16, + StringLitteralClosing = 17, + StringLitteral = 18, + NumericLitteral = 19, + Preprocessor = 20, + Keyword = 21, + } + + #region CTOR + public BufferParser (CodeBuffer _buffer) + { + buffer = _buffer; + + buffer.LineUpadateEvent += Buffer_LineUpadateEvent; + //buffer.LineAdditionEvent += Buffer_LineAdditionEvent;; + buffer.LineRemoveEvent += Buffer_LineRemoveEvent; + buffer.BufferCleared += Buffer_BufferCleared; + } + + #endregion + + #region Buffer events handlers + void Buffer_BufferCleared (object sender, EventArgs e) + { + + } + void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e) + { + + } + void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e) + { + reparseSource (); + } + void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e) + { + for (int i = 0; i < e.LineCount; i++) + tryParseBufferLine (e.LineStart + i); + reparseSource (); + } + #endregion + + void updateFolding () { + // Stack foldings = new Stack(); + // bool inStartTag = false; + // + // for (int i = 0; i < parser.Tokens.Count; i++) { + // TokenList tl = parser.Tokens [i]; + // tl.foldingTo = null; + // int fstTK = tl.FirstNonBlankTokenIndex; + // if (fstTK > 0 && fstTK < tl.Count - 1) { + // if (tl [fstTK + 1] != XMLParser.TokenType.ElementName) + // continue; + // if (tl [fstTK] == XMLParser.TokenType.ElementStart) { + // //search closing tag + // int tkPtr = fstTK+2; + // while (tkPtr < tl.Count) { + // if (tl [tkPtr] == XMLParser.TokenType.ElementClosing) + // + // tkPtr++; + // } + // if (tl.EndingState == (int)XMLParser.States.Content) + // foldings.Push (tl); + // else if (tl.EndingState == (int)XMLParser.States.StartTag) + // inStartTag = true; + // continue; + // } + // if (tl [fstTK] == XMLParser.TokenType.ElementEnd) { + // TokenList tls = foldings.Pop (); + // int fstTKs = tls.FirstNonBlankTokenIndex; + // if (tls [fstTK + 1].Content == tl [fstTK + 1].Content) { + // tl.foldingTo = tls; + // continue; + // } + // parser.CurrentPosition = tls [fstTK + 1].Start; + // parser.SetLineInError(new ParserException(parser, "closing tag not corresponding")); + // } + // + // } + // } + } + public void reparseSource () { + for (int i = 0; i < buffer.LineCount; i++) { + if (!buffer[i].IsParsed) + tryParseBufferLine (i); + } + try { + SyntaxAnalysis (); + } catch (Exception ex) { + Debug.WriteLine ("Syntax Error: " + ex.ToString ()); + if (ex is ParserException) + SetLineInError (ex as ParserException); + } + } + public void tryParseBufferLine(int lPtr) { + buffer [lPtr].exception = null; + currentLine = lPtr; + currentColumn = 0; + eol = false; + + try { + ParseCurrentLine (); + } catch (Exception ex) { + Debug.WriteLine (ex.ToString ()); + if (ex is ParserException) + SetLineInError (ex as ParserException); + } + + } + + protected CodeBuffer buffer; + + internal int currentLine = 0; + internal int currentColumn = 0; + protected Token currentTok; + protected bool eol = true; + + public Node RootNode; + + protected Point CurrentPosition { + get { return new Point (currentLine, currentColumn); } + set { + currentLine = value.Y; + currentColumn = value.X; + } + } + + public abstract void ParseCurrentLine(); + public abstract void SyntaxAnalysis (); + + public virtual void SetLineInError(ParserException ex) { + currentTok = default(Token); + if (ex.Line >= buffer.LineCount) + ex.Line = buffer.LineCount - 1; + if (buffer [ex.Line].IsFolded) + buffer.ToogleFolding (ex.Line); + buffer [ex.Line].SetLineInError (ex); + } + + #region low level parsing + /// + /// Read one char from current position in buffer and store it into the current token + /// + /// if true, set the Start position of the current token to the current position + protected void readToCurrTok(bool startOfTok = false){ + if (startOfTok) + currentTok.Start = CurrentPosition; + currentTok += Read(); + } + /// + /// read n char from the buffer and store it into the current token + /// + protected void readToCurrTok(int length) { + for (int i = 0; i < length; i++) + currentTok += Read (); + } + /// + /// Save current token into current TokensLine and raz current token + /// + protected void saveAndResetCurrentTok() { + currentTok.End = CurrentPosition; + buffer[currentLine].Tokens.Add (currentTok); + currentTok = default(Token); + } + /// + /// read one char and add current token to current TokensLine, current token is reset + /// + /// Type of the token + /// set start of token to current position + protected void readAndResetCurrentTok(System.Enum type, bool startToc = false) { + readToCurrTok (); + saveAndResetCurrentTok (type); + } + /// + /// Save current tok + /// + /// set the type of the tok + protected void saveAndResetCurrentTok(System.Enum type) { + currentTok.Type = (TokenType)type; + saveAndResetCurrentTok (); + } + /// + /// Peek next char, emit '\n' if current column > buffer's line length + /// Throw error if eof is true + /// + protected virtual char Peek() { + if (eol) + throw new ParserException (currentLine, currentColumn, "Unexpected End of line"); + return currentColumn < buffer [currentLine].Length ? + buffer [currentLine] [currentColumn] : '\n'; + } + /// + /// Peek n char from buffer or less if remaining char in buffer's line is less than requested + /// if end of line is reached, no '\n' will be emitted, instead, empty string is returned. '\n' should be checked only + /// with single char Peek(). + /// Throw error is eof is true + /// + /// Length. + protected virtual string Peek(int length) { + if (eol) + throw new ParserException (currentLine, currentColumn, "Unexpected End of Line"); + int lg = Math.Min(length, Math.Max (buffer [currentLine].Length - currentColumn, buffer [currentLine].Length - currentColumn - length)); + if (lg == 0) + return ""; + return buffer [currentLine].Content.Substring (currentColumn, lg); + } + /// + /// read one char from buffer at current position, if '\n' is read, current line is incremented + /// and column is reset to 0 + /// + protected virtual char Read() { + char c = Peek (); + if (c == '\n') + eol = true; + currentColumn++; + return c; + } + /// + /// read until end of line is reached + /// + /// string read + protected virtual string ReadLine () { + StringBuilder tmp = new StringBuilder(); + char c = Read (); + while (!eol) { + tmp.Append (c); + c = Read (); + } + return tmp.ToString(); + } + /// + /// read until end expression is reached or end of line. + /// + /// string read minus the ending expression that has to be read after + /// Expression to search for + protected virtual string ReadLineUntil (string endExp){ + string tmp = ""; + + while (!eol) { + if (buffer [currentLine].Length - currentColumn - endExp.Length < 0) { + tmp += ReadLine(); + break; + } + if (string.Equals (Peek (endExp.Length), endExp)) + return tmp; + tmp += Read(); + } + return tmp; + } + /// + /// skip white spaces, but not line break. Save spaces in a WhiteSpace token. + /// + protected void SkipWhiteSpaces () { + if (currentTok.Type != TokenType.Unknown) + throw new ParserException (currentLine, currentColumn, "current token should be reset to unknown (0) before skiping white spaces"); + while (!eol) { + if (!char.IsWhiteSpace (Peek ())||Peek()=='\n') + break; + readToCurrTok (currentTok.Type == TokenType.Unknown); + currentTok.Type = TokenType.WhiteSpace; + } + if (currentTok.Type != TokenType.Unknown) + saveAndResetCurrentTok (); + } + #endregion + } +} \ No newline at end of file diff --git a/CrowIDE/src/SourceEditor/CSharpParser.cs b/CrowIDE/src/SourceEditor/CSharpParser.cs index 7d56ce43..8c445824 100644 --- a/CrowIDE/src/SourceEditor/CSharpParser.cs +++ b/CrowIDE/src/SourceEditor/CSharpParser.cs @@ -7,7 +7,7 @@ using System.Linq; namespace Crow.Coding { - public class CSharpParser : Parser + public class CSharpParser : BufferParser { #region keywords string[] keywords = new string[] { @@ -171,7 +171,7 @@ namespace Crow.Coding if (Peek () == '\n') { if (currentTok != TokenType.Unknown) - throw new ParsingException (this, "Unexpected end of line"); + throw new ParserException (currentLine, currentColumn, "Unexpected end of line"); Read (); eol = true; continue; @@ -182,7 +182,7 @@ namespace Crow.Coding Debugger.Break (); currentTok.Start = CurrentPosition; - currentTok.Type = (Parser.TokenType)TokenType.BlockComment; + currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment; currentTok += ReadLineUntil ("*/"); if (Peek (2) == "*/") { readToCurrTok (2); diff --git a/CrowIDE/src/SourceEditor/CodeLine.cs b/CrowIDE/src/SourceEditor/CodeLine.cs index 622584c7..612cac73 100644 --- a/CrowIDE/src/SourceEditor/CodeLine.cs +++ b/CrowIDE/src/SourceEditor/CodeLine.cs @@ -10,7 +10,7 @@ namespace Crow.Coding public List Tokens; public int EndingState = 0; public Node SyntacticNode; - public ParsingException exception; + public ParserException exception; public CodeLine (string _content){ Content = _content; @@ -52,7 +52,7 @@ namespace Crow.Coding } } - public void SetLineInError (ParsingException ex) { + public void SetLineInError (ParserException ex) { Tokens = null; exception = ex; } diff --git a/CrowIDE/src/SourceEditor/Parser.cs b/CrowIDE/src/SourceEditor/Parser.cs deleted file mode 100644 index f655fa49..00000000 --- a/CrowIDE/src/SourceEditor/Parser.cs +++ /dev/null @@ -1,302 +0,0 @@ -using System; -using System.IO; -using Crow; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text; - -namespace Crow.Coding -{ - /// - /// base class for tokenizing sources - /// - public abstract class Parser - { - /// - /// Default tokens, this enum may be overriden in derived parser with the new keyword, - /// see XMLParser for example. - /// - public enum TokenType { - Unknown = 0, - WhiteSpace = 1, - NewLine = 2, - LineComment = 3, - BlockCommentStart = 4, - BlockComment = 5, - BlockCommentEnd = 6, - Type = 7, - Identifier = 8, - Indexer = 9, - OpenBlock = 10, - CloseBlock = 11, - StatementEnding = 12, - UnaryOp = 13, - BinaryOp = 14, - Affectation = 15, - StringLitteralOpening = 16, - StringLitteralClosing = 17, - StringLitteral = 18, - NumericLitteral = 19, - Preprocessor = 20, - Keyword = 21, - } - - #region CTOR - public Parser (CodeBuffer _buffer) - { - buffer = _buffer; - - buffer.LineUpadateEvent += Buffer_LineUpadateEvent; - //buffer.LineAdditionEvent += Buffer_LineAdditionEvent;; - buffer.LineRemoveEvent += Buffer_LineRemoveEvent; - buffer.BufferCleared += Buffer_BufferCleared; - } - - #endregion - - #region Buffer events handlers - void Buffer_BufferCleared (object sender, EventArgs e) - { - - } - void Buffer_LineAdditionEvent (object sender, CodeBufferEventArgs e) - { - - } - void Buffer_LineRemoveEvent (object sender, CodeBufferEventArgs e) - { - reparseSource (); - } - void Buffer_LineUpadateEvent (object sender, CodeBufferEventArgs e) - { - for (int i = 0; i < e.LineCount; i++) - tryParseBufferLine (e.LineStart + i); - reparseSource (); - } - #endregion - - void updateFolding () { - // Stack foldings = new Stack(); - // bool inStartTag = false; - // - // for (int i = 0; i < parser.Tokens.Count; i++) { - // TokenList tl = parser.Tokens [i]; - // tl.foldingTo = null; - // int fstTK = tl.FirstNonBlankTokenIndex; - // if (fstTK > 0 && fstTK < tl.Count - 1) { - // if (tl [fstTK + 1] != XMLParser.TokenType.ElementName) - // continue; - // if (tl [fstTK] == XMLParser.TokenType.ElementStart) { - // //search closing tag - // int tkPtr = fstTK+2; - // while (tkPtr < tl.Count) { - // if (tl [tkPtr] == XMLParser.TokenType.ElementClosing) - // - // tkPtr++; - // } - // if (tl.EndingState == (int)XMLParser.States.Content) - // foldings.Push (tl); - // else if (tl.EndingState == (int)XMLParser.States.StartTag) - // inStartTag = true; - // continue; - // } - // if (tl [fstTK] == XMLParser.TokenType.ElementEnd) { - // TokenList tls = foldings.Pop (); - // int fstTKs = tls.FirstNonBlankTokenIndex; - // if (tls [fstTK + 1].Content == tl [fstTK + 1].Content) { - // tl.foldingTo = tls; - // continue; - // } - // parser.CurrentPosition = tls [fstTK + 1].Start; - // parser.SetLineInError(new ParsingException(parser, "closing tag not corresponding")); - // } - // - // } - // } - } - public void reparseSource () { - for (int i = 0; i < buffer.LineCount; i++) { - if (!buffer[i].IsParsed) - tryParseBufferLine (i); - } - try { - SyntaxAnalysis (); - } catch (Exception ex) { - Debug.WriteLine ("Syntax Error: " + ex.ToString ()); - if (ex is ParsingException) - SetLineInError (ex as ParsingException); - } - } - public void tryParseBufferLine(int lPtr) { - buffer [lPtr].exception = null; - currentLine = lPtr; - currentColumn = 0; - eol = false; - - try { - ParseCurrentLine (); - } catch (Exception ex) { - Debug.WriteLine (ex.ToString ()); - if (ex is ParsingException) - SetLineInError (ex as ParsingException); - } - - } - - protected CodeBuffer buffer; - - internal int currentLine = 0; - internal int currentColumn = 0; - protected Token currentTok; - protected bool eol = true; - - public Node RootNode; - - protected Point CurrentPosition { - get { return new Point (currentLine, currentColumn); } - set { - currentLine = value.Y; - currentColumn = value.X; - } - } - - public abstract void ParseCurrentLine(); - public abstract void SyntaxAnalysis (); - - public virtual void SetLineInError(ParsingException ex) { - currentTok = default(Token); - if (ex.Line >= buffer.LineCount) - ex.Line = buffer.LineCount - 1; - if (buffer [ex.Line].IsFolded) - buffer.ToogleFolding (ex.Line); - buffer [ex.Line].SetLineInError (ex); - } - - #region low level parsing - /// - /// Read one char from current position in buffer and store it into the current token - /// - /// if true, set the Start position of the current token to the current position - protected void readToCurrTok(bool startOfTok = false){ - if (startOfTok) - currentTok.Start = CurrentPosition; - currentTok += Read(); - } - /// - /// read n char from the buffer and store it into the current token - /// - protected void readToCurrTok(int length) { - for (int i = 0; i < length; i++) - currentTok += Read (); - } - /// - /// Save current token into current TokensLine and raz current token - /// - protected void saveAndResetCurrentTok() { - currentTok.End = CurrentPosition; - buffer[currentLine].Tokens.Add (currentTok); - currentTok = default(Token); - } - /// - /// read one char and add current token to current TokensLine, current token is reset - /// - /// Type of the token - /// set start of token to current position - protected void readAndResetCurrentTok(System.Enum type, bool startToc = false) { - readToCurrTok (); - saveAndResetCurrentTok (type); - } - /// - /// Save current tok - /// - /// set the type of the tok - protected void saveAndResetCurrentTok(System.Enum type) { - currentTok.Type = (TokenType)type; - saveAndResetCurrentTok (); - } - /// - /// Peek next char, emit '\n' if current column > buffer's line length - /// Throw error if eof is true - /// - protected virtual char Peek() { - if (eol) - throw new ParsingException (this, "Unexpected End of line"); - return currentColumn < buffer [currentLine].Length ? - buffer [currentLine] [currentColumn] : '\n'; - } - /// - /// Peek n char from buffer or less if remaining char in buffer's line is less than requested - /// if end of line is reached, no '\n' will be emitted, instead, empty string is returned. '\n' should be checked only - /// with single char Peek(). - /// Throw error is eof is true - /// - /// Length. - protected virtual string Peek(int length) { - if (eol) - throw new ParsingException (this, "Unexpected End of Line"); - int lg = Math.Min(length, Math.Max (buffer [currentLine].Length - currentColumn, buffer [currentLine].Length - currentColumn - length)); - if (lg == 0) - return ""; - return buffer [currentLine].Content.Substring (currentColumn, lg); - } - /// - /// read one char from buffer at current position, if '\n' is read, current line is incremented - /// and column is reset to 0 - /// - protected virtual char Read() { - char c = Peek (); - if (c == '\n') - eol = true; - currentColumn++; - return c; - } - /// - /// read until end of line is reached - /// - /// string read - protected virtual string ReadLine () { - StringBuilder tmp = new StringBuilder(); - char c = Read (); - while (!eol) { - tmp.Append (c); - c = Read (); - } - return tmp.ToString(); - } - /// - /// read until end expression is reached or end of line. - /// - /// string read minus the ending expression that has to be read after - /// Expression to search for - protected virtual string ReadLineUntil (string endExp){ - string tmp = ""; - - while (!eol) { - if (buffer [currentLine].Length - currentColumn - endExp.Length < 0) { - tmp += ReadLine(); - break; - } - if (string.Equals (Peek (endExp.Length), endExp)) - return tmp; - tmp += Read(); - } - return tmp; - } - /// - /// skip white spaces, but not line break. Save spaces in a WhiteSpace token. - /// - protected void SkipWhiteSpaces () { - if (currentTok.Type != TokenType.Unknown) - throw new ParsingException (this, "current token should be reset to unknown (0) before skiping white spaces"); - while (!eol) { - if (!char.IsWhiteSpace (Peek ())||Peek()=='\n') - break; - readToCurrTok (currentTok.Type == TokenType.Unknown); - currentTok.Type = TokenType.WhiteSpace; - } - if (currentTok.Type != TokenType.Unknown) - saveAndResetCurrentTok (); - } - #endregion - } -} \ No newline at end of file diff --git a/CrowIDE/src/SourceEditor/ParsingException.cs b/CrowIDE/src/SourceEditor/ParsingException.cs deleted file mode 100644 index 88c51c9b..00000000 --- a/CrowIDE/src/SourceEditor/ParsingException.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace Crow.Coding -{ - public class ParsingException : Exception - { - public int Line; - public int Column; - public ParsingException(Parser parser, string txt) - : base(string.Format("Parser exception ({0},{1}): {2}", parser.currentLine, parser.currentColumn, txt)) - { - Line = parser.currentLine; - Column = parser.currentColumn; - } - public ParsingException(Parser parser, string txt, Exception innerException) - : base(txt, innerException) - { - txt = string.Format("Parser exception ({0},{1}): {2}", parser.currentLine, parser.currentColumn, txt); - } - } -} - diff --git a/CrowIDE/src/SourceEditor/SourceEditor.cs b/CrowIDE/src/SourceEditor/SourceEditor.cs index d594776e..8d8a5d68 100644 --- a/CrowIDE/src/SourceEditor/SourceEditor.cs +++ b/CrowIDE/src/SourceEditor/SourceEditor.cs @@ -58,10 +58,10 @@ namespace Crow.Coding formatting.Add ((int)XMLParser.TokenType.AttributeValue, new TextFormatting (Color.TractorRed, Color.Transparent, false, true)); formatting.Add ((int)XMLParser.TokenType.XMLDecl, new TextFormatting (Color.AoEnglish, Color.Transparent)); - formatting.Add ((int)Parser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); - formatting.Add ((int)Parser.TokenType.LineComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); - formatting.Add ((int)Parser.TokenType.Affectation, new TextFormatting (Color.Black, Color.Transparent)); - formatting.Add ((int)Parser.TokenType.Keyword, new TextFormatting (Color.DarkCyan, Color.Transparent)); + formatting.Add ((int)BufferParser.TokenType.BlockComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); + formatting.Add ((int)BufferParser.TokenType.LineComment, new TextFormatting (Color.Gray, Color.Transparent, false, true)); + formatting.Add ((int)BufferParser.TokenType.Affectation, new TextFormatting (Color.Black, Color.Transparent)); + formatting.Add ((int)BufferParser.TokenType.Keyword, new TextFormatting (Color.DarkCyan, Color.Transparent)); parsing.Add (".crow", "Crow.Coding.XMLParser"); parsing.Add (".template", "Crow.Coding.XMLParser"); @@ -122,7 +122,7 @@ namespace Crow.Coding int printedCurrentLine = 0;//Index of the currentline in the PrintedLines array CodeBuffer buffer; - Parser parser; + BufferParser parser; List PrintedLines;//list of lines visible in the Editor depending on scrolling and folding Dictionary formatting = new Dictionary(); @@ -348,7 +348,7 @@ namespace Crow.Coding } } - Parser getParserFromExt (string extension) { + BufferParser getParserFromExt (string extension) { if (string.IsNullOrEmpty(extension)) return null; if (!parsing.ContainsKey(extension)) @@ -356,7 +356,7 @@ namespace Crow.Coding Type parserType = Type.GetType (parsing [extension]); if (parserType == null) return null; - return (Parser)Activator.CreateInstance (parserType, buffer ); + return (BufferParser)Activator.CreateInstance (parserType, buffer ); } #region Public Crow Properties diff --git a/CrowIDE/src/SourceEditor/StyleParser.cs b/CrowIDE/src/SourceEditor/StyleParser.cs index 9952b267..a4273ede 100644 --- a/CrowIDE/src/SourceEditor/StyleParser.cs +++ b/CrowIDE/src/SourceEditor/StyleParser.cs @@ -7,7 +7,7 @@ using System.Linq; namespace Crow.Coding { - public class StyleParser : Parser + public class StyleParser : BufferParser { enum States { init, classNames, members, value, endOfStatement } @@ -15,15 +15,13 @@ namespace Crow.Coding { } - #region Regular Expression for validity checks - private static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); - private static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}"); - private static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); - private static Regex rxDecimal = new Regex(@"[0-9]+"); - private static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); - #endregion - #region Character ValidityCheck + static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}"); + static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + static Regex rxDecimal = new Regex(@"[0-9]+"); + static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); + public bool nextCharIsValidCharStartName { get { return rxNameStartChar.IsMatch(new string(new char[]{Peek()})); } @@ -58,7 +56,7 @@ namespace Crow.Coding if (Peek () == '\n') { if (currentTok != TokenType.Unknown) - throw new ParsingException (this, "Unexpected end of line"); + throw new ParserException (currentLine, currentColumn, "Unexpected end of line"); Read (); eol = true; continue; @@ -80,31 +78,31 @@ namespace Crow.Coding break; case ',': if (curState != States.init || curState != States.classNames ) - throw new ParsingException (this, "Unexpected char ','"); + throw new ParserException (currentLine, currentColumn, "Unexpected char ','"); readAndResetCurrentTok (TokenType.UnaryOp, true); curState = States.classNames; break; case '{': if (!(curState == States.init || curState == States.classNames)) - throw new ParsingException (this, "Unexpected char '{'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char '{'"); readAndResetCurrentTok (TokenType.OpenBlock, true); curState = States.members; break; case '}': if (curState != States.members) - throw new ParsingException (this, "Unexpected char '}'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char '}'"); readAndResetCurrentTok (TokenType.CloseBlock, true); curState = States.classNames; break; case '=': if (curState == States.classNames) - throw new ParsingException (this, "Unexpected char '='"); + throw new ParserException (currentLine, currentColumn, "Unexpected char '='"); readAndResetCurrentTok (TokenType.Affectation, true); curState = States.value; break; case '"': if (curState != States.value) - throw new ParsingException (this, "Unexpected char '\"'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char '\"'"); readAndResetCurrentTok (TokenType.StringLitteralOpening, true); while (!eol) { @@ -115,7 +113,7 @@ namespace Crow.Coding break; } if (eol) - throw new ParsingException (this, "Unexpected end of line"); + throw new ParserException (currentLine, currentColumn, "Unexpected end of line"); saveAndResetCurrentTok (TokenType.StringLitteral); readAndResetCurrentTok (TokenType.StringLitteralClosing, true); @@ -123,17 +121,17 @@ namespace Crow.Coding break; case ';': if (curState != States.endOfStatement) - throw new ParsingException (this, "Unexpected end of statement"); + throw new ParserException (currentLine, currentColumn, "Unexpected end of statement"); readAndResetCurrentTok (TokenType.StatementEnding, true); curState = States.members; break; default: if (currentTok.Type != TokenType.Unknown) - throw new ParsingException (this, "error curtok not null"); + throw new ParserException (currentLine, currentColumn, "error curtok not null"); if (curState == States.value) - throw new ParsingException (this, "expecting value enclosed in '\"'"); + throw new ParserException (currentLine, currentColumn, "expecting value enclosed in '\"'"); if (curState == States.endOfStatement) - throw new ParsingException (this, "expecting end of statement"); + throw new ParserException (currentLine, currentColumn, "expecting end of statement"); if (nextCharIsValidCharStartName) { readToCurrTok (true); diff --git a/CrowIDE/src/SourceEditor/Token.cs b/CrowIDE/src/SourceEditor/Token.cs index 36f0242f..c6b8a3bb 100644 --- a/CrowIDE/src/SourceEditor/Token.cs +++ b/CrowIDE/src/SourceEditor/Token.cs @@ -24,7 +24,7 @@ namespace Crow.Coding { public struct Token { - public Parser.TokenType Type; + public BufferParser.TokenType Type; public string Content; public Point Start; public Point End; diff --git a/CrowIDE/src/SourceEditor/XMLParser.cs b/CrowIDE/src/SourceEditor/XMLParser.cs index 952e038b..59601a75 100644 --- a/CrowIDE/src/SourceEditor/XMLParser.cs +++ b/CrowIDE/src/SourceEditor/XMLParser.cs @@ -7,24 +7,24 @@ using System.Linq; namespace Crow.Coding { - public class XMLParser : Parser + public class XMLParser : BufferParser { public new enum TokenType { - Unknown = Parser.TokenType.Unknown, - WhiteSpace = Parser.TokenType.WhiteSpace, - NewLine = Parser.TokenType.NewLine, - LineComment = Parser.TokenType.LineComment, - BlockCommentStart = Parser.TokenType.BlockCommentStart, - BlockComment = Parser.TokenType.BlockComment, - BlockCommentEnd = Parser.TokenType.BlockCommentEnd, - ElementName = Parser.TokenType.Type, - AttributeName = Parser.TokenType.Identifier, - ElementClosing = Parser.TokenType.StatementEnding, - Affectation = Parser.TokenType.Affectation, - AttributeValueOpening = Parser.TokenType.StringLitteralOpening, - AttributeValueClosing = Parser.TokenType.StringLitteralClosing, - AttributeValue = Parser.TokenType.StringLitteral, - XMLDecl = Parser.TokenType.Preprocessor, + Unknown = BufferParser.TokenType.Unknown, + WhiteSpace = BufferParser.TokenType.WhiteSpace, + NewLine = BufferParser.TokenType.NewLine, + LineComment = BufferParser.TokenType.LineComment, + BlockCommentStart = BufferParser.TokenType.BlockCommentStart, + BlockComment = BufferParser.TokenType.BlockComment, + BlockCommentEnd = BufferParser.TokenType.BlockCommentEnd, + ElementName = BufferParser.TokenType.Type, + AttributeName = BufferParser.TokenType.Identifier, + ElementClosing = BufferParser.TokenType.StatementEnding, + Affectation = BufferParser.TokenType.Affectation, + AttributeValueOpening = BufferParser.TokenType.StringLitteralOpening, + AttributeValueClosing = BufferParser.TokenType.StringLitteralClosing, + AttributeValue = BufferParser.TokenType.StringLitteral, + XMLDecl = BufferParser.TokenType.Preprocessor, ElementStart = 50, ElementEnd = 51, } @@ -82,7 +82,7 @@ namespace Crow.Coding } #endregion - public override void SetLineInError (ParsingException ex) + public override void SetLineInError (ParserException ex) { base.SetLineInError (ex); //buffer[ex.Line].Tokens.EndingState = (int)States.init; @@ -111,7 +111,7 @@ namespace Crow.Coding if (Peek () == '\n') { if (currentTok != TokenType.Unknown) - throw new ParsingException (this, "Unexpected end of line"); + throw new ParserException (currentLine, currentColumn, "Unexpected end of line"); Read (); eol = true; continue; @@ -122,7 +122,7 @@ namespace Crow.Coding Debugger.Break (); currentTok.Start = CurrentPosition; - currentTok.Type = (Parser.TokenType)TokenType.BlockComment; + currentTok.Type = (BufferParser.TokenType)TokenType.BlockComment; currentTok += ReadLineUntil ("-->"); if (Peek (3) == "-->") { readToCurrTok (3); @@ -138,11 +138,11 @@ namespace Crow.Coding switch (Peek()) { case '?': if (curState != States.init) - throw new ParsingException (this, "xml decl may appear only on first line"); + throw new ParserException (currentLine, currentColumn, "xml decl may appear only on first line"); readToCurrTok (); currentTok += ReadLineUntil ("?>"); if (Peek (2) != "?>") - throw new ParsingException (this, "expecting '?>'"); + throw new ParserException (currentLine, currentColumn, "expecting '?>'"); readToCurrTok (2); saveAndResetCurrentTok (TokenType.XMLDecl); curState = States.prolog; @@ -153,7 +153,7 @@ namespace Crow.Coding case '-': readToCurrTok (); if (Peek () != '-') - throw new ParsingException (this, "Expecting comment start tag"); + throw new ParserException (currentLine, currentColumn, "Expecting comment start tag"); readToCurrTok (); currentTok += ReadLineUntil ("--"); if (Peek (3) == "-->") { @@ -163,12 +163,12 @@ namespace Crow.Coding saveAndResetCurrentTok (TokenType.BlockComment); break; default: - throw new ParsingException(this, "error"); + throw new ParserException (currentLine, currentColumn, "error"); } break; default: if (!(curState == States.Content || curState == States.XML || curState == States.init || curState == States.prolog)) - throw new ParsingException (this, "Unexpected char: '<'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char: '<'"); if (Peek () == '/') { curState = States.EndTag; readToCurrTok (); @@ -179,7 +179,7 @@ namespace Crow.Coding } if (!nextCharIsValidCharStartName) - throw new ParsingException (this, "Expected element name"); + throw new ParserException (currentLine, currentColumn, "Expected element name"); readToCurrTok (true); while (nextCharIsValidCharName) @@ -191,10 +191,10 @@ namespace Crow.Coding break; case '/': if (curState != States.StartTag) - throw new ParsingException (this, "Unexpected char: '/'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char: '/'"); readToCurrTok (true); if (Peek () != '>') - throw new ParsingException (this, "Expecting '>'"); + throw new ParserException (currentLine, currentColumn, "Expecting '>'"); readAndResetCurrentTok (TokenType.ElementEnd); curState = States.XML; @@ -209,14 +209,14 @@ namespace Crow.Coding curState = States.Content; break; default: - throw new ParsingException (this, "Unexpected char: '>'"); + throw new ParserException (currentLine, currentColumn, "Unexpected char: '>'"); } break; default: switch (curState) { case States.StartTag: if (!nextCharIsValidCharStartName) - throw new ParsingException (this, "Expected attribute name"); + throw new ParserException (currentLine, currentColumn, "Expected attribute name"); readToCurrTok (true); while (nextCharIsValidCharName) readToCurrTok (); @@ -225,14 +225,14 @@ namespace Crow.Coding SkipWhiteSpaces (); if (Peek () != '=') - throw new ParsingException (this, "Expecting: '='"); + throw new ParserException (currentLine, currentColumn, "Expecting: '='"); readAndResetCurrentTok (TokenType.Affectation, true); SkipWhiteSpaces (); char openAttVal = Peek (); if (openAttVal != '"' && openAttVal != '\'') - throw new ParsingException (this, "Expecting attribute value enclosed either in '\"' or in \"'\""); + throw new ParserException (currentLine, currentColumn, "Expecting attribute value enclosed either in '\"' or in \"'\""); readAndResetCurrentTok (TokenType.AttributeValueOpening, true); currentTok.Start = CurrentPosition; @@ -240,11 +240,11 @@ namespace Crow.Coding saveAndResetCurrentTok (TokenType.AttributeValue); if (Peek () != openAttVal) - throw new ParsingException (this, string.Format ("Expecting {0}", openAttVal)); + throw new ParserException (currentLine, currentColumn, string.Format ("Expecting {0}", openAttVal)); readAndResetCurrentTok (TokenType.AttributeValueClosing, true); break; default: - throw new ParsingException (this, "unexpected char: " + Peek ()); + throw new ParserException (currentLine, currentColumn, "unexpected char: " + Peek ()); } break; } @@ -283,7 +283,7 @@ namespace Crow.Coding if (tokPtr < cl.Tokens.Count) { if ((XMLParser.TokenType)cl.Tokens [tokPtr].Type == TokenType.ElementName && cl.Tokens [tokPtr].Content != currentNode.Name) - throw new ParsingException (this, "Closing tag mismatch"); + throw new ParserException (currentLine, currentColumn, "Closing tag mismatch"); } currentNode.EndLine = cl; currentNode = currentNode.Parent; diff --git a/CrowIDE/ui/IDE.style b/CrowIDE/ui/IDE.style index d7212053..ed964dca 100644 --- a/CrowIDE/ui/IDE.style +++ b/CrowIDE/ui/IDE.style @@ -1,25 +1,25 @@ icon { - Width=14; - Height=14; + Width="14"; + Height="14"; } MemberViewLabel { - Margin=1; - Height=Fit; - Width=50%; - Background=White; + Margin="1"; + Height="Fit"; + Width="50%"; + Background="White"; } MemberViewHStack { - Focusable=true; - Height=Fit; - Spacing=1; - MouseEnter={Background=UnitedNationsBlue}; - MouseLeave={Background=Transparent}; + Focusable="true"; + Height="Fit"; + Spacing="1"; + MouseEnter="{Background=UnitedNationsBlue}"; + MouseLeave="{Background=Transparent}"; } IcoBut { - Template = #Crow.Coding.ui.IcoBut.template; - MinimumSize = 10,10; - Width = 8; - Height = 14; - Background = White; + Template = "#Crow.Coding.ui.IcoBut.template"; + MinimumSize = "10,10"; + Width = "8"; + Height = "14"; + Background = "White"; } \ No newline at end of file diff --git a/Default.style b/Default.style index 11a22191..2e9e72a1 100644 --- a/Default.style +++ b/Default.style @@ -1,184 +1,184 @@ Button, CheckBox, RadioButton, ComboBox, Expandable, MessageBox, Popper, Slider, Spinner, TextBox { - Focusable = true; - Height = Fit; + Focusable = "true"; + Height = "Fit"; } Border { - Foreground = Gray; + Foreground = "Gray"; } -CheckBox { Caption = CheckBox; } -RadioButton { Caption = RadioButton; } -Expandable { Caption = Expandable; } -Popper { Caption = Popper;} -GroupBox { Caption = Group Box; } +CheckBox { Caption = "CheckBox"; } +RadioButton { Caption = "RadioButton"; } +Expandable { Caption = "Expandable"; } +Popper { Caption = "Popper";} +GroupBox { Caption = "Group Box"; } ControlBorder { - BorderWidth = 1; - Foreground = Jet; - Background = Transparent; + BorderWidth = "1"; + Foreground = "Jet"; + Background = "Transparent"; } ControlCaption { - Foreground = Gray; - MouseEnter = {Foreground=White}; - MouseLeave = {Foreground=Gray}; + Foreground = "Gray"; + MouseEnter = "{Foreground=White}"; + MouseLeave = "{Foreground=Gray}"; } Icon { - Margin=1; - Width=12; - Height=12; + Margin = "1"; + Width = "12"; + Height = "12"; } Wrapper { - Orientation = Vertical; + Orientation = "Vertical"; } Button { - Caption = Button; - Width = Fit; + Caption = "Button"; + Width = "Fit"; } Label { - Height = Fit; - Width = Fit; - Margin = 0; + Height = "Fit"; + Width = "Fit"; + Margin = "0"; } Menu { - Margin = 1; - Background = vgradient|0:DimGray|1:Onyx; - Height = Fit; - Width = Stretched; - VerticalAlignment = Top; - SelectionBackground = Transparent; + Margin = "1"; + Background = "vgradient|0:DimGray|1:Onyx"; + Height = "Fit"; + Width = "Stretched"; + VerticalAlignment = "Top"; + SelectionBackground = "Transparent"; } MenuItem { - Caption = MenuItem; - Width = Stretched; - Height = Fit; - Background = Transparent; - Foreground = LightGray; - MouseEnter = {Background = vgradient|0:UnitedNationsBlue|1:Onyx;Foreground=White;} - MouseLeave = {Foreground=LightGray;Background=Transparent;} - SelectionBackground = Transparent; + Caption = "MenuItem"; + Width = "Stretched"; + Height = "Fit"; + Background = "Transparent"; + Foreground = "LightGray"; + MouseEnter = "{Background = vgradient|0:UnitedNationsBlue|1:Onyx;Foreground=White;}"; + MouseLeave = "{Foreground=LightGray;Background=Transparent;}"; + SelectionBackground = "Transparent"; } Docker { - AllowDrop = true; + AllowDrop = "true"; } DockWindow { - AllowDrag = true; + AllowDrag = "true"; } MessageBox { - Background = 0.3,0.3,0.3,0.3; - Width = Fit; - Title=MessageBox; - Font = serif, 12; - MinimumSize = 200,120; - AlwaysOnTop = true; + Background = "0.3,0.3,0.3,0.3"; + Width = "Fit"; + Caption="MessageBox"; + Font = "serif, 12"; + MinimumSize = "200,120"; + AlwaysOnTop = "true"; } Slider { - Background = vgradient|0:Black|0.1:Gray|0.9:Gray|1:LightGray; - Foreground = Gray; - Width = Fit; + Background = "vgradient|0:Black|0.1:Gray|0.9:Gray|1:LightGray"; + Foreground = "Gray"; + Width = "Fit"; } Splitter { - Focusable = true; - Background = DimGray; + Focusable = "true"; + Background = "DimGray"; } Spinner { - Foreground = DimGray; + Foreground = "DimGray"; } TabView { - CacheEnabled = false; + CacheEnabled = "false"; } TabItem { - Caption = TabItem; - Focusable = true; - CacheEnabled = false; + Caption = "TabItem"; + Focusable = "true"; + CacheEnabled = "false"; } TextBox { - Background = White; - Foreground = Black; - Selectable = True; - Text = TextBox; - Margin = 1; + Background = "White"; + Foreground = "Black"; + Selectable = "True"; + Text = "TextBox"; + Margin = "1"; } Window { - Caption = Window; - Focusable = true; - MinimumSize=5,5; - Width = 150; - Height = 150; + Caption = "Window"; + Focusable = "true"; + MinimumSize="5,5"; + Width = "150"; + Height = "150"; } ToolWindow { - Caption = Window; - Template = #Crow.ToolWindow.template; - Focusable = true; - MinimumSize=50,50; - Width = 150; - Height = 150; + Caption = "Window"; + Template = "#Crow.ToolWindow.template"; + Focusable = "true"; + MinimumSize="50,50"; + Width = "150"; + Height = "150"; } DocksView { - AllowDrop = true; + AllowDrop = "true"; } DockingView { - Focusable = true; - AllowDrag = true; + Focusable = "true"; + AllowDrag = "true"; } FileDialog { - Template = #Crow.FileDialog.template; - AlwaysOnTop = true; - Focusable = true; - MinimumSize=50,50; - Width = 500; - Height = 300; + Template = "#Crow.FileDialog.template"; + AlwaysOnTop = "true"; + Focusable = "true"; + MinimumSize="50,50"; + Width = "500"; + Height = "300"; } ProgressBar { - Foreground = vgradient|0:BlueCrayola|0.5:SkyBlue|1:BlueCrayola; + Foreground = "vgradient|0:BlueCrayola|0.5:SkyBlue|1:BlueCrayola"; } ScrollBar { - Maximum = 0; - Value = 0; + Maximum = "0"; + Value = "0"; } Scroller { - CacheEnabled = false; + CacheEnabled = "false"; } Control { - Margin=0; - Spacing=3; + Margin="0"; + Spacing="3"; } SaturationValueSelector { - Foreground=Red; + Foreground="Red"; } HueSelector { - ClipToClientRect=False; + ClipToClientRect="False"; } ColorSpinner { - Minimum = 0; - Maximum = 255; - SmallIncrement = 1; + Minimum = "0"; + Maximum = "255"; + SmallIncrement = "1"; } HSVSpinner { - Minimum = 0; - Maximum = 1; - SmallIncrement = 0.01; + Minimum = "0"; + Maximum = "1"; + SmallIncrement = "0.01"; } TxtInFileDialog { - Margine = 1; - Font = droid, 12; + Margine = "1"; + Font = "droid, 12"; } CheckBoxAlt { - Template= #Crow.Templates.CheckBox2.template; - Background = Transparent; - Checked={Background=DarkSlateGray;Foreground=LightGray;}; - Unchecked = {Background=Transparent;Foreground=DimGray;}; + Template= "#Crow.Templates.CheckBox2.template"; + Background = "Transparent"; + Checked="{Background=DarkSlateGray;Foreground=LightGray;}"; + Unchecked = "{Background=Transparent;Foreground=DimGray;}"; } ArrowBut { - MouseRepeat=true; - Height=Fit; - Width=Fit; - Focusable=true; - Foreground=Jet; - Background=hgradient|0:Gray|1:Jet; - MouseDown={Background=hgradient|0:White|0.4:BlueCrayola|1:Jet}; - MouseUp={Background=hgradient|0:Gray|1:Jet}; - MouseEnter={Foreground=Black}; - MouseLeave={Foreground=Jet}; + MouseRepeat="true"; + Height="Fit"; + Width="Fit"; + Focusable="true"; + Foreground="Jet"; + Background="hgradient|0:Gray|1:Jet"; + MouseDown="{Background=hgradient|0:White|0.4:BlueCrayola|1:Jet}"; + MouseUp="{Background=hgradient|0:Gray|1:Jet}"; + MouseEnter="{Foreground=Black}"; + MouseLeave="{Foreground=Jet}"; } \ No newline at end of file diff --git a/src/ParsingException.cs b/src/ParsingException.cs new file mode 100644 index 00000000..e3bd51c9 --- /dev/null +++ b/src/ParsingException.cs @@ -0,0 +1,20 @@ +using System; + +namespace Crow.Coding +{ + public class ParserException : Exception + { + public int Line; + public int Column; + public ParserException(int line, int column, string txt) + : base(string.Format("Parser exception ({0},{1}): {2}", line, column, txt)) + { + Line = line; + Column = column; + } + public ParserException(int line, int column, string txt, Exception innerException) + : base(string.Format("Parser exception ({0},{1}): {2}", line, column, txt), innerException) + {} + } +} + diff --git a/src/StyleReader.cs b/src/StyleReader.cs index 5a00a594..28eaf780 100644 --- a/src/StyleReader.cs +++ b/src/StyleReader.cs @@ -28,6 +28,8 @@ using System; using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Text.RegularExpressions; +using Crow.Coding; namespace Crow { @@ -37,12 +39,49 @@ namespace Crow //TODO: style key shared by different class may use only first encouneter class setter, which can cause bug. public class StyleReader : StreamReader { - enum readerState { classNames, propertyName, expression } - readerState state = readerState.classNames; + enum States { init, classNames, members, value, endOfStatement } + + States curState = States.init; + string resourceId; int column = 1; int line = 1; + #region Character ValidityCheck + static Regex rxValidChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + static Regex rxNameStartChar = new Regex(@"_|\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}"); + static Regex rxNameChar = new Regex(@"\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nl}|\p{Mn}|\p{Mc}|\p{Nd}|\p{Pc}|\p{Cf}"); + static Regex rxDecimal = new Regex(@"[0-9]+"); + static Regex rxHexadecimal = new Regex(@"[0-9a-fA-F]+"); + + public bool nextCharIsValidCharStartName + { + get { return rxNameStartChar.IsMatch(new string(new char[]{PeekChar()})); } + } + public bool nextCharIsValidCharName + { + get { return rxNameChar.IsMatch(new string(new char[]{PeekChar()})); } + } + #endregion + + char ReadChar () { + column++; + return (Char)Read(); + } + char PeekChar () { + return (Char)Peek(); + } + void SkipWhiteSpaceAndLineBreak (){ + while (!EndOfStream){ + if (!PeekChar ().IsWhiteSpaceOrNewLine ()) + break; + if (ReadChar () == '\n') { + line++; + column = 0; + } + } + } + public StyleReader (Dictionary styling, Stream stream, string resId) : base(stream) { @@ -52,116 +91,95 @@ namespace Crow List targetsClasses = new List (); string currentProperty = ""; - int curlyBracketCount = 0; - while (!EndOfStream) { - char c = (Char)Read (); - if (c == '/' && !EndOfStream) { - if ((char)Peek () == '/') {//process comment, skip until newline - ReadLine (); - continue; - } - } - switch (state) { - case readerState.classNames: - if (c.IsWhiteSpaceOrNewLine () || c == ',' || c == '{') { - if (!string.IsNullOrEmpty (token)) - targetsClasses.Add (token); - if (c == '{') - state = readerState.propertyName; - token = ""; - }else if (c=='='){ - //this file contains only properties, - //resource Id (minus .style extention) will determine the single target class - if (targetsClasses.Count > 1) - throwParserException ("Unexpected token '='"); - else if (targetsClasses.Count == 1) { - if (!string.IsNullOrEmpty (token)) - throwParserException ("Unexpected token '='"); - currentProperty = targetsClasses [0]; - targetsClasses [0] = styleKey; - }else{ - if (string.IsNullOrEmpty (token)) - throwParserException ("Unexpected token '='"); - targetsClasses.Add (styleKey); - currentProperty = token; - token = ""; - } - state = readerState.expression; - }else - token += c; + SkipWhiteSpaceAndLineBreak (); + if (EndOfStream) break; - case readerState.propertyName: - if (c.IsWhiteSpaceOrNewLine () || c == '=') { - if (!string.IsNullOrEmpty (token)) - currentProperty = token; - if (c == '=') - state = readerState.expression; - token = ""; - }else if (c == '}'){ - if (!string.IsNullOrEmpty (token)) - throwParserException ("Unexpected token '" + c + "'"); - targetsClasses = new List (); - currentProperty = ""; - state = readerState.classNames; - } else - token += c; + switch (Peek()) { + case '/': + ReadChar (); + if (PeekChar () != '/') + throw new ParserException (line, column, "Unexpected char '/'"); + ReadLine (); + break; + case ',': + ReadChar (); + if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token)) + throw new ParserException (line, column, "Unexpected char ','"); + targetsClasses.Add (token); + token = ""; + curState = States.classNames; + break; + case '{': + ReadChar (); + if (!(curState == States.init || curState == States.classNames) || string.IsNullOrEmpty (token)) + throw new ParserException (line, column, "Unexpected char '{'"); + targetsClasses.Add (token); + token = ""; + curState = States.members; + break; + case '}': + ReadChar (); + if (curState != States.members) + throw new ParserException (line, column, "Unexpected char '}'"); + curState = States.classNames; + targetsClasses.Clear (); + break; + case '=': + ReadChar (); + if (!(curState == States.init || curState == States.members)) + throw new ParserException (line, column, "Unexpected char '='"); + currentProperty = token; + token = ""; + curState = States.value; break; - case readerState.expression: - bool expressionIsFinished = false; - if (curlyBracketCount == 0) { - if (c == '{'){ - if (!string.IsNullOrEmpty(token.Trim())) - throwParserException ("Unexpected token '{'"); - curlyBracketCount++; - token = "{"; - }else if (c == '}') - throwParserException ("Unexpected token '{'"); - else if (c == ';') { - expressionIsFinished = true; - } else - token += c; - } else { - if (c == '{') - curlyBracketCount++; - else if (c == '}') { - curlyBracketCount--; - if (curlyBracketCount == 0) - expressionIsFinished = true; + case '"': + if (curState != States.value) + throw new ParserException (line, column, "Unexpected char '\"'"); + ReadChar (); + + while (!EndOfStream) { + char c = PeekChar(); + if (c == '\"') { + ReadChar (); + break; } - token += c; + token += ReadChar(); + if (c == '\\' && !EndOfStream) + token += ReadChar(); + } + curState = States.endOfStatement; + break; + case ';': + if (curState != States.endOfStatement) + throw new ParserException (line, column, "Unexpected end of statement"); + ReadChar (); + foreach (string tc in targetsClasses) { + if (!styling.ContainsKey (tc)) + styling [tc] = new Style (); + else if (styling [tc].ContainsKey (currentProperty)) + continue; + styling [tc] [currentProperty] = token; + System.Diagnostics.Debug.WriteLine ("Style: {0}.{1} = {2}", tc, currentProperty, token); } - if (expressionIsFinished) { - if (!string.IsNullOrEmpty (token)) { - string expression = token.Trim (); + token = ""; + curState = States.members; + break; + default: + if (curState == States.value) + throw new ParserException (line, column, "expecting value enclosed in '\"'"); + if (curState == States.endOfStatement) + throw new ParserException (line, column, "expecting end of statement"); - foreach (string tc in targetsClasses) { - if (!styling.ContainsKey (tc)) - styling [tc] = new Style (); - else if (styling [tc].ContainsKey (currentProperty)) - continue; - styling [tc] [currentProperty] = expression; - } - token = ""; - } - //allow omiting ';' if curly bracket close expression - while (!EndOfStream) { - if (Char.IsWhiteSpace((char)Peek())) - Read(); - else - break; - } - if (this.Peek () == ';') - this.Read (); - state = readerState.propertyName; + if (nextCharIsValidCharStartName) { + token += ReadChar(); + while (nextCharIsValidCharName) + token += ReadChar(); } break; } } - - if (curlyBracketCount > 0) - throwParserException ("Unexpected end of file"); } public override int Read ()