diff --git a/BibtexLibrary.Documentation/BibtexLibrary.Documentation.shfbproj b/BibtexLibrary.Documentation/BibtexLibrary.Documentation.shfbproj new file mode 100644 index 0000000..f778cb5 --- /dev/null +++ b/BibtexLibrary.Documentation/BibtexLibrary.Documentation.shfbproj @@ -0,0 +1,135 @@ + + + + + Debug + AnyCPU + 2.0 + 617b9073-b902-49a2-b28d-4d790595d7cd + 2017.9.26.0 + + BibtexLibrary.Documentation + BibtexLibrary.Documentation + BibtexLibrary.Documentation + + .NET Framework 4.5 + ..\..\doc\BibTex\ + BibtexLibrary.Documentation + en-US + + + + + + + + + + + + + Website + C# + VS2013 + True + True + False + False + OnlyWarningsAndErrors + 100 + BibtexLibrary + 1.0.0.0 + MemberName + AboveNamespaces + False + True + 2 + False + Blank + AutoDocumentCtors, AutoDocumentDispose + False + + + {@TokenFiles} + + + + + {@HelpFormatOutputPaths} + + + + + + + + {@SyntaxFilters} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OnBuildSuccess + + \ No newline at end of file diff --git a/BibtexLibrary.Documentation/Content/VersionHistory/VersionHistory.aml b/BibtexLibrary.Documentation/Content/VersionHistory/VersionHistory.aml new file mode 100644 index 0000000..444028f --- /dev/null +++ b/BibtexLibrary.Documentation/Content/VersionHistory/VersionHistory.aml @@ -0,0 +1,33 @@ + + + + + The topics in this section describe the various changes made to the [TODO: Project Title] over the +life of the project. + + +
+ Version History + + Select a version below to see a description of its changes. + + + + + + + + [TODO: Add links to each specific version page] + + + + + +
+ + + + + +
+
diff --git a/BibtexLibrary.Documentation/Content/VersionHistory/v1.0.0.0.aml b/BibtexLibrary.Documentation/Content/VersionHistory/v1.0.0.0.aml new file mode 100644 index 0000000..8d20206 --- /dev/null +++ b/BibtexLibrary.Documentation/Content/VersionHistory/v1.0.0.0.aml @@ -0,0 +1,28 @@ + + + + + Version [TODO: Version] was released on [TODO: Date]. + + + +
+ Changes in This Release + + + + + [TODO: Add change items here] + + + + + +
+ + + + + +
+
diff --git a/BibtexLibrary.Documentation/Content/Welcome.aml b/BibtexLibrary.Documentation/Content/Welcome.aml new file mode 100644 index 0000000..1233b4d --- /dev/null +++ b/BibtexLibrary.Documentation/Content/Welcome.aml @@ -0,0 +1,55 @@ + + + + + This is a sample conceptual topic. You can use this as a starting point for adding more conceptual +content to your help project. + + +
+ Getting Started + + To get started, add a documentation source to the project (a Visual Studio solution, project, or +assembly and XML comments file). See the Getting Started topics in the Sandcastle Help +File Builder's help file for more information. The following default items are included in this project: + + + + ContentLayout.content - Use the content layout file to manage the +conceptual content in the project and define its layout in the table of contents. + + + + The .\media folder - Place images in this folder that you will reference +from conceptual content using medialLink or mediaLinkInline +elements. If you will not have any images in the file, you may remove this folder. + + + + The .\icons folder - This contains a default logo for the help file. You +may replace it or remove it and the folder if not wanted. If removed or if you change the file name, update +the Transform Args project properties page by removing or changing the filename in the +logoFile transform argument. Note that unlike images referenced from conceptual topics, +the logo file should have its BuildAction property set to Content. + + + + The .\Content folder - Use this to store your conceptual topics. You may +name the files and organize them however you like. One suggestion is to lay the files out on disk as you have +them in the content layout file as shown in this project but the choice is yours. Files can be added via the +Solution Explorer or from within the content layout file editor. Files must appear in the content layout file +in order to be compiled into the help file. + + + + See the Conceptual Content topics in the Sandcastle Help File Builder's +help file for more information. See the Sandcastle MAML Guide for details on Microsoft +Assistance Markup Language (MAML) which is used to create these topics. + +
+ + + + +
+
diff --git a/BibtexLibrary.Documentation/ContentLayout.content b/BibtexLibrary.Documentation/ContentLayout.content new file mode 100644 index 0000000..1e04cbc --- /dev/null +++ b/BibtexLibrary.Documentation/ContentLayout.content @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BibtexLibrary.Documentation/icons/Help.png b/BibtexLibrary.Documentation/icons/Help.png new file mode 100644 index 0000000..945e89f Binary files /dev/null and b/BibtexLibrary.Documentation/icons/Help.png differ diff --git a/BibtexLibrary.Standard/BibtexEntry.cs b/BibtexLibrary.Standard/BibtexEntry.cs new file mode 100644 index 0000000..88ae1a7 --- /dev/null +++ b/BibtexLibrary.Standard/BibtexEntry.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace BibtexLibrary +{ + /// + /// Single entry in Bibtex file + /// + public class BibtexEntry + { + /// + /// The tags + /// + private Dictionary _tags = new Dictionary(); + /// + /// Gets or sets the type. + /// + /// + /// The type. + /// + public string Type { get; set; } + + /// + /// Gets or sets the key. + /// + /// + /// The key. + /// + public string Key { get; set; } + + /// + /// Gets or sets the tags. + /// + /// + /// The tags. + /// + public Dictionary Tags + { + get { return _tags; } + set { _tags = value; } + } + } +} diff --git a/BibtexLibrary.Standard/BibtexFile.cs b/BibtexLibrary.Standard/BibtexFile.cs new file mode 100644 index 0000000..1ea2b61 --- /dev/null +++ b/BibtexLibrary.Standard/BibtexFile.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; + +namespace BibtexLibrary +{ + /// + /// Collection of Bibtex entries + /// + public class BibtexFile + { + private ICollection _entries = new List(); + private Dictionary _stringDefinitions = new Dictionary(); + + /// + /// Gets or sets the string definitions. + /// + /// + /// The string definitions. + /// + public Dictionary StringDefinitions + { + get { return _stringDefinitions; } + set { _stringDefinitions = value; } + } + + /// + /// Gets or sets the preamble. + /// + /// + /// The preamble. + /// + public ICollection Preamble { get; set; } + + /// + /// Gets or sets the entries. + /// + /// + /// The entries. + /// + public ICollection Entries + { + get { return _entries; } + set { _entries = value; } + } + } +} diff --git a/BibtexLibrary.Standard/BibtexImporter.cs b/BibtexLibrary.Standard/BibtexImporter.cs new file mode 100644 index 0000000..ba1a013 --- /dev/null +++ b/BibtexLibrary.Standard/BibtexImporter.cs @@ -0,0 +1,38 @@ +using BibtexLibrary.Parser; +using BibtexLibrary.Tokenizer; +using System; +using System.IO; + +namespace BibtexLibrary +{ + /// + /// Parser + /// + public class BibtexImporter + { + + + /// + /// Froms the string. + /// + /// The text. + /// + public static BibtexFile FromString(string text) + { + BibtexParser file = new BibtexParser(new Tokenizer.Tokenizer(new ExpressionDictionary(), text)); + + return file.Parse(); + } + + /// + /// Froms the stream. + /// + /// The reader. + /// + /// + public static BibtexFile FromStream(StreamReader reader) + { + throw new NotImplementedException(); + } + } +} diff --git a/BibtexLibrary.Standard/BibtexLibrary.Standard.csproj b/BibtexLibrary.Standard/BibtexLibrary.Standard.csproj new file mode 100644 index 0000000..b913eba --- /dev/null +++ b/BibtexLibrary.Standard/BibtexLibrary.Standard.csproj @@ -0,0 +1,80 @@ + + + + netstandard2.0;net45;net40 + imbSCI - Copy.ico + True + imbSCI.BibtexLibrary.Standard + 1.5.28 + BibtexLibrary .NET Standard - for imbSCI + + http://doc.veles.rs/imbSCI.ico + http://blog.veles.rs/ + http://doc.veles.rs/LICENCE.txt + Copyright (C) 2018 + Maikel Hofman's BibtexLibrary - multi-target / cross-platform fork by Goran Grubić (imbVeles). + +Original repository: https://github.com/MaikelH/BibtexLibrary + en-US + Targets: .NET 4.0*, .NET 4.5 and .NET Core 2.0 i.e ready for use in cross-platform application development. + + BibTex, Excel + https://github.com/gorangrubic/BibtexLibrary + GitHub + Maikel Hofman, Goran Grubić + imbVeles + 1.5.1.2 + 1.5.1.2 + imbSCI.BibtexLibrary.Standard + False + BibtexLibrary + true + key.snk + + + + + NETCORE;NETSTANDARD;NETSTANDARD2_0 + + + + NET40 + + + + NET45;NETFULL + + + + $(OutputPath)$(PackageId).xml + + + + True + True + False + False + False + True + SettingsVersion + None + 0 + + + + True + True + False + False + False + True + SettingsVersion + None + + + + + + + + diff --git a/BibtexLibrary.Standard/BibtexLibrary.Standard.xml b/BibtexLibrary.Standard/BibtexLibrary.Standard.xml new file mode 100644 index 0000000..0c8e20d --- /dev/null +++ b/BibtexLibrary.Standard/BibtexLibrary.Standard.xml @@ -0,0 +1,184 @@ + + + + BibtexLibrary.Standard + + + + + Single entry in Bibtex file + + + + + The tags + + + + + Gets or sets the type. + + + The type. + + + + + Gets or sets the key. + + + The key. + + + + + Gets or sets the tags. + + + The tags. + + + + + Collection of Bibtex entries + + + + + Gets or sets the string definitions. + + + The string definitions. + + + + + Gets or sets the preamble. + + + The preamble. + + + + + Gets or sets the entries. + + + The entries. + + + + + Parser + + + + + Froms the string. + + The text. + + + + + Froms the stream. + + The reader. + + + + + + Initializes a new instance of the class. + + The tokenizer. + + + + Parses this instance. + + + + + + Converts the parse node. + + The node. + + + + + Parses the input. + + The tokenizer. + + + + + Entries the specified tokenizer. + + The tokenizer. + + + + + Texts the specified tokenizer. + + The tokenizer. + + Expected type Text but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + + + + Openings the brace. + + The tokenizer. + Expected type OpeningBrace but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + + + + Closings the brace. + + The tokenizer. + Expected type ClosingBrace but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + + + + Commas the specified tokenizer. + + The tokenizer. + if set to true [optional]. + Expected type Comma but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + + + + Retrieves the tag values from the input. + + The tokenizer. + + + + + Return all the tokens in the inputstring. + + List of tokens + + + + Checks whether the scanner is at the end of the input. + + + + + Returns the previous n characters. + + + Previous characters in the tokenizer + + + + Base class for tokens + + + + diff --git a/BibtexLibrary.Standard/Parser/BibtexParser.cs b/BibtexLibrary.Standard/Parser/BibtexParser.cs new file mode 100644 index 0000000..7cc234d --- /dev/null +++ b/BibtexLibrary.Standard/Parser/BibtexParser.cs @@ -0,0 +1,370 @@ +using BibtexLibrary.Parser.Nodes; +using BibtexLibrary.Tokens; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace BibtexLibrary.Parser +{ + public class BibtexParser + { + private readonly Tokenizer.Tokenizer _tokenizer; + + /// + /// Initializes a new instance of the class. + /// + /// The tokenizer. + public BibtexParser(Tokenizer.Tokenizer tokenizer) + { + _tokenizer = tokenizer; + } + + /// + /// Parses this instance. + /// + /// + public BibtexFile Parse() + { + ParseNode node = ParseInput(_tokenizer); + BibtexFile fileObject = convertParseNode(node); + + return fileObject; + } + + /// + /// Converts the parse node. + /// + /// The node. + /// + private BibtexFile convertParseNode(ParseNode node) + { + Nodes.BibtexFile parseFile = (Nodes.BibtexFile)node; + + BibtexFile bibtex = new BibtexFile(); + + foreach (Entry entry in parseFile.Entries) + { + if (entry.Type == "String") + { + bibtex.StringDefinitions.Add(entry.Tags.First().Key, entry.Tags.First().Value); + } + else + { + BibtexEntry bibtexEntry = new BibtexEntry { Key = entry.Key, Type = entry.Type }; + + entry.Tags.ToList().ForEach(x => bibtexEntry.Tags.Add(x.Key, x.Value)); + + bibtex.Entries.Add(bibtexEntry); + } + } + + return bibtex; + } + + /// + /// Parses the input. + /// + /// The tokenizer. + /// + private ParseNode ParseInput(Tokenizer.Tokenizer tokenizer) + { + Nodes.BibtexFile file = new Nodes.BibtexFile(); + + while (!tokenizer.EndOfInput) + { + AbstractToken token = tokenizer.NextToken(); + + if (token.GetType() == typeof(At)) + { + file.Entries.Add(Entry(tokenizer)); + } + } + + return file; + } + + /// + /// Entries the specified tokenizer. + /// + /// The tokenizer. + /// + private Entry Entry(Tokenizer.Tokenizer tokenizer) + { + Entry entry = new Entry(); + + entry.Type = Text(tokenizer); + OpeningBrace(tokenizer); + + if (!entry.Type.Equals("String", StringComparison.OrdinalIgnoreCase)) + { + entry.Key = Text(tokenizer); + Comma(tokenizer); + } + + entry.Tags = Tags(tokenizer); + ClosingBrace(tokenizer); + + return entry; + } + + /// + /// Texts the specified tokenizer. + /// + /// The tokenizer. + /// + /// Expected type Text but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + private String Text(Tokenizer.Tokenizer tokenizer) + { + AbstractToken token = tokenizer.NextToken(); + + if (token.GetType() == typeof(Comma) || token.GetType() == typeof(Text)) + { + return token.GetValue(); + } + + throw new ParseException("Expected type Text but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25)); + } + + /// + /// Openings the brace. + /// + /// The tokenizer. + /// Expected type OpeningBrace but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + private void OpeningBrace(Tokenizer.Tokenizer tokenizer) + { + AbstractToken token = tokenizer.NextToken(); + + if (token.GetType() == typeof(OpeningBrace)) + { + return; + } + + throw new ParseException("Expected type OpeningBrace but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25)); + } + + /// + /// Closings the brace. + /// + /// The tokenizer. + /// Expected type ClosingBrace but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + private void ClosingBrace(Tokenizer.Tokenizer tokenizer) + { + AbstractToken token = tokenizer.NextToken(); + + if (token.GetType() == typeof(ClosingBrace)) + { + return; + } + + throw new ParseException("Expected type ClosingBrace but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25)); + } + + /// + /// Commas the specified tokenizer. + /// + /// The tokenizer. + /// if set to true [optional]. + /// Expected type Comma but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + private void Comma(Tokenizer.Tokenizer tokenizer, Boolean optional = false) + { + AbstractToken token = tokenizer.Peek(); + + if (token.GetType() == typeof(Comma)) + { + tokenizer.NextToken(); + return; + } + + if (optional) + { + return; + } + + throw new ParseException("Expected type Comma but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25)); + } + + public static Boolean MUTE_PEEK_EXCEPTIONS = true; + public static Int32 PARSER_EXCEPTIONS_LIMIT = 0; + + public List ParsingExceptions { get; set; } = new List(); + + + /// + /// Retrieves the tag values from the input. + /// + /// The tokenizer. + /// + private ICollection Tags(Tokenizer.Tokenizer tokenizer) + { + // This function needs some refactoring. + List tags = new List(); + + while (tokenizer.Peek().GetType() != typeof(ClosingBrace)) + { + Tag tag = new Tag { Key = Text(tokenizer) }; + Equals(tokenizer); + AbstractToken startToken = ValueStart(tokenizer); + + List tokens = new List(); + + bool keepProcessing = true; + int balance = 1; + + while (keepProcessing) + { + Type nextTokenType = null; + + // ------------------------------------ format failure protection + if (!MUTE_PEEK_EXCEPTIONS) + { + nextTokenType = tokenizer.Peek().GetType(); + } + else + { + try + { + nextTokenType = tokenizer.Peek().GetType(); + } + catch (Exception ex) + { + ParsingExceptions.Add(ex); + if (ParsingExceptions.Count() > PARSER_EXCEPTIONS_LIMIT) + { + throw; + } + } + } + + if (nextTokenType == null) + { + tokenizer.NextToken(); + + if (ParsingExceptions.Count() > PARSER_EXCEPTIONS_LIMIT) + { + keepProcessing = false; + + } + + continue; + + } + + // ------------------------------------ format failure protection + + + + if (nextTokenType == typeof(OpeningBrace)) + { + balance++; + } + + if ((startToken.GetType() == typeof(OpeningBrace) && nextTokenType == typeof(ClosingBrace))) + { + if (balance == 1) + { + keepProcessing = false; + ValueStop(tokenizer); + } + } + + if (nextTokenType == typeof(ClosingBrace)) + { + if (balance > 1) + { + balance--; + } + } + + // Double quotes are much more difficult to handle then the braces. The problem is that there is no distinction between + // start and stop quotes. This means we need to look forward to see what is behind the quote to see if it is a quote @ the end + // or the start of a new quote. + if (nextTokenType == typeof(ValueQuote)) + { + AbstractToken quote = tokenizer.NextToken(); + + Type nextType = tokenizer.Peek().GetType(); + if ((nextType == typeof(ClosingBrace) && balance == 1) || + nextType == typeof(Comma)) + { + // end of line found. + keepProcessing = false; + } + else + { + tokens.Add(quote); + continue; + } + } + + if (keepProcessing) + { + tokens.Add(tokenizer.NextToken()); + } + } + + tag.Value = tokens.Aggregate("", (s, token) => s + token.RawValue); + + Comma(tokenizer, true); + NewLine(tokenizer, true); + + tags.Add(tag); + } + + return tags; + } + + private void Equals(Tokenizer.Tokenizer tokenizer) + { + AbstractToken token = tokenizer.NextToken(); + + if (token.GetType() == typeof(Equals)) + { + return; + } + + throw new ParseException("Expected type Equals but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25)); + } + + private AbstractToken ValueStart(Tokenizer.Tokenizer tokenizer) + { + AbstractToken token = tokenizer.NextToken(); + + if (token.GetType() == typeof(OpeningBrace) || token.GetType() == typeof(ValueQuote)) + { + return token; + } + + throw new ParseException("Expected type Openingbrace or ValueQuote but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25)); + } + + private AbstractToken ValueStop(Tokenizer.Tokenizer tokenizer) + { + AbstractToken token = tokenizer.NextToken(); + + if (token.GetType() == typeof(ClosingBrace) || token.GetType() == typeof(ValueQuote)) + { + return token; + } + + throw new ParseException("Expected type ClosingBrace or ValueQuote but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25)); + } + + private void NewLine(Tokenizer.Tokenizer tokenizer, Boolean optional = false) + { + AbstractToken token = tokenizer.Peek(); + + if (token.GetType() == typeof(NewLine)) + { + tokenizer.NextToken(); + return; + } + + if (optional) + { + return; + } + + throw new ParseException("Expected type Comma but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25)); + } + } +} diff --git a/BibtexLibrary.Standard/Parser/Nodes/BibtexFile.cs b/BibtexLibrary.Standard/Parser/Nodes/BibtexFile.cs new file mode 100644 index 0000000..1d08657 --- /dev/null +++ b/BibtexLibrary.Standard/Parser/Nodes/BibtexFile.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Parser.Nodes +{ + public class BibtexFile : ParseNode + { + private ICollection _entries = new List(); + + public ICollection Entries + { + get { return _entries; } + set { _entries = value; } + } + } +} diff --git a/BibtexLibrary.Standard/Parser/Nodes/Entry.cs b/BibtexLibrary.Standard/Parser/Nodes/Entry.cs new file mode 100644 index 0000000..765ad02 --- /dev/null +++ b/BibtexLibrary.Standard/Parser/Nodes/Entry.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Parser.Nodes +{ + public class Entry : ParseNode + { + public String Type { get; set; } + + public String Key { get; set; } + + public ICollection Tags { get; set; } + } +} diff --git a/BibtexLibrary.Standard/Parser/Nodes/ParseNode.cs b/BibtexLibrary.Standard/Parser/Nodes/ParseNode.cs new file mode 100644 index 0000000..96b7efa --- /dev/null +++ b/BibtexLibrary.Standard/Parser/Nodes/ParseNode.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Parser.Nodes +{ + public abstract class ParseNode + { + + } +} diff --git a/BibtexLibrary.Standard/Parser/Nodes/Tag.cs b/BibtexLibrary.Standard/Parser/Nodes/Tag.cs new file mode 100644 index 0000000..02c63d7 --- /dev/null +++ b/BibtexLibrary.Standard/Parser/Nodes/Tag.cs @@ -0,0 +1,10 @@ +using System; + +namespace BibtexLibrary.Parser.Nodes +{ + public class Tag + { + public String Key { get; set; } + public String Value { get; set; } + } +} \ No newline at end of file diff --git a/BibtexLibrary.Standard/Parser/ParseException.cs b/BibtexLibrary.Standard/Parser/ParseException.cs new file mode 100644 index 0000000..ec64f8a --- /dev/null +++ b/BibtexLibrary.Standard/Parser/ParseException.cs @@ -0,0 +1,13 @@ +using System; + +namespace BibtexLibrary.Parser +{ + public class ParseException : Exception + { + public ParseException(string s) : base(s) + { + + + } + } +} \ No newline at end of file diff --git a/BibtexLibrary.Standard/Tokenizer/ExpressionDictionary.cs b/BibtexLibrary.Standard/Tokenizer/ExpressionDictionary.cs new file mode 100644 index 0000000..cb8396b --- /dev/null +++ b/BibtexLibrary.Standard/Tokenizer/ExpressionDictionary.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using BibtexLibrary.Tokens; + +namespace BibtexLibrary.Tokenizer +{ + public class ExpressionDictionary : Dictionary + { + public ExpressionDictionary() + { + Init(); + } + + private void Init() + { + Add(typeof(Comment), "^(\\s)?\\%(.*)$"); + Add(typeof(At), "^(\\s)*@"); + Add(typeof(Preamble), "(\\s)*Preamble"); + Add(typeof(OpeningBrace), "^(\\s)*{"); + Add(typeof(ClosingBrace), "^(\\s)*}"); + Add(typeof(Equals), "^\\s*="); + Add(typeof(ValueQuote), "^(\\s)*\""); + Add(typeof(Text), "^\\s*['~\\*\\[\\]\\+%|<>#\\w\\d:\\.\\s-;(\\)/\\?&\\?&\\\\]+"); + Add(typeof(Comma), "^\\s*,"); + } + } +} diff --git a/BibtexLibrary.Standard/Tokenizer/MatchException.cs b/BibtexLibrary.Standard/Tokenizer/MatchException.cs new file mode 100644 index 0000000..caf7cd2 --- /dev/null +++ b/BibtexLibrary.Standard/Tokenizer/MatchException.cs @@ -0,0 +1,63 @@ +using System; +using System.Text; + +namespace LexicalAnalyzer +{ + public class MatchException : Exception + { + private readonly string _character; + private readonly int _position; + + public const Int32 windowWidth = 100; + public Int32 lineNumber { get; set; } = 0; + public String line { get; set; } = ""; + public String window { get; set; } = ""; + /// + /// The whole input + /// + public String input = ""; + + /// + /// Initializes a new instance of the class. + /// + /// The input. + /// The character. + /// The position. + public MatchException(String _input, String character, int position) + { + _character = character; + input = _input; + Int32 windowStart = Math.Max(position - windowWidth, 0); + Int32 windowEnd = _input.IndexOf(Environment.NewLine, position); + + var inputLines = input.Split(new String[] { Environment.NewLine }, StringSplitOptions.None); + Int32 head = 0; + + while (head < position) + { + lineNumber++; + line = inputLines[lineNumber]; + head += line.Length; + } + window = input.Substring(windowStart, windowEnd); + + _position = position; + + } + + /// + /// Gets a message that describes the current exception. + /// + public override string Message + { + get + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("BibTexLibrary: Could not match character: " + _character + " at position " + _position + " - ln:" + lineNumber); + sb.AppendLine("> Line: [" + line + "]"); + sb.AppendLine("> Window: [" + window + "]"); + return sb.ToString(); + } + } + } +} \ No newline at end of file diff --git a/BibtexLibrary.Standard/Tokenizer/Tokenizer.cs b/BibtexLibrary.Standard/Tokenizer/Tokenizer.cs new file mode 100644 index 0000000..2c3b607 --- /dev/null +++ b/BibtexLibrary.Standard/Tokenizer/Tokenizer.cs @@ -0,0 +1,121 @@ +using BibtexLibrary.Tokens; +using LexicalAnalyzer; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text.RegularExpressions; + +namespace BibtexLibrary.Tokenizer +{ + public class Tokenizer + { + private readonly ExpressionDictionary _dictionary; + private readonly string _input; + private int _counter; + + public Tokenizer(ExpressionDictionary dictionary, string input) + { + _dictionary = dictionary; + _input = input; + } + + public AbstractToken NextToken() + { + + // Loop through all tokens and check if they match the input string + foreach (KeyValuePair pair in _dictionary) + { + Match match; + + if (pair.Key == typeof(Comment)) + { + match = Regex.Match(_input.Substring(_counter), pair.Value, RegexOptions.Multiline); + } + else + { + // TODO: See if substring does not impose a to harsh performance drop + match = Regex.Match(_input.Substring(_counter), pair.Value); + } + + if (!match.Success) + { + continue; + } + _counter += match.Value.Length; + + if (!pair.Key.IsSubclassOf(typeof(AbstractToken))) + { + continue; + } + + // Create new instance of the specified type with the found value as parameter + AbstractToken token = (AbstractToken)Activator.CreateInstance(pair.Key, new object[] { match.Value, _counter - match.Value.Length }, null); + + return token; + } + + throw new MatchException(_input, _input[_counter].ToString(CultureInfo.InvariantCulture), _counter); + } + + public AbstractToken Peek() + { + // Loop through all tokens and check if they match the input string + foreach (KeyValuePair pair in _dictionary) + { + var test = _input.Length; + // TODO: See if substring does not impose a to harsh performance drop + Match match = Regex.Match(_input.Substring(_counter), pair.Value); + + if (match.Success) + { + if (pair.Key.IsSubclassOf(typeof(AbstractToken))) + { + // Create new instance of the specified type with the found value as parameter + AbstractToken token = (AbstractToken)Activator.CreateInstance(pair.Key, new object[] { match.Value, _counter }, null); + + return token; + } + + } + } + + throw new MatchException(_input, _input[_counter].ToString(CultureInfo.InvariantCulture), _counter); + } + + /// + /// Return all the tokens in the inputstring. + /// + /// List of tokens + public ICollection GetAllTokens() + { + List tokens = new List(); + + while (!EndOfInput) + { + tokens.Add(NextToken()); + } + + return tokens; + } + + /// + /// Checks whether the scanner is at the end of the input. + /// + public bool EndOfInput + { + get { return (_counter >= (_input.Length)); } + } + + /// + /// Returns the previous n characters. + /// + /// + /// Previous characters in the tokenizer + public string GetPreviousCharacters(int n) + { + return _input.Substring(_counter - n, n); + } + + + } +} diff --git a/BibtexLibrary.Standard/Tokens/AbstractToken.cs b/BibtexLibrary.Standard/Tokens/AbstractToken.cs new file mode 100644 index 0000000..6967c00 --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/AbstractToken.cs @@ -0,0 +1,58 @@ +using System; + +namespace BibtexLibrary.Tokens +{ + /// + /// Base class for tokens + /// + public class AbstractToken + { + public AbstractToken(String value) + { + Value = value; + } + + public AbstractToken(String value, int position) + { + RawValue = value; + Value = value.Trim(); + _position = position; + } + + protected bool Equals(AbstractToken other) + { + return string.Equals(Value, other.Value) && _position == other._position; + } + + public override int GetHashCode() + { + unchecked + { + return ((Value != null ? Value.GetHashCode() : 0) * 397) ^ _position; + } + } + + protected readonly string Value; + private readonly int _position; + + public String GetValue() + { + return Value; + } + + public int Position + { + get { return _position; } + } + + public string RawValue { get; private set; } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((AbstractToken)obj); + } + } +} diff --git a/BibtexLibrary.Standard/Tokens/At.cs b/BibtexLibrary.Standard/Tokens/At.cs new file mode 100644 index 0000000..fcea6ae --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/At.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Tokens +{ + public class At : AbstractToken + { + public At(String Value) :base(Value) { } + + public At(String Value, int Postion) : base(Value, Postion) { } + } +} diff --git a/BibtexLibrary.Standard/Tokens/ClosingBrace.cs b/BibtexLibrary.Standard/Tokens/ClosingBrace.cs new file mode 100644 index 0000000..ba548c9 --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/ClosingBrace.cs @@ -0,0 +1,18 @@ +using System; + +namespace BibtexLibrary.Tokens +{ + public class ClosingBrace : AbstractToken + { + public ClosingBrace(String value) + : base(value) + { + } + + public ClosingBrace(String value, int postion) + : base(value, postion) + { + + } + } +} diff --git a/BibtexLibrary.Standard/Tokens/Comma.cs b/BibtexLibrary.Standard/Tokens/Comma.cs new file mode 100644 index 0000000..f11c50b --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/Comma.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Tokens +{ + public class Comma : AbstractToken + { + public Comma(string value) : base(value) + { + } + + public Comma(string value, int position) : base(value, position) + { + } + } +} diff --git a/BibtexLibrary.Standard/Tokens/Comment.cs b/BibtexLibrary.Standard/Tokens/Comment.cs new file mode 100644 index 0000000..3242830 --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/Comment.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BibtexLibrary.Tokens +{ + class Comment : AbstractToken + { + public Comment(String value) + : base(value) + { + } + + public Comment(String value, int postion) + : base(value, postion) + { + { + } + } + } +} diff --git a/BibtexLibrary.Standard/Tokens/Equals.cs b/BibtexLibrary.Standard/Tokens/Equals.cs new file mode 100644 index 0000000..eabcec6 --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/Equals.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Tokens +{ + public class Equals : AbstractToken + { + public Equals(string value) : base(value) + { + } + + public Equals(string value, int position) : base(value, position) + { + } + } +} diff --git a/BibtexLibrary.Standard/Tokens/NewLine.cs b/BibtexLibrary.Standard/Tokens/NewLine.cs new file mode 100644 index 0000000..02ec2d1 --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/NewLine.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Tokens +{ + class NewLine : AbstractToken + { + public NewLine(String Value) :base(Value) { } + public NewLine(String Value, int Postion) : base(Value, Postion) { } + } +} diff --git a/BibtexLibrary.Standard/Tokens/OpeningBrace.cs b/BibtexLibrary.Standard/Tokens/OpeningBrace.cs new file mode 100644 index 0000000..135b300 --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/OpeningBrace.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Tokens +{ + public class OpeningBrace : AbstractToken + { + public OpeningBrace(String Value) :base(Value) { } + public OpeningBrace(String Value, int Postion) : base(Value, Postion) { } + } +} diff --git a/BibtexLibrary.Standard/Tokens/Preamble.cs b/BibtexLibrary.Standard/Tokens/Preamble.cs new file mode 100644 index 0000000..0cc9932 --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/Preamble.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Tokens +{ + public class Preamble : AbstractToken + { + public Preamble(String Value) :base(Value) { } + public Preamble(String Value, int Postion) : base(Value, Postion) { } + } +} diff --git a/BibtexLibrary.Standard/Tokens/Text.cs b/BibtexLibrary.Standard/Tokens/Text.cs new file mode 100644 index 0000000..3f4afff --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/Text.cs @@ -0,0 +1,18 @@ +using System; + +namespace BibtexLibrary.Tokens +{ + public class Text : AbstractToken + { + public Text(String value) + : base(value) + { + } + + public Text(String value, int postion) + : base(value, postion) + { + + } + } +} diff --git a/BibtexLibrary.Standard/Tokens/ValueQuote.cs b/BibtexLibrary.Standard/Tokens/ValueQuote.cs new file mode 100644 index 0000000..8dc0f53 --- /dev/null +++ b/BibtexLibrary.Standard/Tokens/ValueQuote.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BibtexLibrary.Tokens +{ + public class ValueQuote : AbstractToken + { + public ValueQuote(string value) : base(value) + { + } + + public ValueQuote(string value, int position) : base(value, position) + { + } + } +} diff --git a/BibtexLibrary.Standard/imbSCI - Copy.ico b/BibtexLibrary.Standard/imbSCI - Copy.ico new file mode 100644 index 0000000..bae3c80 Binary files /dev/null and b/BibtexLibrary.Standard/imbSCI - Copy.ico differ diff --git a/BibtexLibrary.Standard/imbSCI.BibtexLibrary.Standard.xml b/BibtexLibrary.Standard/imbSCI.BibtexLibrary.Standard.xml new file mode 100644 index 0000000..9d30eb3 --- /dev/null +++ b/BibtexLibrary.Standard/imbSCI.BibtexLibrary.Standard.xml @@ -0,0 +1,202 @@ + + + + BibtexLibrary.Standard + + + + + Single entry in Bibtex file + + + + + The tags + + + + + Gets or sets the type. + + + The type. + + + + + Gets or sets the key. + + + The key. + + + + + Gets or sets the tags. + + + The tags. + + + + + Collection of Bibtex entries + + + + + Gets or sets the string definitions. + + + The string definitions. + + + + + Gets or sets the preamble. + + + The preamble. + + + + + Gets or sets the entries. + + + The entries. + + + + + Parser + + + + + Froms the string. + + The text. + + + + + Froms the stream. + + The reader. + + + + + + Initializes a new instance of the class. + + The tokenizer. + + + + Parses this instance. + + + + + + Converts the parse node. + + The node. + + + + + Parses the input. + + The tokenizer. + + + + + Entries the specified tokenizer. + + The tokenizer. + + + + + Texts the specified tokenizer. + + The tokenizer. + + Expected type Text but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + + + + Openings the brace. + + The tokenizer. + Expected type OpeningBrace but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + + + + Closings the brace. + + The tokenizer. + Expected type ClosingBrace but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + + + + Commas the specified tokenizer. + + The tokenizer. + if set to true [optional]. + Expected type Comma but found: " + token.GetType() + " after " + tokenizer.GetPreviousCharacters(25) + + + + Retrieves the tag values from the input. + + The tokenizer. + + + + + Return all the tokens in the inputstring. + + List of tokens + + + + Checks whether the scanner is at the end of the input. + + + + + Returns the previous n characters. + + + Previous characters in the tokenizer + + + + Base class for tokens + + + + + The whole input + + + + + Initializes a new instance of the class. + + The input. + The character. + The position. + + + + Gets a message that describes the current exception. + + + + diff --git a/BibtexLibrary.Standard/key.snk b/BibtexLibrary.Standard/key.snk new file mode 100644 index 0000000..3d275d8 Binary files /dev/null and b/BibtexLibrary.Standard/key.snk differ diff --git a/BibtexLibrary.sln b/BibtexLibrary.sln index f1ec045..49f9b97 100644 --- a/BibtexLibrary.sln +++ b/BibtexLibrary.sln @@ -1,12 +1,16 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2026 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BibtexLibrary", "BibtexLibrary\BibtexLibrary.csproj", "{BF36652A-A0D7-4877-8AE0-B3E8362019C1}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BibtexLibrary.Tests", "BibtexLibrary.Tests\BibtexLibrary.Tests.csproj", "{5ACEB9AA-F461-4918-8CA9-12156446B0B2}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BibtexLibrary.Standard", "BibtexLibrary.Standard\BibtexLibrary.Standard.csproj", "{4071ADF7-1703-4BE2-A0FB-42B11DD88B5A}" +EndProject +Project("{7CF6DF6D-3B04-46F8-A40B-537D21BCA0B4}") = "BibtexLibrary.Documentation", "BibtexLibrary.Documentation\BibtexLibrary.Documentation.shfbproj", "{617B9073-B902-49A2-B28D-4D790595D7CD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,8 +25,19 @@ Global {5ACEB9AA-F461-4918-8CA9-12156446B0B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {5ACEB9AA-F461-4918-8CA9-12156446B0B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {5ACEB9AA-F461-4918-8CA9-12156446B0B2}.Release|Any CPU.Build.0 = Release|Any CPU + {4071ADF7-1703-4BE2-A0FB-42B11DD88B5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4071ADF7-1703-4BE2-A0FB-42B11DD88B5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4071ADF7-1703-4BE2-A0FB-42B11DD88B5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4071ADF7-1703-4BE2-A0FB-42B11DD88B5A}.Release|Any CPU.Build.0 = Release|Any CPU + {617B9073-B902-49A2-B28D-4D790595D7CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {617B9073-B902-49A2-B28D-4D790595D7CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {617B9073-B902-49A2-B28D-4D790595D7CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {617B9073-B902-49A2-B28D-4D790595D7CD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EC420422-CBDC-43B2-B86F-D2C4F9419E90} + EndGlobalSection EndGlobal