mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-01 01:46:39 +01:00
Better errors still
- Actually can print something that underlines a span - Resolve imports and use the resolutions during building - Doesn't actually make sense to have #checkErrors - Simplify some regexes - Parse structs
This commit is contained in:
parent
279d3a2de7
commit
95dabd900e
13 changed files with 197 additions and 62 deletions
|
@ -89,6 +89,8 @@ public class ShaderSources implements ISelectiveResourceReloadListener {
|
||||||
loadProgramSpecs(manager);
|
loadProgramSpecs(manager);
|
||||||
loadShaderSources(manager);
|
loadShaderSources(manager);
|
||||||
|
|
||||||
|
shaderSources.values().forEach(SourceFile::resolveIncludes);
|
||||||
|
|
||||||
WorldShaderPipeline<WorldProgram> pl = new WorldShaderPipeline<>(this);
|
WorldShaderPipeline<WorldProgram> pl = new WorldShaderPipeline<>(this);
|
||||||
|
|
||||||
SourceFile source = source(new ResourceLocation(Flywheel.ID, "model.glsl"));
|
SourceFile source = source(new ResourceLocation(Flywheel.ID, "model.glsl"));
|
||||||
|
|
|
@ -15,28 +15,25 @@ import net.minecraft.util.ResourceLocation;
|
||||||
public class Includer {
|
public class Includer {
|
||||||
|
|
||||||
public static List<SourceFile> recurseIncludes(SourceFile from) {
|
public static List<SourceFile> recurseIncludes(SourceFile from) {
|
||||||
ShaderSources sources = from.getParent();
|
|
||||||
|
|
||||||
Set<ResourceLocation> seen = new HashSet<>();
|
Set<ResourceLocation> seen = new HashSet<>();
|
||||||
|
|
||||||
seen.add(from.name);
|
seen.add(from.name);
|
||||||
|
|
||||||
List<SourceFile> out = new ArrayList<>();
|
List<SourceFile> out = new ArrayList<>();
|
||||||
|
|
||||||
process(sources, seen, out, from);
|
process(seen, out, from);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void process(ShaderSources sources, Set<ResourceLocation> seen, List<SourceFile> out, SourceFile source) {
|
private static void process(Set<ResourceLocation> seen, List<SourceFile> out, SourceFile source) {
|
||||||
ImmutableList<Include> includes = source.getIncludes();
|
ImmutableList<Include> includes = source.getIncludes();
|
||||||
|
|
||||||
for (Include include : includes) {
|
for (Include include : includes) {
|
||||||
|
|
||||||
if (seen.add(include.getFile())) {
|
SourceFile file = include.getTarget();
|
||||||
SourceFile file = sources.source(include.getFile());
|
if (file != null && seen.add(file.name)) {
|
||||||
|
process(seen, out, file);
|
||||||
process(sources, seen, out, file);
|
|
||||||
|
|
||||||
out.add(file);
|
out.add(file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,20 +10,23 @@ import java.util.regex.Pattern;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.jozufozu.flywheel.backend.ShaderSources;
|
import com.jozufozu.flywheel.backend.ShaderSources;
|
||||||
|
import com.jozufozu.flywheel.backend.pipeline.error.ErrorReporter;
|
||||||
|
import com.jozufozu.flywheel.backend.pipeline.parse.AbstractShaderElement;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.parse.Include;
|
import com.jozufozu.flywheel.backend.pipeline.parse.Include;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.parse.ShaderFunction;
|
import com.jozufozu.flywheel.backend.pipeline.parse.ShaderFunction;
|
||||||
|
import com.jozufozu.flywheel.backend.pipeline.parse.ShaderStruct;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.span.CharPos;
|
import com.jozufozu.flywheel.backend.pipeline.span.CharPos;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.span.ErrorSpan;
|
import com.jozufozu.flywheel.backend.pipeline.span.ErrorSpan;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.span.StringSpan;
|
import com.jozufozu.flywheel.backend.pipeline.span.StringSpan;
|
||||||
|
import com.jozufozu.flywheel.util.StringUtil;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
import it.unimi.dsi.fastutil.ints.IntList;
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
public class SourceFile {
|
public class SourceFile {
|
||||||
// #use "valid_namespace:valid/path_to_file.glsl"
|
private static final Pattern includePattern = Pattern.compile("#use \"(.*)\"");
|
||||||
private static final Pattern includePattern = Pattern.compile("#use \"(\\w+:[\\w./]+)\"");
|
|
||||||
|
|
||||||
private static final Pattern newLine = Pattern.compile("(\\r\\n|\\r|\\n)");
|
private static final Pattern newLine = Pattern.compile("(\\r\\n|\\r|\\n)");
|
||||||
|
|
||||||
|
@ -34,11 +37,13 @@ public class SourceFile {
|
||||||
|
|
||||||
private final ShaderSources parent;
|
private final ShaderSources parent;
|
||||||
private final String source;
|
private final String source;
|
||||||
|
private final ImmutableList<String> lines;
|
||||||
|
|
||||||
private final IntList lineStarts;
|
private final IntList lineStarts;
|
||||||
|
|
||||||
// Function name -> Function object
|
// Function name -> Function object
|
||||||
private final ImmutableMap<String, ShaderFunction> functions;
|
private final ImmutableMap<String, ShaderFunction> functions;
|
||||||
|
private final ImmutableMap<String, ShaderStruct> structs;
|
||||||
|
|
||||||
// Includes ordered as defined in the source
|
// Includes ordered as defined in the source
|
||||||
private final ImmutableList<Include> includes;
|
private final ImmutableList<Include> includes;
|
||||||
|
@ -51,10 +56,12 @@ public class SourceFile {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
|
|
||||||
this.lineStarts = getLinePositions();
|
this.lineStarts = createLineStarts();
|
||||||
|
this.lines = createLineList(lineStarts);
|
||||||
|
|
||||||
this.functions = parseFunctions();
|
|
||||||
this.includes = parseIncludes();
|
this.includes = parseIncludes();
|
||||||
|
this.functions = parseFunctions();
|
||||||
|
this.structs = parseStructs();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSource() {
|
public String getSource() {
|
||||||
|
@ -73,6 +80,12 @@ public class SourceFile {
|
||||||
return includes;
|
return includes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resolveIncludes() {
|
||||||
|
for (Include include : includes) {
|
||||||
|
include.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public CharPos getCharPos(int charPos) {
|
public CharPos getCharPos(int charPos) {
|
||||||
int lineNo = 0;
|
int lineNo = 0;
|
||||||
for (; lineNo < lineStarts.size(); lineNo++) {
|
for (; lineNo < lineStarts.size(); lineNo++) {
|
||||||
|
@ -83,7 +96,9 @@ public class SourceFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int lineStart = lineStarts.getInt(lineNo - 1);
|
lineNo -= 1;
|
||||||
|
|
||||||
|
int lineStart = lineStarts.getInt(lineNo);
|
||||||
|
|
||||||
return new CharPos(charPos, lineNo, charPos - lineStart);
|
return new CharPos(charPos, lineNo, charPos - lineStart);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +110,7 @@ public class SourceFile {
|
||||||
.append(name)
|
.append(name)
|
||||||
.append("':\n");
|
.append("':\n");
|
||||||
int i = 1;
|
int i = 1;
|
||||||
for (String s : source.split("\n")) {
|
for (String s : lines) {
|
||||||
builder.append(String.format("%1$4s: ", i++))
|
builder.append(String.format("%1$4s: ", i++))
|
||||||
.append(s)
|
.append(s)
|
||||||
.append('\n');
|
.append('\n');
|
||||||
|
@ -129,7 +144,7 @@ public class SourceFile {
|
||||||
/**
|
/**
|
||||||
* Scan the source for line breaks, recording the position of the first character of each line.
|
* Scan the source for line breaks, recording the position of the first character of each line.
|
||||||
*/
|
*/
|
||||||
private IntList getLinePositions() {
|
private IntList createLineStarts() {
|
||||||
IntList l = new IntArrayList();
|
IntList l = new IntArrayList();
|
||||||
l.add(0); // first line is always at position 0
|
l.add(0); // first line is always at position 0
|
||||||
|
|
||||||
|
@ -141,6 +156,19 @@ public class SourceFile {
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ImmutableList<String> createLineList(IntList lines) {
|
||||||
|
ImmutableList.Builder<String> builder = ImmutableList.builder();
|
||||||
|
|
||||||
|
for (int i = 1; i < lines.size(); i++) {
|
||||||
|
int start = lines.getInt(i - 1);
|
||||||
|
int end = lines.getInt(i);
|
||||||
|
|
||||||
|
builder.add(StringUtil.trimEnd(source.substring(start, end)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan the source for function definitions and "parse" them into objects that contain properties of the function.
|
* Scan the source for function definitions and "parse" them into objects that contain properties of the function.
|
||||||
*/
|
*/
|
||||||
|
@ -175,6 +203,26 @@ public class SourceFile {
|
||||||
return ImmutableMap.copyOf(functions);
|
return ImmutableMap.copyOf(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan the source for function definitions and "parse" them into objects that contain properties of the function.
|
||||||
|
*/
|
||||||
|
private ImmutableMap<String, ShaderStruct> parseStructs() {
|
||||||
|
Matcher matcher = ShaderStruct.struct.matcher(source);
|
||||||
|
|
||||||
|
ImmutableMap.Builder<String, ShaderStruct> functions = ImmutableMap.builder();
|
||||||
|
while (matcher.find()) {
|
||||||
|
Span self = Span.fromMatcher(this, matcher);
|
||||||
|
Span name = Span.fromMatcher(this, matcher, 1);
|
||||||
|
Span body = Span.fromMatcher(this, matcher, 2);
|
||||||
|
|
||||||
|
ShaderStruct shaderStruct = new ShaderStruct(self, name, body);
|
||||||
|
|
||||||
|
functions.put(body.get(), shaderStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
return functions.build();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan the source for <code>#use "..."</code> directives.
|
* 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.
|
* Records the contents of the directive into an {@link Include} object, and marks the directive for elision.
|
||||||
|
@ -214,4 +262,12 @@ public class SourceFile {
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getLineCount() {
|
||||||
|
return lines.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharSequence getLine(int lineNo) {
|
||||||
|
return lines.get(lineNo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package com.jozufozu.flywheel.backend.pipeline.error;
|
package com.jozufozu.flywheel.backend.pipeline.error;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||||
|
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||||
|
|
||||||
public class ErrorBuilder {
|
public class ErrorBuilder {
|
||||||
|
|
||||||
private StringBuilder internal;
|
private final StringBuilder internal = new StringBuilder();
|
||||||
|
|
||||||
public ErrorBuilder header(CharSequence msg) {
|
public ErrorBuilder header(CharSequence msg) {
|
||||||
internal.append("error: ")
|
internal.append("error: ")
|
||||||
|
@ -18,7 +19,15 @@ public class ErrorBuilder {
|
||||||
return endLine();
|
return endLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErrorBuilder line(int no, CharSequence content) {
|
public ErrorBuilder numberedLine(int no, CharSequence content) {
|
||||||
|
return line(String.valueOf(no), content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ErrorBuilder line(CharSequence leftColumn, CharSequence rightColumn) {
|
||||||
|
|
||||||
|
internal.append(leftColumn)
|
||||||
|
.append(" | ")
|
||||||
|
.append(rightColumn);
|
||||||
|
|
||||||
return endLine();
|
return endLine();
|
||||||
}
|
}
|
||||||
|
@ -27,4 +36,49 @@ public class ErrorBuilder {
|
||||||
internal.append('\n');
|
internal.append('\n');
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ErrorBuilder pointAt(Span span, int ctxLines) {
|
||||||
|
SourceFile file = span.getSourceFile();
|
||||||
|
|
||||||
|
if (span.lines() == 1) {
|
||||||
|
|
||||||
|
int spanLine = span.firstLine();
|
||||||
|
|
||||||
|
int firstLine = Math.max(0, spanLine - ctxLines);
|
||||||
|
int lastLine = Math.min(file.getLineCount(), spanLine + ctxLines);
|
||||||
|
|
||||||
|
|
||||||
|
int firstCol = span.getStart().getCol();
|
||||||
|
int lastCol = span.getEnd().getCol();
|
||||||
|
|
||||||
|
for (int i = firstLine; i <= lastLine; i++) {
|
||||||
|
CharSequence line = file.getLine(i);
|
||||||
|
|
||||||
|
numberedLine(i + 1, line);
|
||||||
|
|
||||||
|
if (i == spanLine) {
|
||||||
|
line(" ", generateUnderline(firstCol, lastCol));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharSequence build() {
|
||||||
|
return internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharSequence generateUnderline(int firstCol, int lastCol) {
|
||||||
|
StringBuilder line = new StringBuilder(lastCol);
|
||||||
|
for (int i = 0; i < firstCol; i++) {
|
||||||
|
line.append(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = firstCol; i < lastCol; i++) {
|
||||||
|
line.append('^');
|
||||||
|
}
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
package com.jozufozu.flywheel.backend.pipeline.error;
|
package com.jozufozu.flywheel.backend.pipeline.error;
|
||||||
|
|
||||||
|
import com.jozufozu.flywheel.backend.Backend;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||||
|
|
||||||
public class ErrorReporter {
|
public class ErrorReporter {
|
||||||
|
|
||||||
|
public static void generateSpanError(Span span, String message) {
|
||||||
public String generateSpanError(Span span, String message) {
|
|
||||||
SourceFile file = span.getSourceFile();
|
SourceFile file = span.getSourceFile();
|
||||||
|
|
||||||
|
ErrorBuilder builder = new ErrorBuilder();
|
||||||
|
|
||||||
|
CharSequence error = builder.header(message)
|
||||||
|
.errorIn(file)
|
||||||
|
.pointAt(span, 2)
|
||||||
|
.build();
|
||||||
|
|
||||||
return "";
|
Backend.log.info(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.jozufozu.flywheel.backend.pipeline.parse;
|
package com.jozufozu.flywheel.backend.pipeline.parse;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.pipeline.error.ErrorReporter;
|
|
||||||
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||||
|
|
||||||
public abstract class AbstractShaderElement {
|
public abstract class AbstractShaderElement {
|
||||||
|
@ -11,5 +10,4 @@ public abstract class AbstractShaderElement {
|
||||||
this.self = self;
|
this.self = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void checkErrors(ErrorReporter e);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package com.jozufozu.flywheel.backend.pipeline.parse;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.jozufozu.flywheel.backend.ShaderSources;
|
import com.jozufozu.flywheel.backend.ShaderSources;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.error.ErrorReporter;
|
import com.jozufozu.flywheel.backend.pipeline.error.ErrorReporter;
|
||||||
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
import com.jozufozu.flywheel.backend.pipeline.SourceFile;
|
||||||
|
@ -14,37 +16,43 @@ public class Include extends AbstractShaderElement {
|
||||||
private final ShaderSources sources;
|
private final ShaderSources sources;
|
||||||
private Span file;
|
private Span file;
|
||||||
|
|
||||||
|
private ResourceLocation fileLoc;
|
||||||
private SourceFile resolution;
|
private SourceFile resolution;
|
||||||
|
|
||||||
|
|
||||||
public Include(ShaderSources sources, Span self, Span file) {
|
public Include(ShaderSources sources, Span self, Span file) {
|
||||||
super(self);
|
super(self);
|
||||||
this.sources = sources;
|
this.sources = sources;
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
|
try {
|
||||||
|
fileLoc = new ResourceLocation(file.get());
|
||||||
|
} catch (RuntimeException error) {
|
||||||
|
ErrorReporter.generateSpanError(file, "malformed source name");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isResolved() {
|
public boolean isResolved() {
|
||||||
return resolution != null;
|
return resolution != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<SourceFile> getTarget() {
|
@Nullable
|
||||||
return Optional.ofNullable(resolution);
|
public SourceFile getTarget() {
|
||||||
|
return resolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceLocation getFile() {
|
public ResourceLocation getFile() {
|
||||||
return new ResourceLocation(file.get());
|
return fileLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void resolve() {
|
||||||
public void checkErrors(ErrorReporter e) {
|
|
||||||
|
|
||||||
String name = file.get();
|
if (fileLoc == null) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ResourceLocation loc = new ResourceLocation(name);
|
resolution = sources.source(fileLoc);
|
||||||
resolution = sources.source(loc);
|
|
||||||
} catch (RuntimeException error) {
|
} catch (RuntimeException error) {
|
||||||
|
ErrorReporter.generateSpanError(file, "could not find source");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,9 +61,4 @@ public class ShaderFunction extends AbstractShaderElement {
|
||||||
|
|
||||||
return type + " " + name + "(" + p + ")";
|
return type + " " + name + "(" + p + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkErrors(ErrorReporter e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.jozufozu.flywheel.backend.pipeline.parse;
|
package com.jozufozu.flywheel.backend.pipeline.parse;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -12,8 +13,8 @@ import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||||
|
|
||||||
public class ShaderStruct extends AbstractShaderElement {
|
public class ShaderStruct extends AbstractShaderElement {
|
||||||
|
|
||||||
// https://regexr.com/5t207
|
// https://regexr.com/61rpe
|
||||||
public static final Pattern struct = Pattern.compile("struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d \\t#\\[\\](),;\\n]*)}\\s*;");
|
public static final Pattern struct = Pattern.compile("struct\\s+([\\w\\d]*)\\s*\\{([\\w\\d\\s,;]*)}\\s*;\\s");
|
||||||
|
|
||||||
public final Span name;
|
public final Span name;
|
||||||
public final Span body;
|
public final Span body;
|
||||||
|
@ -26,18 +27,16 @@ public class ShaderStruct extends AbstractShaderElement {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.fields = parseFields();
|
this.fields = parseFields();
|
||||||
|
this.fields2Types = createTypeLookup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableMap<String, Span> createTypeLookup() {
|
||||||
ImmutableMap.Builder<String, Span> lookup = ImmutableMap.builder();
|
ImmutableMap.Builder<String, Span> lookup = ImmutableMap.builder();
|
||||||
for (StructField field : fields) {
|
for (StructField field : fields) {
|
||||||
lookup.put(field.name.get(), field.type);
|
lookup.put(field.name.get(), field.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fields2Types = lookup.build();
|
return lookup.build();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkErrors(ErrorReporter e) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableList<StructField> parseFields() {
|
private ImmutableList<StructField> parseFields() {
|
||||||
|
|
|
@ -8,30 +8,25 @@ import com.jozufozu.flywheel.backend.pipeline.span.Span;
|
||||||
public class StructField extends AbstractShaderElement {
|
public class StructField extends AbstractShaderElement {
|
||||||
public static final Pattern fieldPattern = Pattern.compile("(\\S+)\\s*(\\S+);");
|
public static final Pattern fieldPattern = Pattern.compile("(\\S+)\\s*(\\S+);");
|
||||||
|
|
||||||
public Span name;
|
|
||||||
public Span type;
|
public Span type;
|
||||||
|
public Span name;
|
||||||
|
|
||||||
public StructField(Span self, Span name, Span type) {
|
public StructField(Span self, Span type, Span name) {
|
||||||
super(self);
|
super(self);
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
this.name = name;
|
||||||
|
|
||||||
public Span getName() {
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Span getType() {
|
public Span getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Span getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TaggedField{" + "name='" + name + '\'' + ", type='" + type + '\'' + '}';
|
return "TaggedField{" + "name='" + name + '\'' + ", type='" + type + '\'' + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkErrors(ErrorReporter e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,4 @@ public class Variable extends AbstractShaderElement {
|
||||||
public Span getName() {
|
public Span getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkErrors(ErrorReporter e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,14 @@ public abstract class Span implements CharSequence {
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CharPos getStart() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharPos getEnd() {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the string index at the (inclusive) beginning of this code segment.
|
* @return the string index at the (inclusive) beginning of this code segment.
|
||||||
*/
|
*/
|
||||||
|
@ -51,6 +59,17 @@ public abstract class Span implements CharSequence {
|
||||||
return start == end;
|
return start == end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return how many lines this span spans.
|
||||||
|
*/
|
||||||
|
public int lines() {
|
||||||
|
return end.getLine() - start.getLine() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int firstLine() {
|
||||||
|
return start.getLine();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a span referring to a code segment inside this code segment.
|
* Get a span referring to a code segment inside this code segment.
|
||||||
*/
|
*/
|
||||||
|
|
12
src/main/java/com/jozufozu/flywheel/util/StringUtil.java
Normal file
12
src/main/java/com/jozufozu/flywheel/util/StringUtil.java
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package com.jozufozu.flywheel.util;
|
||||||
|
|
||||||
|
public class StringUtil {
|
||||||
|
public static String trimEnd(String value) {
|
||||||
|
int len = value.length();
|
||||||
|
int st = 0;
|
||||||
|
while ((st < len) && Character.isWhitespace(value.charAt(len - 1))) {
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
return value.substring(0, len);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue