Parse error highlighting for include statement

This commit is contained in:
aNNiMON 2023-10-14 14:34:05 +03:00 committed by Victor Melnik
parent a05e9e55e3
commit f6d4ff5cc9
5 changed files with 62 additions and 55 deletions

View File

@ -1,12 +1,11 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.parser.Lexer; import com.annimon.ownlang.exceptions.OwnLangParserException;
import com.annimon.ownlang.parser.Parser; import com.annimon.ownlang.exceptions.OwnLangRuntimeException;
import com.annimon.ownlang.parser.SourceLoader; import com.annimon.ownlang.parser.error.ParseErrorsFormatterStage;
import com.annimon.ownlang.parser.Token; import com.annimon.ownlang.stages.*;
import com.annimon.ownlang.parser.visitors.FunctionAdder; import com.annimon.ownlang.util.input.InputSourceFile;
import java.io.IOException; import com.annimon.ownlang.util.input.SourceLoaderStage;
import java.util.List;
/** /**
* *
@ -23,21 +22,21 @@ public final class IncludeStatement extends InterruptableNode implements Stateme
@Override @Override
public void execute() { public void execute() {
super.interruptionCheck(); super.interruptionCheck();
try {
final Statement program = loadProgram(expression.eval().asString());
if (program != null) {
program.accept(new FunctionAdder());
program.execute();
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public Statement loadProgram(String path) throws IOException { final var stagesData = new StagesDataMap();
final String input = SourceLoader.readSource(path); try {
final List<Token> tokens = Lexer.tokenize(input); final String path = expression.eval().asString();
return Parser.parse(tokens); new SourceLoaderStage()
.then(new LexerStage())
.then(new ParserStage())
.then(new FunctionAddingStage())
.then(new ExecutionStage())
.perform(stagesData, new InputSourceFile(path));
} catch (OwnLangParserException ex) {
final var error = new ParseErrorsFormatterStage()
.perform(stagesData, ex.getParseErrors());
throw new OwnLangRuntimeException(error, ex);
}
} }
@Override @Override

View File

@ -53,27 +53,27 @@ public final class UnaryExpression implements Expression, Statement {
final Value value = expr1.eval(); final Value value = expr1.eval();
switch (operation) { switch (operation) {
case INCREMENT_PREFIX: { case INCREMENT_PREFIX: {
if (expr1 instanceof Accessible) { if (expr1 instanceof Accessible accessible) {
return ((Accessible) expr1).set(increment(value)); return accessible.set(increment(value));
} }
return increment(value); return increment(value);
} }
case DECREMENT_PREFIX: { case DECREMENT_PREFIX: {
if (expr1 instanceof Accessible) { if (expr1 instanceof Accessible accessible) {
return ((Accessible) expr1).set(decrement(value)); return accessible.set(decrement(value));
} }
return decrement(value); return decrement(value);
} }
case INCREMENT_POSTFIX: { case INCREMENT_POSTFIX: {
if (expr1 instanceof Accessible) { if (expr1 instanceof Accessible accessible) {
((Accessible) expr1).set(increment(value)); accessible.set(increment(value));
return value; return value;
} }
return increment(value); return increment(value);
} }
case DECREMENT_POSTFIX: { case DECREMENT_POSTFIX: {
if (expr1 instanceof Accessible) { if (expr1 instanceof Accessible accessible) {
((Accessible) expr1).set(decrement(value)); accessible.set(decrement(value));
return value; return value;
} }
return decrement(value); return decrement(value);

View File

@ -3,6 +3,10 @@ package com.annimon.ownlang.parser.visitors;
import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Types; import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.parser.Lexer;
import com.annimon.ownlang.parser.Parser;
import com.annimon.ownlang.parser.SourceLoader;
import com.annimon.ownlang.parser.Token;
import com.annimon.ownlang.parser.ast.BinaryExpression; import com.annimon.ownlang.parser.ast.BinaryExpression;
import com.annimon.ownlang.parser.ast.ConditionalExpression; import com.annimon.ownlang.parser.ast.ConditionalExpression;
import com.annimon.ownlang.parser.ast.IncludeStatement; import com.annimon.ownlang.parser.ast.IncludeStatement;
@ -13,6 +17,7 @@ import com.annimon.ownlang.parser.ast.ValueExpression;
import com.annimon.ownlang.parser.ast.VariableExpression; import com.annimon.ownlang.parser.ast.VariableExpression;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
public final class VisitorUtils { public final class VisitorUtils {
@ -28,9 +33,12 @@ public final class VisitorUtils {
} }
public static Statement includeProgram(IncludeStatement s) { public static Statement includeProgram(IncludeStatement s) {
if (!isValue(s)) return null; if (!isValue(s.expression)) return null;
try { try {
return s.loadProgram(s.expression.eval().asString()); final String path = s.expression.eval().asString();
final String input = SourceLoader.readSource(path);
final List<Token> tokens = Lexer.tokenize(input);
return Parser.parse(tokens);
} catch (IOException ex) { } catch (IOException ex) {
return null; return null;
} }

View File

@ -1,4 +1,4 @@
use std, yaml, ounit use std, yaml
x = yamldecode(" x = yamldecode("
name: \"std\" name: \"std\"
@ -23,9 +23,9 @@ x = yamldecode("
print typeof([]) // 3 (ARRAY) print typeof([]) // 3 (ARRAY)
") ")
assertEquals("std", x.name) assertEquals("std", x.name)
assertEquals("both", x.scope) assertEquals("both", x.scope)
assertEquals(0, length(x.constants)) assertEquals(0, x.constants.length)
assertEquals(2, length(x.functions)) assertEquals(2, x.functions.length)
assertEquals("arrayCombine", x.functions[0].name) assertEquals("arrayCombine", x.functions[0].name)
assertEquals("возвращает тип переданного значения", x.functions[1].desc_ru) assertEquals("возвращает тип переданного значения", x.functions[1].desc_ru)

View File

@ -1,4 +1,4 @@
use std, yaml, ounit use std, yaml
yml = yamlencode({ yml = yamlencode({
"name": "Yaml Example", "name": "Yaml Example",
@ -10,11 +10,11 @@ yml = yamlencode({
"key": "value", "key": "value",
10: "1000" 10: "1000"
} }
}) })
obj = yamldecode(yml) obj = yamldecode(yml)
assertEquals("Yaml Example", obj.name) assertEquals("Yaml Example", obj.name)
assertEquals(1, obj.version) assertEquals(1, obj.version)
assertEquals(4, length(obj.arrayData)) assertEquals(4, length(obj.arrayData))
assertEquals("value", obj.objectData.key) assertEquals("value", obj.objectData.key)
assertEquals("1000", obj.objectData["10"]) assertEquals("1000", obj.objectData["10"])