A few basic expressions, no tests

This commit is contained in:
Andrey Breslav
2010-12-27 19:12:21 +03:00
parent 3d23350629
commit ef9a963ebd
14 changed files with 333 additions and 103 deletions
+12
View File
@@ -2,6 +2,18 @@ if
: "if" "(" expression ")" expression ("else" expression)?
;
try
: "try" block catchBlock* finallyBlock?
;
catchBlock
: "catch" valueParameters block
;
finallyBlock
: "finally" block
;
loop
: for
: while
+4 -3
View File
@@ -11,7 +11,8 @@ expression
: expressionWithPrecedences
: match
: if
: "typeof" // TODO: another keyword
: try
: "typeof" "(" expression ")"
: "new" constructorInvocation // TODO: Do we need "new"?, see factory methods
: objectLiteral
: declaration
@@ -165,11 +166,11 @@ listLiteral
;
mapLiteral
: "[" mapEntryLiteral{","} "]"
: "[" mapLiteralEntry{","} "]"
: "[" ":" "]"
;
mapEntryLiteral
mapLiteralEntry
: expression ":" expression
;
+3
View File
@@ -61,6 +61,7 @@ do
match
out
ref
try
Soft:
wraps -- in a class header
@@ -79,4 +80,6 @@ private
public
internal
protected
catch
finally
*/
@@ -55,6 +55,20 @@ public interface JetNodeTypes {
JetNodeType TYPE_CONSTRAINT_LIST = new JetNodeType("TYPE_CONSTRAINT_LIST");
JetNodeType TYPE_CONSTRAINT = new JetNodeType("TYPE_CONSTRAINT");
JetNodeType ENUM_ENTRY = new JetNodeType("ENUM_ENTRY");
JetNodeType NULL = new JetNodeType("NULL");
JetNodeType BOOLEAN_CONSTANT = new JetNodeType("BOOLEAN_CONSTANT");
JetNodeType FLOAT_CONSTANT = new JetNodeType("FLOAT_CONSTANT");
JetNodeType CHARACTER_CONSTANT = new JetNodeType("CHARACTER_CONSTANT");
JetNodeType STRING_CONSTANT = new JetNodeType("STRING_CONSTANT");
JetNodeType INTEGER_CONSTANT = new JetNodeType("INTEGER_CONSTANT");
JetNodeType SUPERTYE_QUALIFIER = new JetNodeType("SUPERTYE_QUALIFIER");
JetNodeType LONG_CONSTANT = new JetNodeType("LONG_CONSTANT");
JetNodeType TUPLE = new JetNodeType("TUPLE");
JetNodeType MAP_LITERAL_ENTRY = new JetNodeType("MAP_LITERAL_ENTRY");
JetNodeType MAP_LITERAL = new JetNodeType("MAP_LITERAL");
JetNodeType RANGE_LITERAL = new JetNodeType("RANGE_LITERAL");
JetNodeType LIST_LITERAL = new JetNodeType("LIST_LITERAL");
JetNodeType TYPEOF = new JetNodeType("TYPEOF");
IElementType NAMESPACE_NAME = new JetNodeType("NAMESPACE_NAME");
}
@@ -73,6 +73,7 @@ public class JetHighlighter extends SyntaxHighlighterBase {
fillMap(keys1, JetTokens.KEYWORDS, JET_KEYWORD);
keys1.put(JetTokens.INTEGER_LITERAL, JET_NUMBER);
keys1.put(JetTokens.LONG_LITERAL, JET_NUMBER);
keys1.put(JetTokens.FLOAT_LITERAL, JET_NUMBER);
keys1.put(JetTokens.STRING_LITERAL, JET_STRING);
@@ -144,4 +144,64 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
error.error(mesage);
}
/*
* Looks for a the last top-level (not inside any {} [] () <>) '.' occurring before a
* top-level occurrence of a token from the <code>stopSet</code>
*
* Returns -1 if no occurrence is found
*/
protected int findLastBefore(TokenSet lookFor, TokenSet stopAt, boolean dontStopRightAfterOccurrence) {
PsiBuilder.Marker currentPosition = mark();
int lastOccurrence = -1;
int openAngleBrackets = 0;
int openBraces = 0;
int openParentheses = 0;
int openBrackets = 0;
IElementType previousToken = null;
while (!eof()) {
if (atSet(stopAt)) {
if (openAngleBrackets == 0
&& openBrackets == 0
&& openBraces == 0
&& openParentheses == 0
&& (!dontStopRightAfterOccurrence
|| !lookFor.contains(previousToken))) break;
}
if (at(LPAR)) {
openParentheses++;
}
else if (at(LT)) {
openAngleBrackets++;
}
else if (at(LBRACE)) {
openBraces++;
}
else if (at(LBRACKET)) {
openBrackets++;
}
else if (at(RPAR)) {
openParentheses--;
}
else if (at(GT)) {
openAngleBrackets--;
}
else if (at(RBRACE)) {
openBraces--;
}
else if (at(RBRACKET)) {
openBrackets--;
}
else if (atSet(lookFor)
&& openAngleBrackets == 0
&& openBrackets == 0
&& openBraces == 0
&& openParentheses == 0) {
lastOccurrence = myBuilder.getCurrentOffset();
}
previousToken = tt();
advance(); // skip token
}
currentPosition.rollbackTo();
return lastOccurrence;
}
}
@@ -29,11 +29,11 @@ public class JetExpressionParsing extends AbstractJetParsing {
* : range
* : "null"
* : "this" ("<" type ">")?
* : memberAccessExpression
* : expressionWithPrecedences
* : match
* : if
* : "typeof"
* : try
* : "typeof" "(" expression ")"
* : "new" constructorInvocation
* : objectLiteral
* : declaration
@@ -44,41 +44,23 @@ public class JetExpressionParsing extends AbstractJetParsing {
*/
public void parseExpression() {
if (at(LPAR)) {
// TODO (expression) or tuple
}
else if (at(INTEGER_LITERAL)) {
// TODO
}
else if (at(CHARACTER_LITERAL)) {
// TODO
}
else if (at(FLOAT_LITERAL)) {
// TODO
}
else if (at(STRING_LITERAL)) {
// TODO
}
else if (at(TRUE_KEYWORD)) {
// TODO
}
else if (at(FALSE_KEYWORD)) {
// TODO
parseParenthesizedExpressionOrTuple();
}
else if (at(LBRACKET)) {
// TODO: map, list or range
}
else if (at(NULL_KEYWORD)) {
// TODO
parseMapListOrRange();
}
else if (at(THIS_KEYWORD)) {
// TODO
parseThisExpression();
}
else if (at(IF_KEYWORD)) {
// TODO
}
else if (at(TYPEOF_KEYWORD)) {
else if (at(TRY_KEYWORD)) {
// TODO
}
else if (at(TYPEOF_KEYWORD)) {
parseTypeOf();
}
else if (at(NEW_KEYWORD)) {
// TODO
}
@@ -106,10 +88,195 @@ public class JetExpressionParsing extends AbstractJetParsing {
else if (at(DO_KEYWORD)) {
// TODO
}
else if (atSet(TokenSet.create(CLASS_KEYWORD, EXTENSION_KEYWORD, FUN_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, TYPE_KEYWORD))) {
else if (atSet(TokenSet.create(
CLASS_KEYWORD,
EXTENSION_KEYWORD,
FUN_KEYWORD,
VAL_KEYWORD,
VAR_KEYWORD,
TYPE_KEYWORD))) {
// TODO
}
advance(); // TODO
else if (at(IDENTIFIER)) {
advance(); // TODO
}
else if (at(INTEGER_LITERAL)) {
parseOneTokenExpression(INTEGER_CONSTANT);
}
else if (at(LONG_LITERAL)) {
parseOneTokenExpression(LONG_CONSTANT);
}
else if (at(CHARACTER_LITERAL)) {
parseOneTokenExpression(CHARACTER_CONSTANT);
}
else if (at(FLOAT_LITERAL)) {
parseOneTokenExpression(FLOAT_CONSTANT);
}
else if (at(STRING_LITERAL) || at(RAW_STRING_LITERAL)) {
parseOneTokenExpression(STRING_CONSTANT);
}
else if (at(TRUE_KEYWORD)) {
parseOneTokenExpression(BOOLEAN_CONSTANT);
}
else if (at(FALSE_KEYWORD)) {
parseOneTokenExpression(BOOLEAN_CONSTANT);
}
else if (at(NULL_KEYWORD)) {
parseOneTokenExpression(NULL);
}
}
/*
* "typeof" "(" expression ")"
*/
private void parseTypeOf() {
assert at(TYPEOF_KEYWORD);
PsiBuilder.Marker typeof = mark();
advance(); // TYPEOF_KEYWORD
expect(LPAR, "Expecting '('");
parseExpression();
expect(RPAR, "Expecting ')'");
typeof.done(TYPEOF);
}
/*
* listLiteral
* : "[" expression{","}? "]"
* ;
*
* mapLiteral
* : "[" mapEntryLiteral{","} "]"
* : "[" ":" "]"
* ;
*
* mapEntryLiteral
* : expression ":" expression
* ;
*
* range
* : "[" expression ".." expression "]"
* ;
*/
private void parseMapListOrRange() {
assert at(LBRACKET);
PsiBuilder.Marker literal = mark();
advance(); // LBRACKET
// If this is an emty map "[:]"
if (at(COLON)) {
advance(); // COLON
expect(RBRACKET, "Expecting ']' to close an empty map literal '[:]'");
literal.done(MAP_LITERAL);
return;
}
PsiBuilder.Marker item = mark();
parseExpression();
// If it is a map "[e:e, e:e]"
if (at(COLON)) {
advance(); // COLON
parseExpression();
item.done(MAP_LITERAL_ENTRY);
while (at(COMMA)) {
advance(); // COMMA
if (at(COMMA)) error("Expecting a map entry");
parseMapLiteralEntry();
}
expect(RBRACKET, "Expecting ']' to close a map literal");
literal.done(MAP_LITERAL);
return;
}
// If it is a range "[a..b]"
if (at(RANGE)) {
item.drop();
advance(); // RANGE
parseExpression();
expect(RBRACKET, "Expecting ']' to close the range");
literal.done(RANGE_LITERAL);
return;
}
// Else: it must be a list literal "[a, b, c]"
item.drop();
while (at(COMMA)) {
advance(); // COMMA
if (at(COMMA)) error("Expecting a list entry");
parseExpression();
}
expect(RBRACKET, "Expecting a ']' to close a list");
literal.done(LIST_LITERAL);
}
/*
* mapLiteralEntry
* : expression ":" expression
* ;
*/
private void parseMapLiteralEntry() {
PsiBuilder.Marker entry = mark();
parseExpression();
expect(COLON, "Expecting ':'");
parseExpression();
entry.done(MAP_LITERAL_ENTRY);
}
/*
* "(" expression ")" // see tupleLiteral
* "(" expression{","} ")"
* TODO: Labels in tuple literals?
*/
private void parseParenthesizedExpressionOrTuple() {
assert at(LPAR);
PsiBuilder.Marker mark = mark();
advance(); // LPAR
while (true) {
if (at(COMMA)) errorAndAdvance("Expecting a tuple entry (expression)");
parseExpression();
if (!at(COMMA)) break;
advance(); // COMMA
}
expect(RPAR, "Expecting ')'");
mark.done(TUPLE);
}
/*
* "this" ("<" type ">")?
*/
private void parseThisExpression() {
assert at(THIS_KEYWORD);
advance(); // THIS_KEYWORD
if (at(LT)) {
// This may be "this < foo" or "this<foo>", thus the backtracking
PsiBuilder.Marker supertype = mark();
advance(); // LT
myJetParsing.parseTypeRef();
if (at(GT)) {
advance(); // GT
supertype.done(SUPERTYE_QUALIFIER);
}
else {
supertype.rollbackTo();
}
}
}
/*
@@ -172,4 +339,11 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
}
}
private void parseOneTokenExpression(JetNodeType type) {
PsiBuilder.Marker mark = mark();
advance();
mark.done(type);
}
}
@@ -828,65 +828,6 @@ public class JetParsing extends AbstractJetParsing {
return FUN;
}
/*
* Looks for a the last top-level (not inside any {} [] () <>) '.' occurring before a
* top-level occurrence of a token from the <code>stopSet</code>
*/
private int findLastBefore(TokenSet lookFor, TokenSet stopAt, boolean dontStopRightAfterOccurrence) {
PsiBuilder.Marker currentPosition = mark();
int lastOccurrence = -1;
int openAngleBrackets = 0;
int openBraces = 0;
int openParentheses = 0;
int openBrackets = 0;
IElementType previousToken = null;
while (!eof()) {
if (atSet(stopAt)) {
if (openAngleBrackets == 0
&& openBrackets == 0
&& openBraces == 0
&& openParentheses == 0
&& (!dontStopRightAfterOccurrence
|| !lookFor.contains(previousToken))) break;
}
if (at(LPAR)) {
openParentheses++;
}
else if (at(LT)) {
openAngleBrackets++;
}
else if (at(LBRACE)) {
openBraces++;
}
else if (at(LBRACKET)) {
openBrackets++;
}
else if (at(RPAR)) {
openParentheses--;
}
else if (at(GT)) {
openAngleBrackets--;
}
else if (at(RBRACE)) {
openBraces--;
}
else if (at(RBRACKET)) {
openBrackets--;
}
else if (atSet(lookFor)
&& openAngleBrackets == 0
&& openBrackets == 0
&& openBraces == 0
&& openParentheses == 0) {
lastOccurrence = myBuilder.getCurrentOffset();
}
previousToken = tt();
advance(); // skip token
}
currentPosition.rollbackTo();
return lastOccurrence ;
}
/*
* functionBody
* : block
@@ -1188,7 +1129,7 @@ public class JetParsing extends AbstractJetParsing {
* : attributes (userType | functionType | tupleType)
* ;
*/
private void parseTypeRef() {
public void parseTypeRef() {
PsiBuilder.Marker type = mark();
parseAttributeList();
@@ -58,6 +58,16 @@ public class PsiBuilderAdapter implements PsiBuilder {
return myDelegate.lookAhead(steps);
}
// @Override
// public IElementType rawLookup(int steps) {
// return myDelegate.rawLookup(steps);
// }
//
// @Override
// public int rawTokenTypeStart(int steps) {
// return myDelegate.rawTokenTypeStart(steps);
// }
@Nullable
@NonNls
public String getTokenText() {
@@ -109,6 +109,7 @@ RAW_STRING_LITERAL = {THREE_QUO} {QUO_STRING_CHAR}* {THREE_QUO}?
<YYINITIAL> "while" { return JetTokens.WHILE_KEYWORD ;}
<YYINITIAL> "do" { return JetTokens.DO_KEYWORD ;}
<YYINITIAL> "match" { return JetTokens.MATCH_KEYWORD ;}
<YYINITIAL> "try" { return JetTokens.TRY_KEYWORD ;}
<YYINITIAL> {IDENTIFIER} { return JetTokens.IDENTIFIER; }
@@ -17,7 +17,8 @@ public interface JetTokens {
IElementType WHITE_SPACE = TokenType.WHITE_SPACE;
JetToken INTEGER_LITERAL = new JetToken("INTEGER_LITERAL");
JetToken FLOAT_LITERAL = new JetToken("FLOAT_LITERAL");
JetToken LONG_LITERAL = new JetToken("LONG_LITERAL");
JetToken FLOAT_LITERAL = new JetToken("FLOAT_CONSTANT");
JetToken CHARACTER_LITERAL = new JetToken("CHARACTER_LITERAL");
JetToken STRING_LITERAL = new JetToken("STRING_LITERAL");
JetToken RAW_STRING_LITERAL = new JetToken("RAW_STRING_LITERAL");
@@ -47,6 +48,7 @@ public interface JetTokens {
JetKeywordToken CONTINUE_KEYWORD = JetKeywordToken.keyword("continue");
JetKeywordToken OBJECT_KEYWORD = JetKeywordToken.keyword("object");
JetKeywordToken IF_KEYWORD = JetKeywordToken.keyword("if");
JetKeywordToken TRY_KEYWORD = JetKeywordToken.keyword("try");
JetKeywordToken ELSE_KEYWORD = JetKeywordToken.keyword("else");
JetKeywordToken WHILE_KEYWORD = JetKeywordToken.keyword("while");
JetKeywordToken DO_KEYWORD = JetKeywordToken.keyword("do");
@@ -116,17 +118,20 @@ public interface JetTokens {
JetKeywordToken PROTECTED_KEYWORD = JetKeywordToken.softKeyword("protected");
JetKeywordToken OUT_KEYWORD = JetKeywordToken.softKeyword("out");
JetKeywordToken REF_KEYWORD = JetKeywordToken.softKeyword("ref");
JetKeywordToken CATCH_KEYWORD = JetKeywordToken.softKeyword("catch");
JetKeywordToken FINALLY_KEYWORD = JetKeywordToken.softKeyword("finally");
TokenSet KEYWORDS = TokenSet.create(NAMESPACE_KEYWORD, AS_KEYWORD, TYPE_KEYWORD, CLASS_KEYWORD,
THIS_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, FUN_KEYWORD, DECOMPOSER_KEYWORD, EXTENSION_KEYWORD, FOR_KEYWORD,
NULL_KEYWORD, TYPEOF_KEYWORD, NEW_KEYWORD, TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD, ISNOT_KEYWORD,
IN_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD, CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD,
ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD, MATCH_KEYWORD, REF_KEYWORD, OUT_KEYWORD
ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD, MATCH_KEYWORD, REF_KEYWORD, OUT_KEYWORD, TRY_KEYWORD
);
TokenSet SOFT_KEYWORDS = TokenSet.create(WRAPS_KEYWORD, IMPORT_KEYWORD, WHERE_KEYWORD, BY_KEYWORD, LAZY_KEYWORD, GET_KEYWORD,
SET_KEYWORD, ABSTRACT_KEYWORD, VIRTUAL_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, ATTRIBUTE_KEYWORD,
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
CATCH_KEYWORD, FINALLY_KEYWORD
);
TokenSet MODIFIER_KEYWORDS = TokenSet.create(LAZY_KEYWORD, ABSTRACT_KEYWORD, VIRTUAL_KEYWORD, ENUM_KEYWORD,
+4 -2
View File
@@ -30,7 +30,8 @@ JetFile: BabySteps.jet
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
PsiElement(INTEGER_LITERAL)('0')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
@@ -46,7 +47,8 @@ JetFile: BabySteps.jet
NAMED_ARGUMENT
PsiElement(IDENTIFIER)('d')
PsiElement(EQ)('=')
PsiElement(INTEGER_LITERAL)('0')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0')
PsiElement(RPAR)(')')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
+4 -2
View File
@@ -30,7 +30,8 @@ JetFile: BabySteps_ERR.jet
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
PsiElement(INTEGER_LITERAL)('0')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
@@ -46,7 +47,8 @@ JetFile: BabySteps_ERR.jet
NAMED_ARGUMENT
PsiElement(IDENTIFIER)('d')
PsiElement(EQ)('=')
PsiElement(INTEGER_LITERAL)('0')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0')
PsiElement(RPAR)(')')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
+8 -4
View File
@@ -41,7 +41,8 @@ JetFile: Enums.jet
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
PsiElement(INTEGER_LITERAL)('0xFF000')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0xFF000')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
ENUM_ENTRY
@@ -59,7 +60,8 @@ JetFile: Enums.jet
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
PsiElement(INTEGER_LITERAL)('0x00FF00')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0x00FF00')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
ENUM_ENTRY
@@ -77,7 +79,8 @@ JetFile: Enums.jet
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
PsiElement(INTEGER_LITERAL)('0x0000FF')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0x0000FF')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -135,7 +138,8 @@ JetFile: Enums.jet
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
PsiElement(INTEGER_LITERAL)('0')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('0')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
ENUM_ENTRY