update libdexed-d

- remove dependency on defunt iz library, close 
- add a derived parser to handle bounds violation, close 
- removed used of deprecated dparse types
This commit is contained in:
Basile Burg 2022-05-11 20:03:27 +02:00
parent 4138bca34f
commit 5b59cf30a4
14 changed files with 2437 additions and 57 deletions

3
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "etc/libdparse"]
path = etc/libdparse
url = https://github.com/dlang-community/libdparse.git
[submodule "etc/iz"]
path = etc/iz
url = https://gitlab.com/basile.b/iz.git
[submodule "etc/stdx-allocator"]
path = etc/stdx-allocator
url = https://github.com/dlang-community/stdx-allocator.git

View File

@ -1,9 +1,17 @@
# v3.9.17-dev
# v3.9.18-dev
## Enhancements
- Search and Replace: after a failed search give the editor the focus back.
## Bugs fixed
- crash to desktop for certain invalid or incomplete D constructs. (#107)
## Other
- dexed-d does not rely on the old "iz" library
# v3.9.17
## Enhancements

View File

@ -6,12 +6,9 @@
"dependencies" : {
"libdparse" : {
"path" : "../etc/libdparse"
},
"iz" : {
"path" : "../etc/iz"
}
},
"dflags" : [
"-link-defaultlib-shared=false"
]
}
}

View File

@ -7,7 +7,8 @@ import
import
dparse.lexer, dparse.ast, dparse.parser, dparse.rollback_allocator;
import
iz.memory, iz.containers;
iz;
export extern(C) int d_rt_init(){ return rt_init(); }
export extern(C) int d_rt_term(){ return rt_term(); }
@ -402,32 +403,6 @@ unittest
assert(stream.data != "");
}
/**
* Produces and visits the AST for a source code.
*
* This function is used to handle the content of a MixinExpression in an
* ASTVisitor.
*/
T parseAndVisit(T : ASTVisitor, A...)(const(char)[] source, A a)
{
import std.functional;
RollbackAllocator allocator;
LexerConfig config = LexerConfig("", StringBehavior.source, WhitespaceBehavior.skip);
StringCache cache = StringCache(StringCache.defaultBucketCount);
const(Token)[] tokens = getTokensForParser(cast(ubyte[]) source, config, &cache);
Module mod = parseModule(tokens, "", &allocator, toDelegate(&ignoreErrors));
T result = construct!(T)(a);
result.visit(mod);
return result;
}
/**
* By default libdparse outputs errors and warnings to the standard streams.
* This function prevents that.
*/
void ignoreErrors(string, size_t, size_t, string, bool) @system {}
/**
* Split a C string representing a list of filenames into an array of strings.
* The filenames are separated with the system path separator.
@ -459,7 +434,7 @@ public:
* the Pascal side, e.g on ref count decrement.
*/
static FpcArray!T* fromArray(A)(auto ref A array) nothrow @nogc
if (is(Unqual!A == T[]) || is(Unqual!A == iz.containers.Array!T))
if (is(Unqual!A == T[]) || is(Unqual!A == iz.Array!T))
{
alias RT = FpcArray!T;
enum isChar = is(Unqual!T == char);

View File

@ -5,9 +5,9 @@ import
import
std.array, std.conv, std.string;
import
iz.memory, iz.sugar;
iz;
import
dparse.ast, dparse.lexer, dparse.parser, dparse.rollback_allocator;
dparse.ast, dparse.lexer, dparse.rollback_allocator, parser;
import
common;
@ -67,7 +67,7 @@ public:
const(char)* result() { return app.data.toStringz(); }
override void visit(const(ThrowStatement) ts)
override void visit(const(ThrowExpression) ts)
{
_throws = true;
}

View File

@ -7,10 +7,10 @@ import
import
std.stdio, std.ascii, std.digest.crc, std.range: iota;
import
dparse.ast, dparse.lexer, dparse.parser, dparse.rollback_allocator;
dparse.ast, dparse.lexer, dparse.rollback_allocator, parser;
import
iz;
import
iz.memory, iz.containers, iz.sugar;
version(unittest){} else import
common;
/**
@ -477,7 +477,7 @@ private final class HalsteadMetric: ASTVisitor
st.accept(this);
}
override void visit(const(ThrowStatement) st)
override void visit(const(ThrowExpression) st)
{
operators["throw"] +=1;
st.accept(this);

View File

@ -5,9 +5,9 @@ import
import
std.algorithm, std.array, std.file, std.functional;
import
iz.memory;
iz;
import
dparse.lexer, dparse.ast, dparse.parser, dparse.rollback_allocator;
dparse.lexer, dparse.ast, parser, dparse.rollback_allocator;
import
common;

2262
dexed-d/src/iz.d Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,11 +3,11 @@ module mainfun;
import
std.stdio, std.algorithm;
import
iz.memory, iz.sugar;
iz;
import
core.stdc.string;
import
dparse.lexer, dparse.parser, dparse.ast, dparse.rollback_allocator;
dparse.lexer, dparse.ast, dparse.rollback_allocator, parser;
import
common;

144
dexed-d/src/parser.d Normal file
View File

@ -0,0 +1,144 @@
module parser;
import
dparse.lexer, dparse.ast, dparse.parser, dparse.rollback_allocator;
import
iz;
/**
* By default libdparse outputs errors and warnings to the standard streams.
* This function prevents that.
*/
void ignoreErrors(string, size_t, size_t, string, bool) @system {}
/// dparse Parser with bound checks fixed
final class Parser : dparse.parser.Parser
{
override PragmaExpression parsePragmaExpression()
{
mixin (traceEnterAndExit!(__FUNCTION__));
auto startIndex = index;
auto node = allocator.make!PragmaExpression;
mixin(tokenCheck!"pragma");
mixin(tokenCheck!"(");
const ident = expect(tok!"identifier");
mixin(nullCheck!`ident`);
node.identifier = *ident;
if (currentIs(tok!","))
{
advance();
mixin(parseNodeQ!(`node.argumentList`, `ArgumentList`));
}
mixin(tokenCheck!")");
node.tokens = tokens[startIndex .. index];
return node;
}
override TemplateValueParameterDefault parseTemplateValueParameterDefault()
{
mixin(traceEnterAndExit!(__FUNCTION__));
auto startIndex = index;
auto node = allocator.make!TemplateValueParameterDefault;
mixin(tokenCheck!"=");
if (!moreTokens)
{
error("template argument default value expected instead of EOF");
return null;
}
switch (current.type)
{
case tok!"__FILE__":
case tok!"__FILE_FULL_PATH__":
case tok!"__MODULE__":
case tok!"__LINE__":
case tok!"__FUNCTION__":
case tok!"__PRETTY_FUNCTION__":
node.token = advance();
break;
default:
mixin(parseNodeQ!(`node.assignExpression`, `AssignExpression`));
break;
}
node.tokens = tokens[startIndex .. index];
return node;
}
}
/**
* Params:
* parserConfig = a parser configuration.
* Returns:
* The parsed module.
*/
Module parseModule(P = .Parser)(auto ref ParserConfig parserConfig)
{
auto parser = new P();
with (parserConfig)
{
parser.fileName = fileName;
parser.tokens = tokens;
parser.messageFunction = messageFunction;
parser.messageDelegate = messageDelegate;
parser.allocator = allocator;
}
Module mod = parser.parseModule();
with (parserConfig)
{
if (warningCount !is null)
*warningCount = parser.warningCount;
if (errorCount !is null)
*errorCount = parser.errorCount;
}
return mod;
}
/**
* Params:
* tokens = The tokens parsed by dparse.lexer.
* fileName = The name of the file being parsed.
* allocator = A pointer to a rollback allocator.
* messageFuncOrDg = Either a function or a delegate that receives the parser messages.
* errorCount = An optional pointer to a variable receiving the error count.
* warningCount = An optional pointer to a variable receiving the warning count.
* Returns:
* The parsed module.
*/
Module parseModule(P = .Parser,F)(const(Token)[] tokens, string fileName, RollbackAllocator* allocator,
F messageFuncOrDg = null, uint* errorCount = null, uint* warningCount = null)
{
static if (is(F))
{
static if (is(F : MessageFunction))
return ParserConfig(tokens, fileName, allocator, messageFuncOrDg, null,
errorCount, warningCount).parseModule();
else static if (is(F : MessageDelegate))
return ParserConfig(tokens, fileName, allocator, null, messageFuncOrDg,
errorCount, warningCount).parseModule();
else static assert(0, "F must be a MessageFunction or a MessageDelegate");
}
else
{
return ParserConfig(tokens, fileName, allocator, null, null, null, null).parseModule!P();
}
}
/**
* Produces and visits the AST for a source code.
*
* This function is used to handle the content of a MixinExpression in an
* ASTVisitor.
*/
T parseAndVisit(T : ASTVisitor, A...)(const(char)[] source, A a)
{
import std.functional;
RollbackAllocator allocator;
LexerConfig config = LexerConfig("", StringBehavior.source, WhitespaceBehavior.skip);
StringCache cache = StringCache(StringCache.defaultBucketCount);
const(Token)[] tokens = getTokensForParser(cast(ubyte[]) source, config, &cache);
Module mod = parseModule(tokens, "", &allocator, toDelegate(&ignoreErrors));
T result = construct!(T)(a);
result.visit(mod);
return result;
}

View File

@ -6,11 +6,9 @@ import
std.array, std.conv, std.json, std.format,
std.algorithm, std.string;
import
iz.memory: construct, destruct, MustAddGcRange, TellRangeAdded, NoGc;
iz;
import
iz.containers : Array;
import
dparse.lexer, dparse.ast, dparse.parser, dparse.formatter : Formatter;
dparse.lexer, dparse.ast, parser, dparse.formatter : Formatter;
import
dparse.rollback_allocator;
import
@ -450,7 +448,7 @@ static assert (!MustAddGcRange!(SymbolListBuilder!(ListFmt.Pas)));
override void visit(const StaticAssertStatement){}
override void visit(const StructInitializer) {}
override void visit(const SynchronizedStatement){}
override void visit(const ThrowStatement) {}
override void visit(const ThrowExpression) {}
override void visit(const Type) {}
override void visit(const Type2) {}
}

1
etc/iz

@ -1 +0,0 @@
Subproject commit adc010f1d890a9cf41fa5b2308a89852eb8c6bb8

@ -1 +1 @@
Subproject commit b2c880042aeee29e72a07569bec23999c2233d47
Subproject commit b94a1573acc5c5c6b21794970af5907f2a21822d

View File

@ -12,7 +12,7 @@ uses
md5, Spin, LCLIntf, LazFileUtils, LMessages, SynHighlighterCpp, math,
SynGutterBase, LCLVersion,
//SynEditMarkupFoldColoring,
Clipbrd, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls,
Clipbrd, fpjson, jsonparser, LazUTF8, Buttons, StdCtrls,
u_common, u_writableComponent, u_d2syn, u_txtsyn, u_dialogs, u_sxsyn,
u_sharedres, u_dlang, u_stringrange, u_dbgitf, u_observer, u_diff,
u_processes, u_synmultiguttermarks;
@ -2561,12 +2561,12 @@ procedure TDexedMemo.sortSelectedLines(descending, caseSensitive: boolean);
var
i,j: integer;
lne: string;
lst: TStringListUTF8;
lst: TStringList;
pt0: TPoint;
begin
if BlockEnd.Y - BlockBegin.Y < 1 then
exit;
lst := TStringListUTF8.Create;
lst := TStringList.Create;
try
BeginUndoBlock;
for i:= BlockBegin.Y-1 to BlockEnd.Y-1 do