diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2018-02-28 00:51:17 +0100 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2018-02-28 00:51:17 +0100 |
| commit | d5cf794076899803b9a34eb46d3b2e34f3e3cfbc (patch) | |
| tree | 783e637acbeab9c65777c345ae834a93ab7fc86a /src/StyleReader.cs | |
| parent | 8e82014a444722660692bbf730017651ddb6c88c (diff) | |
change styling grammar for value now enclose in double quoteStyleModif
Diffstat (limited to 'src/StyleReader.cs')
| -rw-r--r-- | src/StyleReader.cs | 220 |
1 files changed, 119 insertions, 101 deletions
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<string, Style> styling, Stream stream, string resId) : base(stream) { @@ -52,116 +91,95 @@ namespace Crow List<string> targetsClasses = new List<string> (); 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<string> (); - 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 () |