mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-27 07:26:48 +01:00
Common type and character positions
- Shader source abstractions now inherit from AbstractShaderElement - Spans keep track of line and column positions
This commit is contained in:
parent
a5d282a0ef
commit
865926e783
15 changed files with 327 additions and 107 deletions
|
@ -26,7 +26,7 @@ public class TypeHelper {
|
|||
return 1;
|
||||
}
|
||||
|
||||
public static int getAttributeCount(String type) {
|
||||
public static int getAttributeCount(CharSequence type) {
|
||||
Matcher mat = matType.matcher(type);
|
||||
if (mat.find()) {
|
||||
return Integer.parseInt(mat.group(1));
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Stack;
|
|||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.jozufozu.flywheel.backend.ShaderSources;
|
||||
import com.jozufozu.flywheel.backend.pipeline.parse.Include;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
|
@ -28,12 +29,12 @@ public class Includer {
|
|||
}
|
||||
|
||||
private static void process(ShaderSources sources, Set<ResourceLocation> seen, List<SourceFile> out, SourceFile source) {
|
||||
ImmutableList<ResourceLocation> includes = source.getIncludes();
|
||||
ImmutableList<Include> includes = source.getIncludes();
|
||||
|
||||
for (ResourceLocation include : includes) {
|
||||
for (Include include : includes) {
|
||||
|
||||
if (seen.add(include)) {
|
||||
SourceFile file = sources.source(include);
|
||||
if (seen.add(include.getFile())) {
|
||||
SourceFile file = sources.source(include.getFile());
|
||||
|
||||
process(sources, seen, out, file);
|
||||
|
||||
|
|
|
@ -1,40 +1,47 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.backend.ShaderSources;
|
||||
import com.jozufozu.flywheel.backend.pipeline.parse.Include;
|
||||
import com.jozufozu.flywheel.backend.pipeline.parse.ShaderFunction;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.CharPos;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.ErrorSpan;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.StringSpan;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class SourceFile {
|
||||
// #use "valid_namespace:valid/path_to_file.glsl"
|
||||
private static final Pattern includePattern = Pattern.compile("#use \"(\\w+:[\\w./]+)\"");
|
||||
|
||||
private static final Pattern newLine = Pattern.compile("(\\r\\n|\\r|\\n)");
|
||||
|
||||
// https://regexr.com/60n3d
|
||||
public static final Pattern functionDeclaration = Pattern.compile("(\\w+)\\s+(\\w+)\\s*\\(([\\w,\\s]*)\\)\\s*\\{");
|
||||
|
||||
public final ResourceLocation name;
|
||||
private final String source;
|
||||
private final ShaderSources parent;
|
||||
|
||||
// function name -> function object
|
||||
private final ShaderSources parent;
|
||||
private final String source;
|
||||
|
||||
private final IntList lineStarts;
|
||||
|
||||
// Function name -> Function object
|
||||
private final ImmutableMap<String, ShaderFunction> functions;
|
||||
private final ImmutableList<ResourceLocation> includes;
|
||||
|
||||
// Includes ordered as defined in the source
|
||||
private final ImmutableList<Include> includes;
|
||||
|
||||
// Sections of the source that must be trimmed for compilation.
|
||||
private final List<Span> elisions = new ArrayList<>();
|
||||
|
@ -44,8 +51,10 @@ public class SourceFile {
|
|||
this.name = name;
|
||||
this.source = source;
|
||||
|
||||
functions = parseFunctions();
|
||||
includes = parseIncludes();
|
||||
this.lineStarts = getLinePositions();
|
||||
|
||||
this.functions = parseFunctions();
|
||||
this.includes = parseIncludes();
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
|
@ -60,28 +69,81 @@ public class SourceFile {
|
|||
return functions;
|
||||
}
|
||||
|
||||
public ImmutableList<ResourceLocation> getIncludes() {
|
||||
public ImmutableList<Include> getIncludes() {
|
||||
return includes;
|
||||
}
|
||||
|
||||
private ImmutableList<ResourceLocation> parseIncludes() {
|
||||
Matcher uses = includePattern.matcher(source);
|
||||
public CharPos getCharPos(int charPos) {
|
||||
int lineNo = 0;
|
||||
for (; lineNo < lineStarts.size(); lineNo++) {
|
||||
int ls = lineStarts.getInt(lineNo);
|
||||
|
||||
List<ResourceLocation> includes = new ArrayList<>();
|
||||
|
||||
while (uses.find()) {
|
||||
Span use = Span.fromMatcher(this, uses);
|
||||
|
||||
elisions.add(use); // we have to trim that later
|
||||
|
||||
ResourceLocation loc = new ResourceLocation(uses.group(1)); // TODO: error gracefully
|
||||
|
||||
includes.add(loc);
|
||||
if (charPos < ls) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ImmutableList.copyOf(includes);
|
||||
int lineStart = lineStarts.getInt(lineNo - 1);
|
||||
|
||||
return new CharPos(charPos, lineNo, charPos - lineStart);
|
||||
}
|
||||
|
||||
public String printSource() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("Source for shader '")
|
||||
.append(name)
|
||||
.append("':\n");
|
||||
int i = 1;
|
||||
for (String s : source.split("\n")) {
|
||||
builder.append(String.format("%1$4s: ", i++))
|
||||
.append(s)
|
||||
.append('\n');
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private CharSequence elided = null;
|
||||
|
||||
public CharSequence getElidedSource() {
|
||||
if (elided == null) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
int lastEnd = 0;
|
||||
|
||||
for (Span elision : elisions) {
|
||||
out.append(source, lastEnd, elision.getStart());
|
||||
|
||||
lastEnd = elision.getEnd();
|
||||
}
|
||||
|
||||
out.append(source, lastEnd, source.length());
|
||||
|
||||
elided = out.toString();
|
||||
}
|
||||
|
||||
return elided;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the source for line breaks, recording the position of the first character of each line.
|
||||
*/
|
||||
private IntList getLinePositions() {
|
||||
IntList l = new IntArrayList();
|
||||
l.add(0); // first line is always at position 0
|
||||
|
||||
Matcher matcher = newLine.matcher(source);
|
||||
|
||||
while (matcher.find()) {
|
||||
l.add(matcher.end());
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the source for function definitions and "parse" them into objects that contain properties of the function.
|
||||
*/
|
||||
private ImmutableMap<String, ShaderFunction> parseFunctions() {
|
||||
Matcher matcher = functionDeclaration.matcher(source);
|
||||
|
||||
|
@ -113,59 +175,43 @@ public class SourceFile {
|
|||
return ImmutableMap.copyOf(functions);
|
||||
}
|
||||
|
||||
private int findEndOfBlock(int end) {
|
||||
char[] rest = source.substring(end)
|
||||
.toCharArray();
|
||||
/**
|
||||
* Scan the source for <code>#use "..."</code> directives.
|
||||
* Records the contents of the directive into an {@link Include} object, and marks the directive for elision.
|
||||
*/
|
||||
private ImmutableList<Include> parseIncludes() {
|
||||
Matcher uses = includePattern.matcher(source);
|
||||
|
||||
List<Include> includes = new ArrayList<>();
|
||||
|
||||
while (uses.find()) {
|
||||
Span use = Span.fromMatcher(this, uses);
|
||||
Span file = Span.fromMatcher(this, uses, 1);
|
||||
|
||||
includes.add(new Include(parent, use, file));
|
||||
|
||||
elisions.add(use); // we have to trim that later
|
||||
}
|
||||
|
||||
return ImmutableList.copyOf(includes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the position of an opening brace, scans through the source for a paired closing brace.
|
||||
*/
|
||||
private int findEndOfBlock(int start) {
|
||||
int blockDepth = 0;
|
||||
for (int i = 0; i < rest.length; i++) {
|
||||
char ch = rest[i];
|
||||
for (int i = start + 1; i < source.length(); i++) {
|
||||
char ch = source.charAt(i);
|
||||
|
||||
if (ch == '{') blockDepth++;
|
||||
if (ch == '}') blockDepth--;
|
||||
else if (ch == '}') blockDepth--;
|
||||
|
||||
if (blockDepth < 0) {
|
||||
return end + i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String printSource() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("Source for shader '")
|
||||
.append(name)
|
||||
.append("':\n");
|
||||
int i = 1;
|
||||
for (String s : source.split("\n")) {
|
||||
builder.append(String.format("%1$4s: ", i++))
|
||||
.append(s)
|
||||
.append('\n');
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private CharSequence elided = null;
|
||||
public CharSequence getElidedSource() {
|
||||
if (elided == null) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
int lastEnd = 0;
|
||||
|
||||
for (Span elision : elisions) {
|
||||
out.append(source, lastEnd, elision.getStart());
|
||||
|
||||
lastEnd = elision.getEnd();
|
||||
}
|
||||
|
||||
out.append(source, lastEnd, source.length());
|
||||
|
||||
elided = out.toString();
|
||||
}
|
||||
|
||||
return elided;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline.parse;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
public abstract class AbstractShaderElement {
|
||||
|
||||
public final Span self;
|
||||
|
||||
public AbstractShaderElement(Span self) {
|
||||
this.self = self;
|
||||
}
|
||||
|
||||
public abstract void checkErrors(ErrorReporter e);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline.parse;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
public class ErrorReporter {
|
||||
|
||||
|
||||
public String generateSpanError(Span span, String message) {
|
||||
SourceFile file = span.getSourceFile();
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline.parse;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.jozufozu.flywheel.backend.ShaderSources;
|
||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class Include extends AbstractShaderElement {
|
||||
|
||||
private final ShaderSources sources;
|
||||
private Span file;
|
||||
|
||||
private SourceFile resolution;
|
||||
|
||||
public Include(ShaderSources sources, Span self, Span file) {
|
||||
super(self);
|
||||
this.sources = sources;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public boolean isResolved() {
|
||||
return resolution != null;
|
||||
}
|
||||
|
||||
public Optional<SourceFile> getTarget() {
|
||||
return Optional.ofNullable(resolution);
|
||||
}
|
||||
|
||||
public ResourceLocation getFile() {
|
||||
return new ResourceLocation(file.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkErrors(ErrorReporter e) {
|
||||
|
||||
String name = file.get();
|
||||
|
||||
try {
|
||||
ResourceLocation loc = new ResourceLocation(name);
|
||||
resolution = sources.source(loc);
|
||||
} catch (RuntimeException error) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ import java.util.stream.Collectors;
|
|||
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
public class ShaderFunction {
|
||||
public class ShaderFunction extends AbstractShaderElement {
|
||||
|
||||
public static final Pattern argument = Pattern.compile("(\\w+)\\s+(\\w+)");
|
||||
public static final Pattern assignment = Pattern.compile("(\\w+)\\s*=");
|
||||
|
@ -17,16 +17,15 @@ public class ShaderFunction {
|
|||
private final Span name;
|
||||
private final Span args;
|
||||
private final Span body;
|
||||
private final Span self;
|
||||
|
||||
private final List<Variable> parameters;
|
||||
|
||||
public ShaderFunction(Span self, Span type, Span name, Span args, Span body) {
|
||||
super(self);
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.args = args;
|
||||
this.body = body;
|
||||
this.self = self;
|
||||
|
||||
this.parameters = new ArrayList<>();
|
||||
|
||||
|
@ -59,6 +58,11 @@ public class ShaderFunction {
|
|||
.map(Span::get)
|
||||
.collect(Collectors.joining(","));
|
||||
|
||||
return name + "(" + p + ")";
|
||||
return type + " " + name + "(" + p + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkErrors(ErrorReporter e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,36 +7,56 @@ import java.util.Map;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.jozufozu.flywheel.backend.loading.Program;
|
||||
import com.jozufozu.flywheel.backend.loading.TypeHelper;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
public class ShaderStruct {
|
||||
public class ShaderStruct extends AbstractShaderElement {
|
||||
|
||||
// https://regexr.com/5t207
|
||||
public static final Pattern struct = Pattern.compile("struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d \\t#\\[\\](),;\\n]*)}\\s*;");
|
||||
|
||||
public final Span self;
|
||||
public final Span name;
|
||||
public final Span body;
|
||||
|
||||
List<StructField> fields = new ArrayList<>(4);
|
||||
Map<String, String> fields2Types = new HashMap<>();
|
||||
private final ImmutableList<StructField> fields;
|
||||
private final ImmutableMap<String, Span> fields2Types;
|
||||
|
||||
public ShaderStruct(Span self, Span name, Span body) {
|
||||
this.self = self;
|
||||
super(self);
|
||||
this.name = name;
|
||||
this.body = body;
|
||||
parseFields();
|
||||
this.fields = parseFields();
|
||||
|
||||
ImmutableMap.Builder<String, Span> lookup = ImmutableMap.builder();
|
||||
for (StructField field : fields) {
|
||||
lookup.put(field.name.get(), field.type);
|
||||
}
|
||||
|
||||
this.fields2Types = lookup.build();
|
||||
}
|
||||
|
||||
private void parseFields() {
|
||||
Matcher fielder = StructField.fieldPattern.matcher(body.get());
|
||||
@Override
|
||||
public void checkErrors(ErrorReporter e) {
|
||||
|
||||
while (fielder.find()) {
|
||||
fields.add(new StructField(fielder));
|
||||
fields2Types.put(fielder.group(2), fielder.group(1));
|
||||
}
|
||||
|
||||
private ImmutableList<StructField> parseFields() {
|
||||
Matcher matcher = StructField.fieldPattern.matcher(body);
|
||||
|
||||
ImmutableList.Builder<StructField> fields = ImmutableList.builder();
|
||||
|
||||
while (matcher.find()) {
|
||||
Span field = Span.fromMatcher(body, matcher);
|
||||
Span type = Span.fromMatcher(body, matcher, 1);
|
||||
Span name = Span.fromMatcher(body, matcher, 2);
|
||||
|
||||
fields.add(new StructField(field, type, name));
|
||||
}
|
||||
|
||||
return fields.build();
|
||||
}
|
||||
|
||||
public void addPrefixedAttributes(Program builder, String prefix) {
|
||||
|
|
|
@ -4,24 +4,25 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
import com.jozufozu.flywheel.backend.loading.LayoutTag;
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
public class StructField {
|
||||
public class StructField extends AbstractShaderElement {
|
||||
public static final Pattern fieldPattern = Pattern.compile("(\\S+)\\s*(\\S+);");
|
||||
|
||||
public String name;
|
||||
public String type;
|
||||
public LayoutTag layout;
|
||||
public Span name;
|
||||
public Span type;
|
||||
|
||||
public StructField(Matcher fieldMatcher) {
|
||||
type = fieldMatcher.group(2);
|
||||
name = fieldMatcher.group(3);
|
||||
public StructField(Span self, Span name, Span type) {
|
||||
super(self);
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
public Span getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
public Span getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -29,4 +30,9 @@ public class StructField {
|
|||
public String toString() {
|
||||
return "TaggedField{" + "name='" + name + '\'' + ", type='" + type + '\'' + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkErrors(ErrorReporter e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,13 @@ package com.jozufozu.flywheel.backend.pipeline.parse;
|
|||
|
||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||
|
||||
public class Variable {
|
||||
public class Variable extends AbstractShaderElement {
|
||||
|
||||
private final Span self;
|
||||
private final Span type;
|
||||
private final Span name;
|
||||
|
||||
public Variable(Span self, Span type, Span name) {
|
||||
this.self = self;
|
||||
super(self);
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -21,4 +20,9 @@ public class Variable {
|
|||
public Span getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkErrors(ErrorReporter e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
@ParametersAreNonnullByDefault
|
||||
@MethodsReturnNonnullByDefault
|
||||
package com.jozufozu.flywheel.backend.pipeline.parse;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import mcp.MethodsReturnNonnullByDefault;
|
|
@ -0,0 +1,28 @@
|
|||
package com.jozufozu.flywheel.backend.pipeline.span;
|
||||
|
||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||
|
||||
public class CharPos {
|
||||
|
||||
private final int idx;
|
||||
private final int line;
|
||||
private final int col;
|
||||
|
||||
public CharPos(int idx, int line, int col) {
|
||||
this.idx = idx;
|
||||
this.line = line;
|
||||
this.col = col;
|
||||
}
|
||||
|
||||
public int getPos() {
|
||||
return idx;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public int getCol() {
|
||||
return col;
|
||||
}
|
||||
}
|
|
@ -11,6 +11,10 @@ public class ErrorSpan extends Span {
|
|||
super(in, start, end);
|
||||
}
|
||||
|
||||
public ErrorSpan(SourceFile in, CharPos start, CharPos end) {
|
||||
super(in, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Span subSpan(int from, int to) {
|
||||
return new ErrorSpan(in, start, end); // the sub-span of an error is an error in the same location
|
||||
|
|
|
@ -7,13 +7,17 @@ import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
|||
/**
|
||||
* A span of code in a {@link SourceFile}.
|
||||
*/
|
||||
public abstract class Span {
|
||||
public abstract class Span implements CharSequence {
|
||||
|
||||
protected final SourceFile in;
|
||||
protected final int start;
|
||||
protected final int end;
|
||||
protected final CharPos start;
|
||||
protected final CharPos end;
|
||||
|
||||
public Span(SourceFile in, int start, int end) {
|
||||
this(in, in.getCharPos(start), in.getCharPos(end));
|
||||
}
|
||||
|
||||
public Span(SourceFile in, CharPos start, CharPos end) {
|
||||
this.in = in;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
@ -24,11 +28,11 @@ public abstract class Span {
|
|||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
return start.getPos();
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return end;
|
||||
return end.getPos();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
|
@ -41,6 +45,21 @@ public abstract class Span {
|
|||
|
||||
public abstract boolean isErr();
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return end.getPos() - start.getPos();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return in.getSource().charAt(start.getPos() + index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
return subSpan(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return get();
|
||||
|
|
|
@ -8,15 +8,19 @@ public class StringSpan extends Span {
|
|||
super(in, start, end);
|
||||
}
|
||||
|
||||
public StringSpan(SourceFile in, CharPos start, CharPos end) {
|
||||
super(in, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Span subSpan(int from, int to) {
|
||||
return new StringSpan(in, start + from, start + to);
|
||||
return new StringSpan(in, start.getPos() + from, start.getPos() + to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
return in.getSource()
|
||||
.substring(start, end);
|
||||
.substring(start.getPos(), end.getPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue