mirror of
https://gitlab.kit.edu/uskyk/typicalc.git
synced 2024-11-09 10:50:42 +00:00
Code style in util and parser
This commit is contained in:
parent
8d6782793e
commit
1b642e84f9
@ -118,52 +118,56 @@ public class LambdaLexer {
|
|||||||
advance();
|
advance();
|
||||||
return new Result<>(t);
|
return new Result<>(t);
|
||||||
default:
|
default:
|
||||||
// only allow ascii characters in variable names
|
return parseAtomToken(c);
|
||||||
if (Character.isLetter(c) && (int) c < 128) {
|
}
|
||||||
int startPos = pos;
|
}
|
||||||
// identifier
|
|
||||||
StringBuilder sb = new StringBuilder();
|
private Result<Token, ParseError> parseAtomToken(char c) {
|
||||||
do {
|
// only allow ascii characters in variable names
|
||||||
sb.append(term.charAt(pos));
|
if (Character.isLetter(c) && (int) c < 128) {
|
||||||
advance();
|
int startPos = pos;
|
||||||
} while (pos < term.length() && Character.isLetterOrDigit(term.charAt(pos))
|
// identifier or keyword
|
||||||
&& (int) term.charAt(pos) < 128);
|
StringBuilder sb = new StringBuilder();
|
||||||
if (pos < term.length() && (int) term.charAt(pos) >= 128) {
|
do {
|
||||||
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER
|
sb.append(term.charAt(pos));
|
||||||
.withCharacter(term.charAt(pos), pos));
|
advance();
|
||||||
}
|
} while (pos < term.length() && Character.isLetterOrDigit(term.charAt(pos))
|
||||||
String s = sb.toString();
|
&& (int) term.charAt(pos) < 128);
|
||||||
TokenType type;
|
if (pos < term.length() && (int) term.charAt(pos) >= 128) {
|
||||||
switch (s) {
|
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER
|
||||||
case "let":
|
.withCharacter(term.charAt(pos), pos));
|
||||||
type = TokenType.LET;
|
}
|
||||||
break;
|
String s = sb.toString();
|
||||||
case "in":
|
TokenType type;
|
||||||
type = TokenType.IN;
|
switch (s) {
|
||||||
break;
|
case "let":
|
||||||
case "true":
|
type = TokenType.LET;
|
||||||
type = TokenType.TRUE;
|
break;
|
||||||
break;
|
case "in":
|
||||||
case "false":
|
type = TokenType.IN;
|
||||||
type = TokenType.FALSE;
|
break;
|
||||||
break;
|
case "true":
|
||||||
default:
|
type = TokenType.TRUE;
|
||||||
type = TokenType.VARIABLE;
|
break;
|
||||||
break;
|
case "false":
|
||||||
}
|
type = TokenType.FALSE;
|
||||||
return new Result<>(new Token(type, sb.toString(), startPos));
|
break;
|
||||||
} else if (Character.isDigit(c)) {
|
default:
|
||||||
int startPos = pos;
|
type = TokenType.VARIABLE;
|
||||||
// number literal
|
break;
|
||||||
StringBuilder sb = new StringBuilder();
|
}
|
||||||
do {
|
return new Result<>(new Token(type, sb.toString(), startPos));
|
||||||
sb.append(term.charAt(pos));
|
} else if (Character.isDigit(c)) {
|
||||||
advance();
|
int startPos = pos;
|
||||||
} while (pos < term.length() && Character.isDigit(term.charAt(pos)));
|
// number literal
|
||||||
return new Result<>(new Token(TokenType.NUMBER, sb.toString(), startPos));
|
StringBuilder sb = new StringBuilder();
|
||||||
} else {
|
do {
|
||||||
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER.withCharacter(c, pos));
|
sb.append(term.charAt(pos));
|
||||||
}
|
advance();
|
||||||
|
} while (pos < term.length() && Character.isDigit(term.charAt(pos)));
|
||||||
|
return new Result<>(new Token(TokenType.NUMBER, sb.toString(), startPos));
|
||||||
|
} else {
|
||||||
|
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER.withCharacter(c, pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -34,7 +34,7 @@ public class LambdaParser {
|
|||||||
|
|
||||||
private static final Set<TokenType> ATOM_START_TOKENS
|
private static final Set<TokenType> ATOM_START_TOKENS
|
||||||
= EnumSet.of(TokenType.VARIABLE, TokenType.NUMBER, TokenType.TRUE,
|
= EnumSet.of(TokenType.VARIABLE, TokenType.NUMBER, TokenType.TRUE,
|
||||||
TokenType.FALSE, TokenType.LEFT_PARENTHESIS);
|
TokenType.FALSE, TokenType.LEFT_PARENTHESIS, TokenType.LAMBDA, TokenType.LET);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a parser with the specified String
|
* Constructs a parser with the specified String
|
||||||
@ -85,10 +85,10 @@ public class LambdaParser {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
Optional<ParseError> next = expect(TokenType.EOF);
|
Optional<ParseError> next = expect(TokenType.EOF);
|
||||||
if (next.isPresent()) {
|
if (next.isEmpty()) {
|
||||||
return new Result<>(null, next.get());
|
return t;
|
||||||
}
|
}
|
||||||
return t;
|
return new Result<>(null, next.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,26 +103,10 @@ public class LambdaParser {
|
|||||||
return new Result<>(null, error.get());
|
return new Result<>(null, error.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (token.getType()) {
|
if (token.getType() == TokenType.EOF) {
|
||||||
case LAMBDA:
|
return new Result<>(null, ParseError.TOO_FEW_TOKENS);
|
||||||
Result<AbsTerm, ParseError> abs = parseAbstraction();
|
|
||||||
if (abs.isError()) {
|
|
||||||
return new Result<>(abs);
|
|
||||||
}
|
|
||||||
return new Result<>(abs.unwrap());
|
|
||||||
case LET:
|
|
||||||
Result<LetTerm, ParseError> let = parseLet();
|
|
||||||
if (let.isError()) {
|
|
||||||
return new Result<>(let);
|
|
||||||
}
|
|
||||||
return new Result<>(let.unwrap());
|
|
||||||
case VARIABLE:
|
|
||||||
return new Result<>(parseApplication());
|
|
||||||
case EOF:
|
|
||||||
return new Result<>(null, ParseError.TOO_FEW_TOKENS);
|
|
||||||
default:
|
|
||||||
return parseApplication();
|
|
||||||
}
|
}
|
||||||
|
return parseApplication();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Result<AbsTerm, ParseError> parseAbstraction() {
|
private Result<AbsTerm, ParseError> parseAbstraction() {
|
||||||
@ -148,20 +132,12 @@ public class LambdaParser {
|
|||||||
* @return the term, or an error
|
* @return the term, or an error
|
||||||
*/
|
*/
|
||||||
private Result<LambdaTerm, ParseError> parseApplication() {
|
private Result<LambdaTerm, ParseError> parseApplication() {
|
||||||
Result<LambdaTerm, ParseError> left = parseAtom();
|
Result<LambdaTerm, ParseError> left = parsePart();
|
||||||
if (left.isError()) {
|
if (left.isError()) {
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
while (ATOM_START_TOKENS.contains(token.getType())
|
while (ATOM_START_TOKENS.contains(token.getType())) {
|
||||||
|| token.getType() == TokenType.LAMBDA || token.getType() == TokenType.LET) {
|
Result<LambdaTerm, ParseError> atom = parsePart();
|
||||||
Result<LambdaTerm, ParseError> atom;
|
|
||||||
if (token.getType() == TokenType.LAMBDA) {
|
|
||||||
atom = new Result<>(parseAbstraction());
|
|
||||||
} else if (token.getType() == TokenType.LET) {
|
|
||||||
atom = new Result<>(parseLet());
|
|
||||||
} else {
|
|
||||||
atom = parseAtom();
|
|
||||||
}
|
|
||||||
if (atom.isError()) {
|
if (atom.isError()) {
|
||||||
return atom;
|
return atom;
|
||||||
}
|
}
|
||||||
@ -199,15 +175,28 @@ public class LambdaParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses an atom (variable or number) or a parenthesised expression.
|
* Parses a part of an expression (variable, constants, abstraction, let).
|
||||||
*
|
*
|
||||||
* @return the term
|
* @return the term
|
||||||
*/
|
*/
|
||||||
private Result<LambdaTerm, ParseError> parseAtom() {
|
private Result<LambdaTerm, ParseError> parsePart() {
|
||||||
switch (token.getType()) {
|
switch (token.getType()) {
|
||||||
case VARIABLE:
|
case VARIABLE:
|
||||||
Result<VarTerm, ParseError> var = parseVar();
|
Result<VarTerm, ParseError> var = parseVar();
|
||||||
return new Result<>(var.unwrap()); // variable token can always be parsed
|
return new Result<>(var.unwrap()); // variable token can always be parsed
|
||||||
|
case LAMBDA:
|
||||||
|
return new Result<>(parseAbstraction());
|
||||||
|
case LET:
|
||||||
|
return new Result<>(parseLet());
|
||||||
|
case TRUE:
|
||||||
|
case FALSE:
|
||||||
|
String boolText = token.getText();
|
||||||
|
boolean b = Boolean.parseBoolean(boolText);
|
||||||
|
Optional<ParseError> error = nextToken();
|
||||||
|
if (error.isEmpty()) {
|
||||||
|
return new Result<>(new BooleanTerm(b));
|
||||||
|
}
|
||||||
|
return new Result<>(null, error.get());
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
String number = token.getText();
|
String number = token.getText();
|
||||||
int n;
|
int n;
|
||||||
@ -216,20 +205,11 @@ public class LambdaParser {
|
|||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER.withToken(token));
|
return new Result<>(null, ParseError.UNEXPECTED_CHARACTER.withToken(token));
|
||||||
}
|
}
|
||||||
Optional<ParseError> error = nextToken();
|
|
||||||
if (error.isPresent()) {
|
|
||||||
return new Result<>(null, error.get());
|
|
||||||
}
|
|
||||||
return new Result<>(new IntegerTerm(n));
|
|
||||||
case TRUE:
|
|
||||||
case FALSE:
|
|
||||||
String boolText = token.getText();
|
|
||||||
boolean b = Boolean.parseBoolean(boolText);
|
|
||||||
error = nextToken();
|
error = nextToken();
|
||||||
if (error.isPresent()) {
|
if (error.isEmpty()) {
|
||||||
return new Result<>(null, error.get());
|
return new Result<>(new IntegerTerm(n));
|
||||||
}
|
}
|
||||||
return new Result<>(new BooleanTerm(b));
|
return new Result<>(null, error.get());
|
||||||
default:
|
default:
|
||||||
error = expect(TokenType.LEFT_PARENTHESIS);
|
error = expect(TokenType.LEFT_PARENTHESIS);
|
||||||
if (error.isPresent()) {
|
if (error.isPresent()) {
|
||||||
@ -237,19 +217,19 @@ public class LambdaParser {
|
|||||||
}
|
}
|
||||||
Result<LambdaTerm, ParseError> term = parseTerm(false);
|
Result<LambdaTerm, ParseError> term = parseTerm(false);
|
||||||
error = expect(TokenType.RIGHT_PARENTHESIS);
|
error = expect(TokenType.RIGHT_PARENTHESIS);
|
||||||
if (error.isPresent()) {
|
if (error.isEmpty()) {
|
||||||
return new Result<>(null, error.get());
|
return term;
|
||||||
}
|
}
|
||||||
return term;
|
return new Result<>(null, error.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Result<VarTerm, ParseError> parseVar() {
|
private Result<VarTerm, ParseError> parseVar() {
|
||||||
String s = token.getText();
|
String s = token.getText();
|
||||||
Optional<ParseError> next = expect(TokenType.VARIABLE);
|
Optional<ParseError> next = expect(TokenType.VARIABLE);
|
||||||
if (next.isPresent()) {
|
if (next.isEmpty()) {
|
||||||
return new Result<>(null, next.get());
|
return new Result<>(new VarTerm(s));
|
||||||
}
|
}
|
||||||
return new Result<>(new VarTerm(s));
|
return new Result<>(null, next.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ public class Token {
|
|||||||
RIGHT_PARENTHESIS, // )
|
RIGHT_PARENTHESIS, // )
|
||||||
DOT, // .
|
DOT, // .
|
||||||
EQUALS, // =
|
EQUALS, // =
|
||||||
ARROW, // -> TODO: document
|
ARROW, // ->
|
||||||
EOF // pseudo token if end of file is reached
|
EOF // pseudo token if end of file is reached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ public class Result<T, E> {
|
|||||||
*
|
*
|
||||||
* @param other the result
|
* @param other the result
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public Result(Result<?, ?> other) {
|
public Result(Result<?, ?> other) {
|
||||||
this.value = (T) other.value;
|
this.value = (T) other.value;
|
||||||
this.error = (E) other.error;
|
this.error = (E) other.error;
|
||||||
@ -42,7 +43,7 @@ public class Result<T, E> {
|
|||||||
*/
|
*/
|
||||||
public Result(T value, E error) {
|
public Result(T value, E error) {
|
||||||
if ((value != null) == (error != null)) {
|
if ((value != null) == (error != null)) {
|
||||||
throw new IllegalArgumentException("value xor error must be null in constructor!");
|
throw new IllegalArgumentException("value or error must be null in constructor!");
|
||||||
}
|
}
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.error = error;
|
this.error = error;
|
||||||
|
@ -31,7 +31,7 @@ public class LambdaTermGenerator extends Generator<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private LambdaTerm generateReal(SourceOfRandomness random) {
|
private LambdaTerm generateReal(SourceOfRandomness random) {
|
||||||
if (random.nextInt(1, 7) < 3) {
|
if (random.nextInt(1, 10) < 3) {
|
||||||
LambdaTerm one = generateReal(random);
|
LambdaTerm one = generateReal(random);
|
||||||
LambdaTerm two = generateReal(random);
|
LambdaTerm two = generateReal(random);
|
||||||
if (random.nextInt(1, 10) < 8) {
|
if (random.nextInt(1, 10) < 8) {
|
||||||
|
Loading…
Reference in New Issue
Block a user