commit 8e4be0b7e14725166b27ba82408c2b355280612d Author: Timerix22 Date: Tue Dec 19 02:20:25 2023 +0600 ported code from c# diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4432991 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +bin/ +obj/ +out/ +*.log diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..dd72655 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.h": "c" + } +} \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..008c2f2 --- /dev/null +++ b/build.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -eo pipefail +rm -rf out bin +mkdir out bin +fut -l c -o out/FusionCalculator.c src/*.fu +gcc -Wall -O2 out/FusionCalculator.c -o bin/FusionCalculator.exe $(pkg-config --cflags glib-2.0) $(pkg-config --libs glib-2.0) diff --git a/src/Calculator.fu b/src/Calculator.fu new file mode 100644 index 0000000..1ab022b --- /dev/null +++ b/src/Calculator.fu @@ -0,0 +1,20 @@ +public static class Calculator +{ + public static void Main(string[] args){ + string() joined = ""; + foreach(string arg in args){ + joined += arg; + } + double rezult = Calculate(joined); + Console.WriteLine(rezult); + } + + public static double Calculate(string exprStr) + { + Lexer() lexer = { ExprStr = exprStr}; + Token[]# tokens = lexer.Lex(); + Parser() parser = { Tokens = tokens }; + IExpression# expr = parser.Parse(); + return expr.Calculate(); + } +} diff --git a/src/Expressions.fu b/src/Expressions.fu new file mode 100644 index 0000000..90c8811 --- /dev/null +++ b/src/Expressions.fu @@ -0,0 +1,29 @@ +public abstract class IExpression +{ + public abstract double Calculate(); +} + +public class NumericExpression : IExpression +{ + double N; + public override double Calculate() => N; +} + +public abstract class OperatorExpression : IExpression +{ + IExpression a; + IExpression b; + + public abstract double OperatorImplementation(double a, double b); + + public double Calculate() => OperatorImplementation(a.Calculate(), b.Calculate()); +} + +public abstract class FunctionCallExpression : IExpression +{ + IExpression x; + + public abstract double FunctionImplementation(double x); + + public double Calculate() => FunctionImplementation(x.Calculate()); +} diff --git a/src/Lexer.fu b/src/Lexer.fu new file mode 100644 index 0000000..bb8637a --- /dev/null +++ b/src/Lexer.fu @@ -0,0 +1,122 @@ +//namespace SharpCalculator.Parsing; + +public enum TokenType +{ + BracketOpen, + BracketClose, + OperatorPow, + OperatorMul, + OperatorMod, + OperatorDiv, + OperatorAdd, + OperatorSub, + Literal, + Number +} + +public class Token +{ + string Str; + TokenType Type; + + public static Token() Create(string str, TokenType type){ + Token() tok = { + Str = str, + Type = type + }; + return tok; + } + + public string GetStr() => Str; + public TokenType GetType() => Type; +} + +public class Lexer +{ + string ExprStr; + + protected List() tokens; + protected TokenType tokType = TokenType.Number; + protected int tokBegin = 0; + protected int i = 0; + + protected Token() TokBracketOpen; + protected Token() TokBracketClose; + protected Token() TokPow; + protected Token() TokMul; + protected Token() TokMod; + protected Token() TokDiv; + protected Token() TokAdd; + protected Token() TokSub; + + public Lexer(){ + TokBracketOpen = Token.Create("(", TokenType.BracketOpen); + TokBracketClose = Token.Create(")", TokenType.BracketClose); + TokPow = Token.Create("^", TokenType.OperatorPow); + TokMul = Token.Create("*", TokenType.OperatorMul); + TokMod = Token.Create("%", TokenType.OperatorMod); + TokDiv = Token.Create("/", TokenType.OperatorDiv); + TokAdd = Token.Create("+", TokenType.OperatorAdd); + TokSub = Token.Create("-", TokenType.OperatorSub); + } + + public Token[]# Lex!() + { + while (i < ExprStr.Length) + { + switch (ExprStr[i]) + { + // end token, add new predifined token and move next + case '(': AddStaticToken(TokBracketOpen); break; + case ')': AddStaticToken(TokBracketClose); break; + case '^': AddStaticToken(TokPow); break; + case '*': AddStaticToken(TokMul); break; + case '%': AddStaticToken(TokMod); break; + case '/': AddStaticToken(TokDiv); break; + case '+': AddStaticToken(TokAdd); break; + case '-': AddStaticToken(TokSub); break; + // try end token and skip current char + case ' ': case '\t': case '\n': case '\r': + TryEndToken(); + i++; + break; + // move next + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + i++; + break; + // set type from Numeric to Literal + default: + tokType = TokenType.Literal; + i++; + break; + } + } + + // end last token + TryEndToken(); + Token[]# tokensArray = new Token[tokens.Count]; + tokens.CopyTo(0, tokensArray, 0, tokens.Count); + return tokensArray; + } + + void TryEndToken!() + { + if (tokBegin != i) + { + string() tokStr = ExprStr.Substring(tokBegin, i - tokBegin); + Token() tok = { Str=tokStr, Type = tokType }; + tokens.Add(tok); + tokType = TokenType.Number; + tokBegin = i; + } + } + + void AddStaticToken!(Token tok) + { + TryEndToken(); + tokens.Add(tok); + tokType = TokenType.Number; + tokBegin = ++i; + } +} diff --git a/src/Parser.fu b/src/Parser.fu new file mode 100644 index 0000000..9339ea4 --- /dev/null +++ b/src/Parser.fu @@ -0,0 +1,9 @@ +public class Parser +{ + Token[]# Tokens; + + public IExpression# Parse(){ + NumericExpression# n = new NumericExpression { N = 1 }; + return n; + } +}