use of dyvilx.tools.compiler.parser.type.TypeParser in project Dyvil by Dyvil.
the class ClassDeclarationParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
int type = token.type();
switch(this.mode) {
case NAME:
if (!Tokens.isIdentifier(type)) {
pm.report(token, "class.identifier");
return;
}
final Name name = token.nameValue();
if (name.qualified.indexOf('$') >= 0) {
pm.report(Markers.syntaxError(token, "class.identifier.invalid", name, name.qualified));
}
this.theClass = this.consumer.createClass(token.raw(), name, this.classAttributes);
this.mode = GENERICS;
return;
case GENERICS:
if (type == BaseSymbols.SEMICOLON && token.isInferred() && TypeParser.isGenericStart(token.next())) {
// allow an implicit semicolon / line break between name and generic argument list
return;
}
if (TypeParser.isGenericStart(token, type)) {
pm.splitJump(token, 1);
pm.pushParser(new TypeParameterListParser(this.theClass));
this.mode = GENERICS_END;
return;
}
// Fallthrough
case PARAMETERS:
final Modifier modifier = ModifierParser.parseModifier(token, pm);
if (modifier != null) {
this.theClass.getConstructorAttributes().add(modifier);
return;
}
if (type == DyvilSymbols.AT) {
final Annotation annotation = new CodeAnnotation(token.raw());
this.theClass.getConstructorAttributes().add(annotation);
pm.pushParser(new AnnotationParser(annotation));
return;
}
if (type == BaseSymbols.OPEN_PARENTHESIS) {
pm.pushParser(new ParameterListParser(this.theClass).withFlags(ParameterListParser.ALLOW_PROPERTIES));
this.mode = PARAMETERS_END;
return;
}
// Fallthrough
case EXTENDS:
if (type == DyvilKeywords.EXTENDS) {
if (this.theClass.isInterface()) {
pm.pushParser(new TypeListParser(this));
this.mode = BODY;
return;
}
pm.pushParser(new TypeParser(this));
this.mode = EXTENDS_PARAMETERS;
return;
}
// Fallthrough
case IMPLEMENTS:
if (type == DyvilKeywords.IMPLEMENTS) {
pm.pushParser(new TypeListParser(this));
this.mode = BODY;
if (this.theClass.isInterface()) {
pm.report(token, "class.interface.implements");
return;
}
return;
}
// Fallthrough
case BODY:
if (type == BaseSymbols.OPEN_CURLY_BRACKET) {
ClassBody body = new ClassBody(this.theClass);
this.theClass.setBody(body);
pm.pushParser(new ClassBodyParser(body), true);
this.mode = BODY_END;
return;
}
if (BaseSymbols.isTerminator(type)) {
if (token.isInferred()) {
switch(token.next().type()) {
case DyvilKeywords.EXTENDS:
this.mode = EXTENDS;
return;
case DyvilKeywords.IMPLEMENTS:
this.mode = IMPLEMENTS;
return;
case BaseSymbols.OPEN_SQUARE_BRACKET:
this.mode = GENERICS;
return;
case BaseSymbols.OPEN_PARENTHESIS:
this.mode = PARAMETERS;
return;
}
}
pm.popParser(true);
this.consumer.addClass(this.theClass);
return;
}
this.mode = BODY_END;
pm.report(token, "class.body.separator");
return;
case GENERICS_END:
this.mode = PARAMETERS;
if (TypeParser.isGenericEnd(token, type)) {
pm.splitJump(token, 1);
return;
}
pm.reparse();
pm.report(token, "generic.close_angle");
return;
case PARAMETERS_END:
this.mode = EXTENDS;
if (type != BaseSymbols.CLOSE_PARENTHESIS) {
pm.reparse();
pm.report(token, "class.parameters.close_paren");
}
return;
case BODY_END:
pm.popParser();
this.consumer.addClass(this.theClass);
if (type != BaseSymbols.CLOSE_CURLY_BRACKET) {
pm.reparse();
pm.report(token, "class.body.close_brace");
}
return;
case EXTENDS_PARAMETERS_END:
this.mode = IMPLEMENTS;
if (type != BaseSymbols.CLOSE_PARENTHESIS) {
pm.reparse();
pm.report(token, "class.extends.close_paren");
}
return;
case EXTENDS_PARAMETERS:
if (type == BaseSymbols.OPEN_PARENTHESIS) {
ArgumentListParser.parseArguments(pm, token.next(), this.theClass::setSuperConstructorArguments);
this.mode = EXTENDS_PARAMETERS_END;
return;
}
this.mode = IMPLEMENTS;
pm.reparse();
}
}
use of dyvilx.tools.compiler.parser.type.TypeParser in project Dyvil by Dyvil.
the class PatternParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
final int type = token.type();
switch(this.mode) {
case PATTERN:
switch(type) {
case DyvilKeywords.TRUE:
this.pattern = new BooleanPattern(token.raw(), true);
this.mode = END;
return;
case DyvilKeywords.FALSE:
this.pattern = new BooleanPattern(token.raw(), false);
this.mode = END;
return;
case DyvilSymbols.UNDERSCORE:
this.pattern = new WildcardPattern(token.raw());
this.mode = END;
return;
case DyvilKeywords.NULL:
this.pattern = new NullPattern(token.raw());
this.mode = END;
return;
case Tokens.STRING:
this.pattern = new StringPattern(token.raw(), token.stringValue());
this.mode = END;
return;
case Tokens.SINGLE_QUOTED_STRING:
this.pattern = new CharPattern(token.raw(), token.stringValue());
this.mode = END;
return;
case Tokens.VERBATIM_CHAR:
this.pattern = new CharPattern(token.raw(), token.stringValue(), true);
this.mode = END;
return;
case Tokens.INT:
this.pattern = new IntPattern(token.raw(), token.intValue());
this.mode = END;
return;
case Tokens.LONG:
this.pattern = new LongPattern(token.raw(), token.longValue());
this.mode = END;
return;
case Tokens.FLOAT:
this.pattern = new FloatPattern(token.raw(), token.floatValue());
this.mode = END;
return;
case Tokens.DOUBLE:
this.pattern = new DoublePattern(token.raw(), token.doubleValue());
this.mode = END;
return;
case DyvilKeywords.VAR:
case DyvilKeywords.LET:
final BindingPattern pattern = new BindingPattern();
pm.pushParser(new DataMemberParser<>(pattern), true);
this.pattern = pattern;
this.mode = END;
return;
case BaseSymbols.OPEN_PARENTHESIS:
final dyvilx.tools.compiler.ast.pattern.object.TuplePattern tuplePattern = new dyvilx.tools.compiler.ast.pattern.object.TuplePattern(token);
this.pattern = tuplePattern;
this.mode = TUPLE_END;
pm.pushParser(new PatternListParser(tuplePattern));
return;
case BaseSymbols.DOT:
this.mode = ENUM_IDENTIFIER;
return;
}
if (Tokens.isIdentifier(type)) {
if (token.nameValue() == Names.minus) {
this.mode = NEGATIVE_NUMBER;
return;
}
this.mode = TYPE_END;
pm.pushParser(new TypeParser(this).withFlags(TypeParser.NAMED_ONLY), true);
return;
}
if (BaseSymbols.isTerminator(type)) {
pm.popParser(true);
}
pm.report(Markers.syntaxError(token, "pattern.invalid", token.toString()));
return;
case NEGATIVE_NUMBER:
switch(type) {
case Tokens.INT:
this.pattern = new IntPattern(token.prev().to(token), -token.intValue());
this.mode = END;
return;
case Tokens.LONG:
this.pattern = new LongPattern(token.prev().to(token), -token.intValue());
this.mode = END;
return;
case Tokens.FLOAT:
this.pattern = new FloatPattern(token.prev().to(token), -token.intValue());
this.mode = END;
return;
case Tokens.DOUBLE:
this.pattern = new DoublePattern(token.prev().to(token), -token.intValue());
this.mode = END;
return;
default:
pm.report(token, "pattern.number.negative");
this.mode = END;
pm.reparse();
return;
}
case ENUM_IDENTIFIER:
if (Tokens.isIdentifier(type)) {
this.pattern = new dyvilx.tools.compiler.ast.pattern.object.EnumPattern(token.raw(), token.nameValue());
this.mode = END;
return;
}
pm.report(token, "pattern.enum.identifier");
return;
case TYPE_END:
if (type == BaseSymbols.OPEN_PARENTHESIS) {
// TYPE ( ...
// => Unapply pattern
final dyvilx.tools.compiler.ast.pattern.object.UnapplyPattern unapplyPattern = new UnapplyPattern(token, this.type);
pm.pushParser(new PatternListParser(unapplyPattern));
this.pattern = unapplyPattern;
this.mode = CASE_CLASS_END;
return;
}
// TYPE
// => Object Pattern
this.pattern = new dyvilx.tools.compiler.ast.pattern.object.ObjectPattern(this.type.getPosition(), this.type);
this.mode = END;
pm.reparse();
return;
case TUPLE_END:
this.mode = END;
this.pattern.expandPosition(token);
if (type != BaseSymbols.CLOSE_PARENTHESIS) {
pm.report(token, "pattern.tuple.close_paren");
}
return;
case CASE_CLASS_END:
this.mode = END;
this.pattern.expandPosition(token);
if (type != BaseSymbols.CLOSE_PARENTHESIS) {
pm.report(token, "pattern.case_class.close_paren");
}
return;
case END:
if (type == DyvilKeywords.AS) {
final TypeCheckPattern typeCheck = new TypeCheckPattern(token.raw(), this.pattern);
this.pattern = typeCheck;
pm.pushParser(new TypeParser(typeCheck));
return;
}
if (Tokens.isIdentifier(type)) {
final Name name = token.nameValue();
if (name == Names.bar) {
if (this.checkPrecedence(OPERATOR_OR)) {
this.endPattern(pm);
return;
}
final OrPattern orPattern = new OrPattern(this.pattern, token.raw(), null);
this.pattern = orPattern;
pm.pushParser(new PatternParser(orPattern::setRight, OPERATOR_OR));
return;
}
if (name == Names.amp) {
if (this.checkPrecedence(OPERATOR_AND)) {
this.endPattern(pm);
return;
}
final AndPattern andPattern = new AndPattern(this.pattern, token.raw(), null);
this.pattern = andPattern;
pm.pushParser(new PatternParser(andPattern::setRight, OPERATOR_AND));
return;
}
}
this.endPattern(pm);
}
}
use of dyvilx.tools.compiler.parser.type.TypeParser in project Dyvil by Dyvil.
the class ExpressionParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
final int type = token.type();
switch(type) {
case Tokens.EOF:
case BaseSymbols.SEMICOLON:
case BaseSymbols.COMMA:
case Tokens.STRING_PART:
case Tokens.STRING_END:
this.end(pm, true);
return;
}
switch(this.mode) {
case END:
this.end(pm, true);
return;
case VALUE:
if ((type & Tokens.IDENTIFIER) != 0) {
// IDENTIFIER
this.parseInfixAccess(pm, token, token.nameValue());
return;
}
if (this.parseValue(pm, token, type)) {
// STATEMENT
return;
}
// Fallthrough
case ACCESS:
switch(type) {
case BaseSymbols.DOT:
this.mode = DOT_ACCESS;
return;
case DyvilSymbols.ARROW_RIGHT:
case DyvilSymbols.DOUBLE_ARROW_RIGHT:
if (!this.hasFlag(IGNORE_LAMBDA)) {
break;
}
// Fallthrough
case DyvilKeywords.ELSE:
case DyvilKeywords.CATCH:
case DyvilKeywords.FINALLY:
case DyvilKeywords.WHILE:
this.end(pm, true);
return;
case DyvilKeywords.AS:
{
// EXPRESSION as
final IToken next = token.next();
final boolean optional;
if (next.type() == Tokens.SYMBOL_IDENTIFIER && next.nameValue() == Names.qmark && token.isNeighboring(next)) {
// EXPRESSION as?
optional = true;
pm.skip();
} else {
optional = false;
}
final CastOperator castOperator = new CastOperator(token.raw(), this.value, optional);
pm.pushParser(new TypeParser(castOperator).withFlags(TypeParser.IGNORE_OPERATOR));
this.value = castOperator;
return;
}
case DyvilKeywords.IS:
{
// EXPRESSION is
final InstanceOfOperator instanceOfOperator = new InstanceOfOperator(token.raw(), this.value);
pm.pushParser(new TypeParser(instanceOfOperator).withFlags(TypeParser.IGNORE_OPERATOR));
this.value = instanceOfOperator;
return;
}
case DyvilKeywords.MATCH:
// EXPRESSION match
// Parse a match expression
// e.g. int1 match { ... }, this match { ... }
MatchExpr me = new MatchExpr(token.raw(), this.value);
pm.pushParser(new MatchExpressionParser(me));
this.value = me;
return;
case BaseSymbols.OPEN_SQUARE_BRACKET:
// EXPRESSION [
// Parse a subscript access
// e.g. this[1], array[0]
final SubscriptAccess subscriptAccess = new SubscriptAccess(token, this.value);
ArgumentListParser.parseArguments(pm, token.next(), subscriptAccess);
this.value = subscriptAccess;
this.mode = SUBSCRIPT_END;
return;
case BaseSymbols.OPEN_PARENTHESIS:
// EXPRESSION (
// Parse an apply call
// e.g. 1("a"), this("stuff"), "myString"(2)
final ApplyAccess applyAccess = new ApplyAccess(this.value.getPosition(), this.value);
ArgumentListParser.parseArguments(pm, token.next(), applyAccess);
this.value = applyAccess;
this.mode = PARAMETERS_END;
return;
case BaseSymbols.COLON:
if (this.hasFlag(IGNORE_COLON)) {
this.end(pm, true);
return;
}
this.parseInfixAccess(pm, token, Names.colon, true);
return;
case BaseSymbols.EQUALS:
this.parseInfixAccess(pm, token, Names.eq, true);
return;
}
if (isExpressionEnd(type)) {
// ... ]
// Close bracket, end expression
this.end(pm, true);
return;
}
if (isSymbolic(type)) {
// EXPRESSION IDENTIFIER
// EXPRESSION SYMBOL
this.parseInfixAccess(pm, token);
return;
}
if (this.value != null) {
// EXPRESSION EXPRESSION -> EXPRESSION ( EXPRESSION )
// Juxtaposition
this.parseApply(pm, token);
return;
}
pm.report(Markers.syntaxError(token, "expression.invalid", token.toString()));
return;
case DOT_ACCESS:
if (type == BaseSymbols.OPEN_CURLY_BRACKET) {
// EXPRESSION . {
final BraceAccessExpr braceAccessExpr = new BraceAccessExpr(token.raw(), this.value);
pm.pushParser(new StatementListParser(braceAccessExpr::setStatement), true);
this.value = braceAccessExpr;
this.mode = ACCESS;
return;
}
if (Tokens.isIdentifier(type)) {
if (this.value == null) {
// .IDENTIFIER
this.value = new EnumValue(token.raw(), token.nameValue());
this.mode = ACCESS;
return;
}
// EXPRESSION . IDENTIFIER
this.parseInfixAccess(pm, token, token.nameValue());
return;
}
pm.report(Markers.syntaxError(token, "expression.access.dot.invalid"));
if (BaseSymbols.isTerminator(type)) {
pm.popParser(true);
return;
}
this.mode = ACCESS;
pm.reparse();
return;
case PARAMETERS_END:
// ... ( ... )
// ^
this.mode = ACCESS;
this.value.expandPosition(token);
if (type != BaseSymbols.CLOSE_PARENTHESIS) {
pm.reparse();
pm.report(token, "method.call.close_paren");
}
return;
case SUBSCRIPT_END:
// ... [ ... ]
// ^
this.mode = ACCESS;
this.value.expandPosition(token);
if (type != BaseSymbols.CLOSE_SQUARE_BRACKET) {
pm.reparse();
pm.report(token, "method.subscript.close_bracket");
}
return;
case TYPE_ARGUMENTS_END:
if (!TypeParser.isGenericEnd(token, type)) {
pm.reparse();
pm.report(token, "method.call.generic.close_angle");
}
pm.splitJump(token, 1);
final IToken next = token.next();
if (next.type() == BaseSymbols.OPEN_PARENTHESIS) {
pm.skip();
ArgumentListParser.parseArguments(pm, next.next(), (ICall) this.value);
this.mode = PARAMETERS_END;
return;
}
this.mode = ACCESS;
return;
}
throw new Error("unreachable");
}
use of dyvilx.tools.compiler.parser.type.TypeParser in project Dyvil by Dyvil.
the class DataMemberParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
final int type = token.type();
switch(this.mode) {
case DECLARATOR:
switch(type) {
case DyvilSymbols.AT:
this.parseAnnotation(pm, token);
return;
case DyvilKeywords.LET:
this.attributes.addFlag(Modifiers.FINAL);
// Fallthrough
case DyvilKeywords.VAR:
this.mode = NAME;
return;
}
if (this.parseModifier(pm, token)) {
return;
}
// Fallthrough
case NAME:
if (!Tokens.isIdentifier(type)) {
pm.report(token, "variable.identifier");
return;
}
this.dataMember = this.consumer.createDataMember(token.raw(), token.nameValue(), Types.UNKNOWN, this.attributes);
this.mode = TYPE;
return;
case TYPE:
if (type == BaseSymbols.COLON) {
// ... IDENTIFIER : TYPE ...
pm.pushParser(new TypeParser(this.dataMember));
this.mode = VALUE;
return;
}
// Fallthrough
case VALUE:
if (type == BaseSymbols.EQUALS && (this.flags & PARSE_VALUE) != 0) {
pm.pushParser(new ExpressionParser(this.dataMember));
this.mode = END;
return;
}
// Fallthrough
case END:
this.consumer.addDataMember(this.dataMember);
pm.popParser(type != Tokens.EOF);
}
}
use of dyvilx.tools.compiler.parser.type.TypeParser in project Dyvil by Dyvil.
the class FieldParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
final int type = token.type();
switch(this.mode) {
case DECLARATOR:
switch(type) {
case DyvilSymbols.AT:
this.parseAnnotation(pm, token);
return;
case DyvilKeywords.CONST:
this.attributes.addFlag(Modifiers.CONST);
this.mode = NAME;
return;
case DyvilKeywords.LET:
this.attributes.addFlag(Modifiers.FINAL);
// Fallthrough
case DyvilKeywords.VAR:
this.mode = NAME;
return;
}
if (this.parseModifier(pm, token)) {
return;
}
// Fallthrough
case NAME:
if (!Tokens.isIdentifier(type)) {
pm.report(token, "field.identifier");
return;
}
this.position = token.raw();
this.name = token.nameValue();
this.mode = TYPE;
return;
case TYPE:
if (type == BaseSymbols.COLON) {
// ... IDENTIFIER : TYPE ...
pm.pushParser(new TypeParser(this));
this.mode = VALUE;
return;
}
// Fallthrough
case VALUE:
if ((this.flags & NO_VALUES) == 0 && type == BaseSymbols.EQUALS) {
// definitely a field
final T field = this.initField();
if ((this.flags & NO_PROPERTIES) != 0) {
this.mode = END;
pm.pushParser(new ExpressionParser(field));
} else {
this.mode = PROPERTY;
pm.pushParser(new ExpressionParser(field).withFlags(ExpressionParser.IGNORE_CLOSURE));
}
return;
}
// Fallthrough
case PROPERTY:
if ((this.flags & NO_PROPERTIES) == 0 && type == BaseSymbols.OPEN_CURLY_BRACKET) {
// either a standalone property or a field property
pm.pushParser(new PropertyBodyParser(this.initProperty()), true);
this.mode = END;
return;
}
// Fallthrough
case END:
if (this.property != null) {
this.consumer.addProperty(this.property);
} else {
// for fields without values or properties, the dataMember field has not beed initialized yet
this.consumer.addDataMember(this.initField());
}
pm.popParser(type != Tokens.EOF);
}
}
Aggregations