From ee369b50b14ffe662e05355459f57c076680cd58 Mon Sep 17 00:00:00 2001 From: Maƫl Gassmann Date: Thu, 10 Jun 2021 16:02:29 +0200 Subject: [+] Basic stucture of the java calculator --- calculator-java/.gitignore | 3 + calculator-java/pom.xml | 16 ++++ calculator-java/src/main/java/CalculatorLexer.java | 105 +++++++++++++++++++++ calculator-java/src/main/java/Token.java | 21 +++++ .../src/main/java/exceptions/LexerException.java | 5 + 5 files changed, 150 insertions(+) create mode 100644 calculator-java/.gitignore create mode 100644 calculator-java/pom.xml create mode 100644 calculator-java/src/main/java/CalculatorLexer.java create mode 100644 calculator-java/src/main/java/Token.java create mode 100644 calculator-java/src/main/java/exceptions/LexerException.java (limited to 'calculator-java') diff --git a/calculator-java/.gitignore b/calculator-java/.gitignore new file mode 100644 index 0000000..6c0dce9 --- /dev/null +++ b/calculator-java/.gitignore @@ -0,0 +1,3 @@ +calculator-java.iml +target/ +.idea/ \ No newline at end of file diff --git a/calculator-java/pom.xml b/calculator-java/pom.xml new file mode 100644 index 0000000..1edc3ba --- /dev/null +++ b/calculator-java/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + ch.bfh + calculator-java + 1.0-SNAPSHOT + + + 11 + 11 + + + \ No newline at end of file diff --git a/calculator-java/src/main/java/CalculatorLexer.java b/calculator-java/src/main/java/CalculatorLexer.java new file mode 100644 index 0000000..61b906c --- /dev/null +++ b/calculator-java/src/main/java/CalculatorLexer.java @@ -0,0 +1,105 @@ +// Lexer for classical arithmetic expressions with identifiers and assignements. +// Scans a source string char by char. + +import exceptions.LexerException; + +public class CalculatorLexer { + + private String src; // source string for lexical analysis + private int idx; // current index in source + private int len; // length of source + + public CalculatorLexer() { } + + public void initLexer(String source) { + this.src = source; + idx = 0; + len = src.length(); + } + + // Consumes letters only and builds an identifier + private String identifier() { + StringBuffer s = new StringBuffer(); + + do { + s.append(src.charAt(idx)); + idx++; + } while (idx < len && Character.isLetter(src.charAt(idx))); + return s.toString(); + } + + // Consumes digits and convert integer part and decimal part + // Convert characters using the formula + // "3456.253" = [(((3+0)*10+4)*10+5)*10+6]+[0.1*2+0.01*5+0.001*3] + private double number() throws LexerException { + double v = 0; // accumulates the result + double factor = 0.1; // factor for decimal part + + do { // integer part + v = v * 10 + Character.digit(src.charAt(idx),30); + idx++; + } while (idx < len && Character.isDigit(src.charAt(idx))); + if (idx < len && src.charAt(idx) == '.') { // decimal point + idx++; + if (idx < len && Character.isDigit(src.charAt(idx))) { // decimal part + while (idx < len && Character.isDigit(src.charAt(idx))) { + v = v + (factor * Character.digit(src.charAt(idx),30)); + factor = factor * 0.1; + idx++; + } + } + else throw new LexerException("Illegal number: decimal part missing"); + } + return v; + } + + // Skips blanks, tabs, newlines + private void skip() { + char c; + while (idx < len) { + c = src.charAt(idx); + if (c==' ' || c=='\t' || c=='\n') idx++; + else break; + } + } + + // returns next token + public Token nextToken() throws LexerException { + Token tok = new Token(); + + skip(); + if (idx>=len) { + tok.str="EOL"; + tok.type=Token.EOL; + } + else + // is it a positive number? + if (Character.isDigit(src.charAt(idx))) { + tok.value = number(); + tok.type = Token.NUM; + tok.str = Double.toString(tok.value); + } + else + if (Character.isLetter(src.charAt(idx))) { + tok.value = 0; + tok.type = Token.ID; + tok.str = identifier(); + if (tok.str.compareTo("let")==0) tok.type = Token.LET; + if (tok.str.compareTo("exit")==0) tok.type = Token.END; + } + else { + switch (src.charAt(idx)) { + case '+': tok.type = Token.ADD; tok.str = "+"; break; + case '-': tok.type = Token.SUB; tok.str = "-"; break; + case '*': tok.type = Token.MUL; tok.str = "*"; break; + case '/': tok.type = Token.DIV; tok.str = "/"; break; + case '(': tok.type = Token.PAL; tok.str = "("; break; + case ')': tok.type = Token.PAR; tok.str = ")"; break; + case '=': tok.type = Token.EQU; tok.str = "="; break; + default : throw new LexerException("Illegal Token: '" + src.charAt(idx) + "'"); + } + idx++; + } + return tok; + } +} \ No newline at end of file diff --git a/calculator-java/src/main/java/Token.java b/calculator-java/src/main/java/Token.java new file mode 100644 index 0000000..4fe8b23 --- /dev/null +++ b/calculator-java/src/main/java/Token.java @@ -0,0 +1,21 @@ +// Various Tokens for arithmetic expressions based on integers +// with identifiers and assignments + +public class Token { + public int type; // token type + public double value; // numerical value for NUM + public String str; // token string + + public static final int EOL=0; // End Of Line + public static final int PAL=1; // Left Parenthesis + public static final int PAR=2; // Right Parenthesis + public static final int ADD=3; // operators + public static final int SUB=4; + public static final int MUL=5; + public static final int DIV=6; + public static final int NUM=7; // number + public static final int EQU=8; // equal + public static final int LET=9; // let + public static final int ID=10; // identifier + public static final int END=11; // exit +} diff --git a/calculator-java/src/main/java/exceptions/LexerException.java b/calculator-java/src/main/java/exceptions/LexerException.java new file mode 100644 index 0000000..b7b1f24 --- /dev/null +++ b/calculator-java/src/main/java/exceptions/LexerException.java @@ -0,0 +1,5 @@ +package exceptions; + +public class LexerException extends RuntimeException { + public LexerException(String s) { super(s); } +} \ No newline at end of file -- cgit v1.2.3