123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- package me.hammerle.snuviscript.compiler;
- import me.hammerle.snuviscript.exceptions.PreScriptException;
- import me.hammerle.snuviscript.token.Token;
- import me.hammerle.snuviscript.token.TokenType;
- public class Compiler
- {
- private int index = 0;
- private Token[] tokens = null;
-
- public Compiler()
- {
- }
-
- public void checkSyntax(Token[] tokens)
- {
- this.tokens = tokens;
- index = 0;
- checkLine();
- }
-
- private Token consumeToken()
- {
- if(index >= tokens.length)
- {
- return null;
- }
- return tokens[index++];
- }
-
- private Token peekOrNullToken()
- {
- if(index >= tokens.length)
- {
- return null;
- }
- return tokens[index];
- }
-
- private Token peekToken()
- {
- if(index >= tokens.length)
- {
- throw new PreScriptException("missing token at end of file", -1);
- }
- return tokens[index];
- }
-
- private void consumeTokenAndCheck(TokenType... type)
- {
- Token t = consumeToken();
- if(t == null)
- {
- throw new PreScriptException("missing token at end of file " + type, -1);
- }
- for(TokenType ty : type)
- {
- if(ty == t.getType())
- {
- return;
- }
- }
- throw new PreScriptException("unexpected token " + t, t.getLine());
- }
-
- private void checkFunctionArguments()
- {
- TokenType type = peekToken().getType();
- if(type == TokenType.CLOSE_BRACKET)
- {
- consumeToken();
- return;
- }
- consumeTokenAndCheck(TokenType.LITERAL);
- while(true)
- {
- type = peekToken().getType();
- if(type == TokenType.CLOSE_BRACKET)
- {
- consumeToken();
- return;
- }
- consumeTokenAndCheck(TokenType.COMMA);
- consumeTokenAndCheck(TokenType.LITERAL);
- }
- }
-
- private void checkLine()
- {
- while(true)
- {
- Token t = peekOrNullToken();
- if(t == null || t.getType() == TokenType.CLOSE_CURVED_BRACKET)
- {
- break;
- }
- consumeToken();
- switch(t.getType())
- {
- case LITERAL:
- switch(t.getData().toString())
- {
- case "function":
- consumeTokenAndCheck(TokenType.LITERAL);
- consumeTokenAndCheck(TokenType.OPEN_BRACKET);
- checkFunctionArguments();
- consumeTokenAndCheck(TokenType.OPEN_CURVED_BRACKET);
- checkLine();
- consumeTokenAndCheck(TokenType.CLOSE_CURVED_BRACKET);
- break;
- case "for":
- consumeTokenAndCheck(TokenType.OPEN_BRACKET);
- checkArguments(TokenType.CLOSE_BRACKET);
- consumeTokenAndCheck(TokenType.OPEN_CURVED_BRACKET);
- checkLine();
- consumeTokenAndCheck(TokenType.CLOSE_CURVED_BRACKET);
- break;
- case "else":
- consumeTokenAndCheck(TokenType.OPEN_CURVED_BRACKET);
- checkLine();
- consumeTokenAndCheck(TokenType.CLOSE_CURVED_BRACKET);
- break;
- case "elseif":
- case "while":
- case "if":
- consumeTokenAndCheck(TokenType.OPEN_BRACKET);
- checkExpression();
- consumeTokenAndCheck(TokenType.CLOSE_BRACKET);
- consumeTokenAndCheck(TokenType.OPEN_CURVED_BRACKET);
- checkLine();
- consumeTokenAndCheck(TokenType.CLOSE_CURVED_BRACKET);
- break;
- case "try":
- consumeTokenAndCheck(TokenType.OPEN_CURVED_BRACKET);
- checkLine();
- consumeTokenAndCheck(TokenType.CLOSE_CURVED_BRACKET);
- Token token = consumeToken();
- if(token.getType() != TokenType.LITERAL || !token.getData().equals("catch"))
- {
- throw new PreScriptException("try without catch", token.getLine());
- }
- consumeTokenAndCheck(TokenType.OPEN_CURVED_BRACKET);
- checkLine();
- consumeTokenAndCheck(TokenType.CLOSE_CURVED_BRACKET);
- break;
- case "continue":
- case "break":
- consumeTokenAndCheck(TokenType.SEMICOLON);
- break;
- case "return":
- if(peekToken().getType() == TokenType.SEMICOLON)
- {
- consumeToken();
- }
- else
- {
- checkExpression();
- consumeTokenAndCheck(TokenType.SEMICOLON);
- }
- break;
- default:
- checkAfterLiteral(true);
- consumeTokenAndCheck(TokenType.SEMICOLON);
- }
- break;
- case OPEN_CURVED_BRACKET:
- checkLine();
- consumeTokenAndCheck(TokenType.CLOSE_CURVED_BRACKET);
- break;
- /*case DOLLAR:
- checkVariable();
- checkVariableOperation(true);
- consumeTokenAndCheck(TokenType.SEMICOLON);
- break;*/
- case LABEL:
- consumeTokenAndCheck(TokenType.LITERAL, TokenType.NUMBER);
- break;
- case SEMICOLON:
- break;
- case INC:
- case DEC:
- Token token = peekToken();
- //if(token.getType() == TokenType.DOLLAR)
- {
- consumeToken();
- }
- checkVariable();
- consumeTokenAndCheck(TokenType.SEMICOLON);
- break;
- default:
- throw new PreScriptException("unexpected token " + t, t.getLine());
- }
- }
- }
-
- private void checkVariable()
- {
- consumeTokenAndCheck(TokenType.LITERAL);
-
- Token t = peekToken();
- if(t.getType() == TokenType.OPEN_SQUARE_BRACKET)
- {
- consumeToken();
- checkArguments(TokenType.CLOSE_SQUARE_BRACKET);
- }
- }
-
- private void checkAfterLiteral(boolean line)
- {
- Token t = peekToken();
- switch(t.getType())
- {
- case OPEN_BRACKET:
- consumeToken();
- checkArguments(TokenType.CLOSE_BRACKET);
- if(!line)
- {
- checkCalc();
- }
- return;
- case OPEN_SQUARE_BRACKET:
- consumeToken();
- checkArguments(TokenType.CLOSE_SQUARE_BRACKET);
- checkVariableOperation(line);
- return;
- case INC:
- case DEC:
- consumeToken();
- checkCalc();
- return;
- case SET:
- case ADD_SET:
- case SUB_SET:
- case MUL_SET:
- case DIV_SET:
- case MOD_SET:
- case LEFT_SHIFT_SET:
- case RIGHT_SHIFT_SET:
- case BIT_AND_SET:
- case BIT_XOR_SET:
- case BIT_OR_SET:
- consumeToken();
- checkExpression();
- return;
- default:
- if(line)
- {
- throw new PreScriptException("unexpected token " + t, t.getLine());
- }
- }
-
- checkCalc();
- }
-
- private void checkVariableOperation(boolean line)
- {
- Token t = peekToken();
- switch(t.getType())
- {
- case INC:
- case DEC:
- case SET:
- case ADD_SET:
- case SUB_SET:
- case MUL_SET:
- case DIV_SET:
- case MOD_SET:
- case LEFT_SHIFT_SET:
- case RIGHT_SHIFT_SET:
- case BIT_AND_SET:
- case BIT_XOR_SET:
- case BIT_OR_SET:
- consumeToken();
- checkExpression();
- break;
- default:
- if(line)
- {
- throw new PreScriptException("unexpected token " + t, t.getLine());
- }
- else
- {
- checkCalc();
- }
- }
- }
-
- private void checkCalc()
- {
- Token t = peekToken();
- switch(t.getType())
- {
- case MUL:
- case DIV:
- case MOD:
- case ADD:
- case SUB:
- case LEFT_SHIFT:
- case RIGHT_SHIFT:
- case LESS:
- case LESS_EQUAL:
- case GREATER:
- case GREATER_EQUAL:
- case EQUAL:
- case NOT_EQUAL:
- case BIT_AND:
- case BIT_XOR:
- case BIT_OR:
- case AND:
- case OR:
- consumeToken();
- checkExpression();
- break;
- }
- }
-
- private void checkArguments(TokenType end)
- {
- Token t = peekToken();
- if(t.getType() == end)
- {
- consumeToken();
- return;
- }
-
- checkExpression();
-
- while(true)
- {
- t = peekToken();
- if(t.getType() == end)
- {
- consumeToken();
- return;
- }
- consumeTokenAndCheck(TokenType.COMMA);
- checkExpression();
- }
- }
-
- private void checkExpression()
- {
- Token t = consumeToken();
- switch(t.getType())
- {
- case SUB:
- checkExpression();
- break;
- case NUMBER:
- case STRING:
- checkCalc();
- break;
- case LITERAL:
- checkAfterLiteral(false);
- break;
- case OPEN_BRACKET:
- checkExpression();
- consumeTokenAndCheck(TokenType.CLOSE_BRACKET);
- checkCalc();
- break;
- /*case DOLLAR:
- checkVariable();
- checkVariableOperation(false);
- break;*/
- case LABEL:
- consumeTokenAndCheck(TokenType.LITERAL);
- break;
- case INC:
- case DEC:
- Token token = peekToken();
- //if(token.getType() == TokenType.DOLLAR)
- {
- consumeToken();
- }
- checkVariable();
- checkCalc();
- break;
- case INVERT:
- case BIT_INVERT:
- checkExpression();
- break;
- default:
- throw new PreScriptException("unexpected token " + t, t.getLine());
- }
- }
- }
|