Skip to content

Commit

Permalink
Increased version to 2.1.0 and eliminated LNodePrinter delegate, re…
Browse files Browse the repository at this point in the history
…placing it with `ILNodePrinter`. `LNodePrinter` now holds extension methods of `ILNodePrinter`.

- `IParsingService` no longer includes a printing capability; language services implement `ILNodePrinter` separately.
- Renamed `LesNodePrinter` to `Les2Printer`, `LesParser` to `Les2Parser`, and so on for `LesLexer` and LESv2 unit tests.
  • Loading branch information
qwertie committed Dec 3, 2016
1 parent ceffb6b commit 32b19b7
Show file tree
Hide file tree
Showing 58 changed files with 321 additions and 316 deletions.
4 changes: 2 additions & 2 deletions Core/AssemblyVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
// by using '.*' as shown below - but you shouldn't, because it will cause a simple
// "Rebuild All" command to produce an incompatible assembly, since the .NET
// framework apparently requires an exact match on all four AssemblyVersion numbers.
[assembly: AssemblyVersion("2.0.1.0")]
[assembly: AssemblyFileVersion("2.0.1.0")]
[assembly: AssemblyVersion("2.1.0.0")]
[assembly: AssemblyFileVersion("2.1.0.0")]
48 changes: 3 additions & 45 deletions Core/Loyc.Syntax/IParsingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

namespace Loyc.Syntax
{
/// <summary>An interface that encapsulates the lexer, parser, and printer
/// of a programming language, or a non-programming language that can be
/// <summary>An interface that encapsulates the lexer and parser of a
/// programming language, or a non-programming language that can be
/// represented by Loyc trees.</summary>
/// <remarks>
/// The simplest way to parse code is with the extension method
Expand Down Expand Up @@ -97,30 +97,9 @@ public interface IParsingService
/// <exception cref="NotSupportedException">This feature is not supported
/// by this parsing service.</exception>
IListSource<LNode> Parse(IListSource<Token> tokens, ISourceFile file, IMessageSink msgs, ParsingMode inputType);

/// <summary>Gets a printer delegate that you can use with
/// <see cref="LNode.Printer"/> and <see cref="LNode.PushPrinter"/>,
/// or null if there is no corresponding printer available for the parser
/// reresented by this object.</summary>
LNodePrinter Printer { get; }

/// <summary>Converts the specified syntax tree to a string.</summary>
/// <param name="node">A syntax tree to print.</param>
/// <param name="options">A set of options to control printer behavior. If null,
/// an appropriate default set of options should be used. Some languages may
/// support additional option interfaces beyond <see cref="ILNodePrinterOptions"/>.</param>
/// <param name="sink">An object used to print warning and error messages. If
/// this is null, messages are sent to <see cref="MessageSink.Current"/>.</param>
/// <param name="mode">Indicates the context in which the node(s) to be printed
/// should be understood (e.g. is it a statement or an expression?).</param>
string Print(LNode node, IMessageSink sink = null, ParsingMode mode = null, ILNodePrinterOptions options = null);

/// <summary>Converts the specified list of syntax trees to a string.</summary>
/// <remarks>Most implementations can simply call <see cref="ParsingService.PrintMultiple"/>.</remarks>
string Print(IEnumerable<LNode> nodes, IMessageSink sink = null, ParsingMode mode = null, ILNodePrinterOptions options = null);
}

/// <summary>Extension methods for <see cref="IParsingService"/>.</summary>
/// <summary>Standard extension methods for <see cref="IParsingService"/>.</summary>
public static class ParsingService
{
static ThreadLocalVariable<IParsingService> _current = new ThreadLocalVariable<IParsingService>();
Expand Down Expand Up @@ -279,26 +258,5 @@ public static ILexer<Token> TokenizeFile(this IParsingService parser, string fil
using (var stream = new FileStream(fileName, FileMode.Open))
return Tokenize(parser, stream, fileName, msgs);
}
/// <summary>Converts a sequences of LNodes to strings, adding a line separator between each.</summary>
/// <param name="printer">Printer for a single LNode.</param>
/// <param name="mode">A language-specific way of modifying printer behavior.
/// The printer ignores the mode object if it does not not understand it.</param>
/// <param name="sb">Buffer to append to (null to allocate automatically)</param>
/// <returns>A string form of the nodes.</returns>
/// <remarks>The newline between two nodes is suppressed if the second
/// node has a #trivia_appendStatement attribute.</remarks>
public static string PrintMultiple(LNodePrinter printer, IEnumerable<LNode> nodes, IMessageSink sink = null, ParsingMode mode = null, ILNodePrinterOptions options = null, StringBuilder sb = null)
{
sb = sb ?? new StringBuilder();
var lineSeparator = (options != null ? options.NewlineString : null) ?? "\n";
bool first = true;
foreach (LNode node in nodes) {
if (!first)
sb.Append(node.AttrNamed(CodeSymbols.TriviaAppendStatement) == null ? lineSeparator : " ");
printer(node, sb, sink, mode, options);
first = false;
}
return sb.ToString();
}
}
}
2 changes: 1 addition & 1 deletion Core/Loyc.Syntax/LES/INodePrinterWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace Loyc.Syntax.Les
{
/// <summary>This interface is implemented by helper objects that handle the
/// low-level details of node printing. It is used by <see cref="LesNodePrinter"/>.</summary>
/// low-level details of node printing. It is used by <see cref="Les2Printer"/>.</summary>
/// <remarks>Specifically, INodePrinterWriter objects are in charge of how much
/// to indent lines of code, and ensuring that there are spaces between tokens
/// whenever omitting a space would screw up parsing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Loyc.Syntax.Les
/// <remarks>
/// LES overview: http://loyc.net/les
/// </remarks>
public class Les2LanguageService : IParsingService
public class Les2LanguageService : IParsingService, ILNodePrinter
{
public static readonly Les2LanguageService Value = new Les2LanguageService();

Expand All @@ -25,19 +25,17 @@ public override string ToString()
static readonly string[] _fileExtensions = new[] { "les", "les2" };
public IEnumerable<string> FileExtensions { get { return _fileExtensions; } }

public LNodePrinter Printer
void ILNodePrinter.Print(LNode node, StringBuilder target, IMessageSink sink, ParsingMode mode, ILNodePrinterOptions options)
{
get { return LesNodePrinter.Printer; }
Print((ILNode)node, target, sink, mode, options);
}
public string Print(LNode node, IMessageSink msgs = null, ParsingMode mode = null, ILNodePrinterOptions options = null)
public void Print(ILNode node, StringBuilder target, IMessageSink sink = null, ParsingMode mode = null, ILNodePrinterOptions options = null)
{
var sb = new StringBuilder();
Printer(node, sb, msgs, mode, options);
return sb.ToString();
Les2Printer.Print(node, target, sink, mode, options);
}
public string Print(IEnumerable<LNode> nodes, IMessageSink msgs = null, ParsingMode mode = null, ILNodePrinterOptions options = null)
public void Print(IEnumerable<LNode> nodes, StringBuilder target, IMessageSink msgs = null, ParsingMode mode = null, ILNodePrinterOptions options = null)
{
return ParsingService.PrintMultiple(Printer, nodes, msgs, mode, options);
LNodePrinter.PrintMultiple(this, nodes, target, msgs, mode, options);
}
public bool HasTokenizer
{
Expand All @@ -49,7 +47,7 @@ public bool CanPreserveComments
}
public ILexer<Token> Tokenize(ICharSource text, string fileName, IMessageSink msgs)
{
return new LesLexer(text, fileName, msgs);
return new Les2Lexer(text, fileName, msgs);
}
public IListSource<LNode> Parse(ICharSource text, string fileName, IMessageSink msgs, ParsingMode inputType = null, bool preserveComments = true)
{
Expand All @@ -70,7 +68,7 @@ public IListSource<LNode> Parse(ILexer<Token> input, IMessageSink msgs, ParsingM
}

[ThreadStatic]
static LesParser _parser;
static Les2Parser _parser;

public IListSource<LNode> Parse(IListSource<Token> input, ISourceFile file, IMessageSink msgs, ParsingMode inputType = null)
{
Expand All @@ -85,9 +83,9 @@ public IListSource<LNode> Parse(IListSource<Token> input, ISourceFile file, IMes
bool exprMode = inputType == ParsingMode.Expressions;
char _ = '\0';
if (inputType == ParsingMode.Expressions || file.Text.TryGet(255, ref _)) {
LesParser parser = _parser;
Les2Parser parser = _parser;
if (parser == null)
_parser = parser = new LesParser(input, file, msgs);
_parser = parser = new Les2Parser(input, file, msgs);
else {
parser.ErrorSink = msgs;
parser.Reset(input.AsList(), file);
Expand All @@ -97,7 +95,7 @@ public IListSource<LNode> Parse(IListSource<Token> input, ISourceFile file, IMes
else
return parser.Start(new Holder<TokenType>(TokenType.Semicolon)).Buffered();
} else {
var parser = new LesParser(input, file, msgs);
var parser = new Les2Parser(input, file, msgs);
return parser.Start(new Holder<TokenType>(TokenType.Semicolon)).Buffered();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ namespace Loyc.Syntax.Les
/// <summary>Lexer for EC# source code.</summary>
/// <seealso cref="ILexer{Token}"/>
/// <seealso cref="TokensToTree"/>
public partial class LesLexer : BaseILexer<ICharSource, Token>, ILexer<Token>, ICloneable<LesLexer>
public partial class Les2Lexer : BaseILexer<ICharSource, Token>, ILexer<Token>, ICloneable<Les2Lexer>
{
public LesLexer(UString text, IMessageSink errorSink) : this(text, "", errorSink) { }
public LesLexer(ICharSource text, string fileName, IMessageSink sink, int startPosition = 0) : base(text, fileName, startPosition) {
public Les2Lexer(UString text, IMessageSink errorSink) : this(text, "", errorSink) { }
public Les2Lexer(ICharSource text, string fileName, IMessageSink sink, int startPosition = 0) : base(text, fileName, startPosition) {
ErrorSink = sink;
}

Expand Down Expand Up @@ -69,9 +69,9 @@ protected sealed override void AfterNewline()
}
protected override bool SupportDotIndents() { return true; }

public LesLexer Clone()
public Les2Lexer Clone()
{
return (LesLexer)MemberwiseClone();
return (Les2Lexer)MemberwiseClone();
}

#region Token value parsers
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated from LesLexerGrammar.les by LeMP custom tool. LeMP version: 1.9.6.0
// Generated from Les2LexerGrammar.les by LeMP custom tool. LeMP version: 2.1.0.0
// Note: you can give command-line arguments to the tool via 'Custom Tool Namespace':
// --no-out-header Suppress this message
// --verbose Allow verbose messages (shown by VS as 'warnings')
Expand All @@ -19,7 +19,7 @@ namespace Loyc.Syntax.Les
using TT = TokenType;
using S = CodeSymbols;

public partial class LesLexer
public partial class Les2Lexer
{

void Newline(bool ignoreIndent = false)
Expand Down Expand Up @@ -1330,4 +1330,4 @@ private bool MLCommentLine_Test0()
return true;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Loyc.Syntax.Les
using TT = TokenType;
using S = CodeSymbols;

@[public, partial] class LesLexer
@[public, partial] class Les2Lexer
{
@[FullLLk, AddCsLineDirectives(@false)]
LLLPG lexer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ namespace Loyc.Syntax.Les
/// You can use <see cref="Les2LanguageService.Value"/> with <see cref="ParsingService.Parse"/>
/// to easily parse a text string (holding zero or more LES statements) into a Loyc tree.
/// <para/>
/// This class expects to receive tokens from <see cref="LesLexer"/> that have been
/// This class expects to receive tokens from <see cref="Les2Lexer"/> that have been
/// preprocessed by <see cref="TokensToTree"/>, with whitespace tokens filtered out.
/// </remarks>
public partial class LesParser : BaseParserForList<Token, int>
public partial class Les2Parser : BaseParserForList<Token, int>
{
protected LNodeFactory F;
protected LesPrecedenceMap _prec = LesPrecedenceMap.Default;

new const TT EOF = TT.EOF;

public LesParser(IListAndListSource<Token> tokens, ISourceFile file, IMessageSink messageSink) : this((IList<Token>)tokens, file, messageSink) {}
public LesParser(IListSource<Token> tokens, ISourceFile file, IMessageSink messageSink) : this(tokens.AsList(), file, messageSink) {}
public LesParser(IList<Token> tokens, ISourceFile file, IMessageSink messageSink, int startIndex = 0)
public Les2Parser(IListAndListSource<Token> tokens, ISourceFile file, IMessageSink messageSink) : this((IList<Token>)tokens, file, messageSink) {}
public Les2Parser(IListSource<Token> tokens, ISourceFile file, IMessageSink messageSink) : this(tokens.AsList(), file, messageSink) {}
public Les2Parser(IList<Token> tokens, ISourceFile file, IMessageSink messageSink, int startIndex = 0)
: base(tokens, default(Token), file, startIndex)
{
ErrorSink = messageSink;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated from LesParserGrammar.les by LeMP custom tool. LeMP version: 1.9.6.0
// Generated from Les2ParserGrammar.les by LeMP custom tool. LeMP version: 2.1.0.0
// Note: you can give command-line arguments to the tool via 'Custom Tool Namespace':
// --no-out-header Suppress this message
// --verbose Allow verbose messages (shown by VS as 'warnings')
Expand All @@ -22,7 +22,7 @@ namespace Loyc.Syntax.Les {
// 0162=Unreachable code detected; 0642=Possibly mistaken empty statement
#pragma warning disable 162, 642

public partial class LesParser
public partial class Les2Parser
{
public VList<LNode> ExprList(VList<LNode> list = default(VList<LNode>)) {
var endMarker = default(TT);
Expand Down Expand Up @@ -504,4 +504,4 @@ TokenTree TokenTree()
return result;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace Loyc.Syntax.Les {
// 0162=Unreachable code detected; 0642=Possibly mistaken empty statement
#rawText("#pragma warning disable 162, 642");

@[public, partial] class LesParser
@[public, partial] class Les2Parser
{
@[FullLLk, LL(2), AddCsLineDirectives(@false)]
LLLPG (parser(laType(TT), matchType(int), terminalType(Token), allowSwitch(@true)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Loyc.Syntax.Les
{
/// <summary>Prints a Loyc tree in LES (Loyc Expression Syntax) format.</summary>
/// <remarks>Unless otherwise noted, the default value of all options is false.</remarks>
public class LesNodePrinter
public class Les2Printer
{
INodePrinterWriter _out;
IMessageSink _errors;
Expand All @@ -33,18 +33,17 @@ public void SetOptions(ILNodePrinterOptions options)
#region Constructors and default Printer

[ThreadStatic]
static LesNodePrinter _printer;
public static readonly LNodePrinter Printer = Print;
static Les2Printer _printer;

internal static void Print(ILNode node, StringBuilder target, IMessageSink sink, ParsingMode mode, ILNodePrinterOptions options = null)
{
var p = _printer = _printer ?? new LesNodePrinter(TextWriter.Null, null);
var p = _printer = _printer ?? new Les2Printer(TextWriter.Null, null);
var oldOptions = p._o;
var oldWriter = p.Writer;
var oldSink = p.Errors;
p.Errors = sink;
p.SetOptions(options);
p.Writer = new LesNodePrinterWriter(target, p.Options.IndentString ?? "\t", p.Options.NewlineString ?? "\n");
p.Writer = new Les2PrinterWriter(target, p.Options.IndentString ?? "\t", p.Options.NewlineString ?? "\n");

if (mode == ParsingMode.Expressions)
p.Print(node, StartStmt, "");
Expand All @@ -56,15 +55,15 @@ internal static void Print(ILNode node, StringBuilder target, IMessageSink sink,
p.Errors = oldSink;
}

internal LesNodePrinter(TextWriter target, ILNodePrinterOptions options = null)
internal Les2Printer(TextWriter target, ILNodePrinterOptions options = null)
{
SetOptions(options);
Writer = new LesNodePrinterWriter(target, _o.IndentString ?? "\t", _o.NewlineString ?? "\n");
Writer = new Les2PrinterWriter(target, _o.IndentString ?? "\t", _o.NewlineString ?? "\n");
}
internal LesNodePrinter(StringBuilder target, ILNodePrinterOptions options = null)
internal Les2Printer(StringBuilder target, ILNodePrinterOptions options = null)
{
SetOptions(options);
Writer = new LesNodePrinterWriter(target, _o.IndentString ?? "\t", _o.NewlineString ?? "\n");
Writer = new Les2PrinterWriter(target, _o.IndentString ?? "\t", _o.NewlineString ?? "\n");
}

#endregion
Expand Down Expand Up @@ -427,8 +426,8 @@ private void PrintSpaces(string spaces)
static readonly Symbol Var = GSymbol.Get("var"), Def = GSymbol.Get("def");

static StringBuilder _staticStringBuilder = new StringBuilder();
static LesNodePrinterWriter _staticWriter = new LesNodePrinterWriter(_staticStringBuilder);
static LesNodePrinter _staticPrinter = new LesNodePrinter(_staticStringBuilder);
static Les2PrinterWriter _staticWriter = new Les2PrinterWriter(_staticStringBuilder);
static Les2Printer _staticPrinter = new Les2Printer(_staticStringBuilder);

public static string PrintId(Symbol name)
{
Expand Down Expand Up @@ -469,12 +468,12 @@ static bool IsSpecialIdentifier(Symbol name, out bool backquote)
bool special = false, first = true;
foreach (char c in name.Name)
{
if (!LesLexer.IsIdContChar(c)) {
if (LesLexer.IsSpecialIdChar(c))
if (!Les2Lexer.IsIdContChar(c)) {
if (Les2Lexer.IsSpecialIdChar(c))
special = true;
else
backquote = true;
} else if (first && !LesLexer.IsIdStartChar(c))
} else if (first && !Les2Lexer.IsIdStartChar(c))
special = true;
first = false;
}
Expand Down Expand Up @@ -525,7 +524,7 @@ private void PrintStringCore(char quoteType, bool tripleQuoted, string text)
_out.Write(quoteType, true);
}

static Pair<RuntimeTypeHandle,Action<LesNodePrinter, object, NodeStyle>> P<T>(Action<LesNodePrinter, object, NodeStyle> handler)
static Pair<RuntimeTypeHandle,Action<Les2Printer, object, NodeStyle>> P<T>(Action<Les2Printer, object, NodeStyle> handler)
{ return Pair.Create(typeof(T).TypeHandle, handler); }
static Pair<K,V> P<K,V>(K key, V value)
{ return Pair.Create(key, value); }
Expand All @@ -536,7 +535,7 @@ static Dictionary<K,V> Dictionary<K,V>(params Pair<K,V>[] input)
d.Add(input[i].Key, input[i].Value);
return d;
}
static Dictionary<RuntimeTypeHandle,Action<LesNodePrinter, object, NodeStyle>> LiteralPrinters = Dictionary(
static Dictionary<RuntimeTypeHandle,Action<Les2Printer, object, NodeStyle>> LiteralPrinters = Dictionary(
P<int> ((np, value, style) => np.PrintIntegerToString(value, style, "")),
P<long> ((np, value, style) => np.PrintIntegerToString(value, style, "L")),
P<uint> ((np, value, style) => np.PrintIntegerToString(value, style, "u")),
Expand Down Expand Up @@ -654,7 +653,7 @@ private void PrintLiteral(ILNode node)
}
private bool PrintLiteralCore(object value, NodeStyle style)
{
Action<LesNodePrinter, object, NodeStyle> p;
Action<Les2Printer, object, NodeStyle> p;
if (value == null)
_out.Write("@null", true);
else if (LiteralPrinters.TryGetValue(value.GetType().TypeHandle, out p))
Expand All @@ -667,7 +666,7 @@ private bool PrintLiteralCore(object value, NodeStyle style)
#endregion
}

/// <summary>Options to control the way Loyc trees are printed by <see cref="LesNodePrinter"/>.</summary>
/// <summary>Options to control the way Loyc trees are printed by <see cref="Les2Printer"/>.</summary>
public sealed class Les2PrinterOptions : LNodePrinterOptions
{
public Les2PrinterOptions() { }
Expand Down
Loading

0 comments on commit 32b19b7

Please sign in to comment.