summaryrefslogtreecommitdiffstats
path: root/src/Compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/Compiler')
-rw-r--r--src/Compiler/Parser.java60
-rw-r--r--src/Compiler/Statement.java25
-rw-r--r--src/Compiler/TokenScanner.java15
-rw-r--r--src/Compiler/TokenType.java6
-rw-r--r--src/Compiler/Translator.java61
5 files changed, 131 insertions, 36 deletions
diff --git a/src/Compiler/Parser.java b/src/Compiler/Parser.java
index 68851bf..7eb22df 100644
--- a/src/Compiler/Parser.java
+++ b/src/Compiler/Parser.java
@@ -28,19 +28,37 @@ public class Parser {
//Clean up and reduce code mess
private Statement declaration(){
if (matchAndAdvance(TokenType.INT)){
- if (matchOrError(TokenType.DEFINE, ":: Required for variable definition")){
- if (matchOrError(TokenType.IDENTIFIER,"Expected variable name.")){
- Token varName = getPreviousToken();
- return new Statement.VariableDeclaration(varName,"int");
- }
- }
+ matchOrError(TokenType.DEFINE, ":: Required for variable definition");
+ matchOrError(TokenType.IDENTIFIER,"Expected variable name.");
+ Token varName = getPreviousToken();
+ return new Statement.VariableDeclaration(varName,"int");
} else if (matchAndAdvance(TokenType.REAL)){
- if (matchOrError(TokenType.DEFINE, ":: Required for variable definition")){
- if (matchOrError(TokenType.IDENTIFIER,"Expected variable name.")){
- Token varName = getPreviousToken();
- return new Statement.VariableDeclaration(varName,"real");
- }
+ matchOrError(TokenType.DEFINE, ":: Required for variable definition");
+ matchOrError(TokenType.IDENTIFIER,"Expected variable name.");
+ Token varName = getPreviousToken();
+ return new Statement.VariableDeclaration(varName,"real");
+
+ //Could be improved significatly when verifiying length is a positive integer
+ } else if (matchAndAdvance(TokenType.STRING)){
+ matchOrError(TokenType.LEFT_PAREN, "Length of string must be defined");
+ matchOrError(TokenType.LEN, "Length of string must be defined");
+ matchOrError(TokenType.EQUALS, "Length of string must be defined");
+ Expression length = expression();
+ if(!(length instanceof Expression.Literal)){
+ throw error("String length must be a number");
+ }
+ if(!((Expression.Literal)length).type.equals("int")){
+ throw error("String length must be a integer");
}
+ if((int)((Expression.Literal)length).value.value<1){
+ throw error("String length must be greater then 0");
+ }
+ matchOrError(TokenType.RIGHT_PAREN, "Length of string must be defined");
+
+ matchOrError(TokenType.DEFINE, ":: Required for variable definition");
+ matchOrError(TokenType.IDENTIFIER,"Expected variable name.");
+ Token varName = getPreviousToken();
+ return new Statement.StringDeclaration(varName,length);
}
return statement();
@@ -48,8 +66,7 @@ public class Parser {
private Statement statement(){
if (matchAndAdvance(TokenType.PRINT)){
- Expression expression = expression();
- return new Statement.PrintStatement(expression);
+ return printStatement();
}else if (matchAndAdvance(TokenType.IF)){
Statement statement = ifStatement();
return statement;
@@ -57,6 +74,20 @@ public class Parser {
return expressionStatement();
}
+ private Statement printStatement(){
+ matchOrError(TokenType.STAR, "Syntax, print *, item1, item2...");
+ List<Expression> exprList = new ArrayList<>();
+ while(!matchAndAdvance(TokenType.ENDPRINT)){
+ if(checkEOF()){
+ throw error("Missing close parentheses");
+ }
+ matchOrError(TokenType.COMMA, "Print items must be seperated by ,");
+ Expression expr = expression();
+ exprList.add(expr);
+ }
+ return new Statement.PrintStatement(exprList);
+ }
+
//Could be cleaned up to handle else statements better
private Statement ifStatement(){
Expression condition = expression();
@@ -155,6 +186,9 @@ public class Parser {
return new Expression.Literal(getPreviousToken(),"double");
}
}
+ if (matchAndAdvance(TokenType.STRING)){
+ return new Expression.Literal(getPreviousToken(), "string");
+ }
if (matchAndAdvance(TokenType.IDENTIFIER)) {
diff --git a/src/Compiler/Statement.java b/src/Compiler/Statement.java
index a74009d..b8916aa 100644
--- a/src/Compiler/Statement.java
+++ b/src/Compiler/Statement.java
@@ -48,16 +48,33 @@ abstract class Statement {
@Override
public String getStatmentType() {
- return "vardec";
+ return "varDec";
+ }
+
+ }
+
+ static class StringDeclaration extends Statement{
+ StringDeclaration(Token name,Expression length){
+ this.name=name;
+ this.length=length;
+ }
+
+
+ final Token name;
+ final Expression length;
+
+ @Override
+ public String getStatmentType() {
+ return "stringDec";
}
}
static class PrintStatement extends Statement{
- PrintStatement(Expression expr){
- this.expr=expr;
+ PrintStatement(List<Expression> exprList){
+ this.exprList=exprList;
}
- final Expression expr;
+ final List<Expression> exprList;
@Override
public String getStatmentType() {
diff --git a/src/Compiler/TokenScanner.java b/src/Compiler/TokenScanner.java
index 27501fa..f2fcab3 100644
--- a/src/Compiler/TokenScanner.java
+++ b/src/Compiler/TokenScanner.java
@@ -40,6 +40,7 @@ public class TokenScanner {
case '*': createTokenNull(TokenType.STAR); break;
case '/': createTokenNull(TokenType.SLASH); break;
case ';': createTokenNull(TokenType.SEMI_COLON); break;
+ case ',': createTokenNull(TokenType.COMMA); break;
//Some tokens are multiple characters long (==, <=) etc
//so need to check next char as well
@@ -75,6 +76,17 @@ public class TokenScanner {
createTokenNull(TokenType.GREATER);
break;
}
+ case '"':
+ while(lookAhead()!='"' && !checkEOF()){
+ currentLoc++;
+ }
+ if(checkEOF()){
+ Language.displayError("Strings must end with \"");
+ break;
+ }
+ currentLoc++;
+ createToken(TokenType.STRING, sourceCode.substring(tokenStart, currentLoc+1));
+ break;
default:
//Check for numer
@@ -180,8 +192,11 @@ public class TokenScanner {
static {
keywords = new HashMap<>();
keywords.put("int", TokenType.INT);
+ keywords.put("len", TokenType.LEN);
keywords.put("real", TokenType.REAL);
+ keywords.put("character", TokenType.STRING);
keywords.put("print", TokenType.PRINT);
+ keywords.put("endprint", TokenType.ENDPRINT);
keywords.put("if", TokenType.IF);
keywords.put("then", TokenType.THEN);
keywords.put("endif", TokenType.ENDIF);
diff --git a/src/Compiler/TokenType.java b/src/Compiler/TokenType.java
index f56bf38..f597d2f 100644
--- a/src/Compiler/TokenType.java
+++ b/src/Compiler/TokenType.java
@@ -4,15 +4,15 @@ package Compiler;
public enum TokenType {
EQUALS, LEFT_PAREN, RIGHT_PAREN,
PLUS, MINUS, SLASH, STAR, SEMI_COLON,
- COLON,
+ COLON,COMMA,
EQUALITY, GREATER, LESS,
GREATER_EQUAL, LESS_EQUAL,
DEFINE,
- NUMBER,IDENTIFIER,
+ NUMBER,IDENTIFIER,STRING,
- INT,REAL,PRINT,IF,THEN,ENDIF,ELSE,
+ INT,REAL,PRINT,ENDPRINT,IF,THEN,ENDIF,ELSE,LEN,
EOF
}
diff --git a/src/Compiler/Translator.java b/src/Compiler/Translator.java
index 716bafd..d343b80 100644
--- a/src/Compiler/Translator.java
+++ b/src/Compiler/Translator.java
@@ -15,6 +15,7 @@ public class Translator{
public List<String> compileToC(List<Statement> statements){
CCode.add("#include <stdio.h>");
+ CCode.add("#include <string.h>");
CCode.add("int main(){");
try{
for (Statement statement: statements){
@@ -37,9 +38,12 @@ public class Translator{
case "exprStmt":
evalExpressionStatement((ExpressionStatement)statement);
break;
- case "vardec":
+ case "varDec":
evalVariableDeclaration((VariableDeclaration)statement);
break;
+ case "stringDec":
+ evalStringDeclaration((StringDeclaration)statement);
+ break;
case "print":
evalPrintStatement((PrintStatement)statement);
break;
@@ -52,31 +56,49 @@ public class Translator{
evaluateExpression(stmt.expr);
}
+ private void evalStringDeclaration(StringDeclaration stringdec){
+ environment.defineVariable(stringdec.name.text, "string");
+ int size = (int)((Expression.Literal)stringdec.length).value.value;
+ size++;
+ CCode.add("char "+stringdec.name.text+"["+size+"];");
+ }
+
private void evalVariableDeclaration(VariableDeclaration vardec){
environment.defineVariable(vardec.name.text, vardec.type);
if(vardec.type.equals("int")){
CCode.add("int "+vardec.name.text+";");
} else if(vardec.type.equals("real")){
CCode.add("float "+vardec.name.text+";");
- }
+ }
}
private void evalPrintStatement(PrintStatement print){
- if(print.expr instanceof Expression.Literal){
- if (((Expression.Literal)print.expr).type.equals("int")){
- CCode.add("printf(\"%d\","+evaluateExpression(print.expr)+");");
- } else if (((Expression.Literal)print.expr).type.equals("double")){
- CCode.add("printf(\"%f\","+evaluateExpression(print.expr)+");");
+ String types="";
+ String values="";
+ boolean first=true;
+ for(Expression expr:print.exprList){
+ if(!first){
+ values+=",";
+ }else{
+ first=false;
+ }
+ String exprType="";
+ if(expr instanceof Expression.Literal){
+ exprType=((Expression.Literal)expr).type;
+ }
+ else if (expr instanceof Expression.Variable){
+ exprType=(String)environment.getVariable((((Expression.Variable)expr).name).text);
}
- } else if (print.expr instanceof Expression.Variable){
- Object varValue = environment.getVariable((((Expression.Variable)print.expr).name).text);
- if (varValue.equals("int")){
- CCode.add("printf(\"%d\","+evaluateExpression(print.expr)+");");
- } else if (varValue.equals("real")){
- CCode.add("printf(\"%f\","+evaluateExpression(print.expr)+");");
- }
+ if (exprType.equals("int")){
+ types+="%d";
+ } else if (exprType.equals("double")){
+ types+="%f";
+ } else if (exprType.equals("string")){
+ types+="%s";
+ }
+ values+=evaluateExpression(expr);
}
-
+ CCode.add("printf(\""+types+"\","+values+");");
}
private void evalIfStatement(IfStatement ifstatement){
@@ -145,7 +167,14 @@ public class Translator{
}
private void evaluateAssignmentExpression(AssignmentExpression expr){
- CCode.add(expr.name.text+"="+evaluateExpression(expr.value)+";");
+ if(expr.value instanceof Expression.Literal){
+ if(((Expression.Literal)expr.value).type.equals("string")){
+ CCode.add("strcpy("+expr.name.text+","+evaluateExpression(expr.value)+");");
+ }
+ }
+ else{
+ CCode.add(expr.name.text+"="+evaluateExpression(expr.value)+";");
+ }
}
private String evaluateVariableExpression(Variable expr){