diff --git a/dwarf-cs/dwarf.core/lang/Lexer.cs b/dwarf-cs/dwarf.core/lang/Lexer.cs index 004bc92..de5d1d4 100644 --- a/dwarf-cs/dwarf.core/lang/Lexer.cs +++ b/dwarf-cs/dwarf.core/lang/Lexer.cs @@ -47,15 +47,42 @@ internal class NumberRule : ITokenRule { public bool Check(char c, int pos) { - if (pos == 0 && (c == '-' && c == '+')) - return true; + return Char.IsNumber(c); + } + + public Token CreateToken(string src) + { + return new ConstantToken(long.Parse(src)); + } + } + + internal class SignedNumberRule : ITokenRule + { + public bool Check(char c, int pos) + { + if (pos == 0) + return c == '-' || c == '+'; else return Char.IsNumber(c); } public Token CreateToken(string src) { - return new ConstantToken(long.Parse(src)); + long c; + + // FIXME: Это по сути затычка для ситуации, когда src не является + // правильной константой, но check возвращает true потому, + // что проверяет только один символ. По сути это ошибка + // дизайна. + + if (Int64.TryParse(src, out c)) + { + return new ConstantToken(c); + } + else + { + return null; + } } } @@ -75,10 +102,10 @@ public Token CreateToken(string src) internal class Matcher { private ITokenRule rule; - private bool stop; private string matched; public Token Token { get; private set; } + public bool Stop { get; private set; } public Matcher(ITokenRule rule) { @@ -87,14 +114,14 @@ public Matcher(ITokenRule rule) public void Reset() { - stop = false; + Stop = false; matched = String.Empty; Token = null; } public void Update(char c) { - if (stop) + if (Stop) return; if (rule.Check(c, matched.Length)) @@ -103,10 +130,10 @@ public void Update(char c) } else { - stop = true; + Stop = true; } - if (stop && matched.Length > 0) + if (Stop && matched.Length > 0) { Token = rule.CreateToken(matched); } @@ -119,6 +146,9 @@ public class Lexer { new WhitespaceRule(), + new NumberRule(), + new SignedNumberRule(), + new KeywordRule("if"), new KeywordRule("then"), new KeywordRule("else"), @@ -143,7 +173,6 @@ public class Lexer new KeywordRule(":="), new IdentifierRule(), - new NumberRule(), }; public IEnumerable Tokenize(string source) @@ -174,12 +203,16 @@ public IEnumerable Tokenize(string source) } Token token = null; - foreach (var matcher in matchers) + + if (matchers.All(m => m.Stop)) { - if (matcher.Token != null) + foreach (var matcher in matchers) { - token = matcher.Token; - break; + if (matcher.Token != null) + { + token = matcher.Token; + break; + } } } diff --git a/dwarf-cs/tests/LexerTests.cs b/dwarf-cs/tests/LexerTests.cs index ad32038..e89afe0 100644 --- a/dwarf-cs/tests/LexerTests.cs +++ b/dwarf-cs/tests/LexerTests.cs @@ -48,5 +48,24 @@ public void IfThenElseTest() Assert.AreEqual(expected, actual); } + + [Test] + public void ConstTest() + { + var source = Multiline( + "a := 10", + "a := -12", + "a := +13" + ); + + var lexer = new Lexer(); + var actual = String.Join("", lexer.Tokenize(source)); + + const string expected = "[a] := <10> " + + "[a] := <-12> " + + "[a] := <13> "; + + Assert.AreEqual(expected, actual); + } } }