diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2015-12-08 21:38:50 +0200 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2015-12-08 21:38:50 +0200 |
| commit | d6d401c83f186e72a105821e60a856ca4d5c998c (patch) | |
| tree | 55e19022be522c3616ef2ffef2244c2a8fbbf6b8 | |
| download | lbasi-d6d401c83f186e72a105821e60a856ca4d5c998c.tar.gz lbasi-d6d401c83f186e72a105821e60a856ca4d5c998c.zip | |
part 1 + tests
| -rw-r--r-- | .gitattributes | 3 | ||||
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | calc1.pas | 219 | ||||
| -rw-r--r-- | tests/calc1.txt | 26 |
4 files changed, 255 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..de3c41b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto +*.pas text +*.txt text diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..888575f --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +FPC_FLAGS = -Mobjfpc -FUobj -g + +calc1: calc1.pas | obj + fpc ${FPC_FLAGS} $< + +obj: + mkdir obj diff --git a/calc1.pas b/calc1.pas new file mode 100644 index 0000000..0757421 --- /dev/null +++ b/calc1.pas @@ -0,0 +1,219 @@ +program calc1; + +{$H+} + +uses + typinfo, sysutils, character; + +type + TokenType = (TT_Integer, TT_Plus, TT_Minus, TT_Eof); + + Token = class + TokenType: TokenType; + constructor Create(Type_: TokenType); + function ToStr: String; virtual; + end; + + TokenInteger = class(Token) + Val: Integer; + constructor Create(Value_: Integer); + function ToStr: String; override; + end; + + TokenPlus = class(Token) + constructor Create; + end; + + TokenMinus = class(Token) + constructor Create; + end; + + TokenEof = class(Token) + constructor Create; + end; + + Interpreter = class + Text: AnsiString; + CurPos: Integer; + Current: Token; + + constructor Create(Text_: AnsiString); + + procedure Error; + function GetNextToken: Token; + procedure Eat(T: TokenType); + function Expr: Integer; + end; + +constructor Token.Create(Type_: TokenType); +begin + inherited Create; + TokenType := Type_; +end; + +function Token.ToStr: String; +begin + Result := GetEnumName(TypeInfo(TokenType), Ord(Self.TokenType)); +end; + +constructor TokenInteger.Create(Value_: Integer); +begin + inherited Create(TT_Integer); + Val := Value_; +end; + +function TokenInteger.ToStr: String; +begin + Result := inherited; + Result := Result + '(' + IntToStr(Val) + ')'; +end; + +constructor TokenPlus.Create; +begin + inherited Create(TT_Plus); +end; + +constructor TokenMinus.Create; +begin + inherited Create(TT_Minus); +end; + + +constructor TokenEof.Create; +begin + inherited Create(TT_Eof); +end; + +constructor Interpreter.Create(Text_: String); +begin + inherited Create; + Text := Text_; + CurPos := 1; + Current := Default(Token); +end; + +procedure Interpreter.Error; +begin + Raise Exception.Create('error!'); +end; + +function Interpreter.GetNextToken: Token; +var + Text_: String; + CurrentChar: Char; + Start: Integer; + + procedure SkipWhitespace; + begin + while (CurPos <= Length(Text)) and IsWhiteSpace(Text[CurPos]) do + Inc(CurPos); + end; + + function AtEnd: Boolean; + begin + Result := CurPos > Length(Text); + end; +begin + SkipWhitespace; + + if AtEnd then + begin + Result := TokenEof.Create; + Exit; + end; + + Start := CurPos; + + while (CurPos <= Length(Text)) and IsDigit(Text[CurPos]) do + Inc(CurPos); + + if CurPos - Start > 0 then + begin + Result := TokenInteger.Create(StrToInt(Copy(Text, Start, + CurPos-Start))); + Exit; + end; + + CurrentChar := Text[CurPos]; + + if CurrentChar = '+' then + begin + Result := TokenPlus.Create; + Inc(CurPos); + Exit; + end + else if CurrentChar = '-' then + begin + Result := TokenMinus.Create; + Inc(CurPos); + Exit; + end; + + Error; +end; + +procedure Interpreter.Eat(T: TokenType); +begin + if Current.TokenType = T then + begin + Current := GetNextToken; + end + else + Error; +end; + +function Interpreter.Expr: Integer; +var + Left, Op, Right: Token; +begin + Current := GetNextToken; + + Left := Current; + Eat(TT_Integer); + + Op := Current; + Eat(TT_Minus); + + Right := Current; + Eat(TT_Integer); + + Result := TokenInteger(Left).Val - TokenInteger(Right).Val; +end; + +var + Interp: Interpreter; + Line: String; + I: Integer; + +procedure InterpString(S: String); +begin + Interp := Interpreter.Create(S); + WriteLn(Interp.Expr); + FreeAndNil(Interp); +end; + +procedure InputLoop; +begin + while True do + begin + Write('calc> '); + if Eof(Input) then break; + ReadLn(Line); + if Length(Line) = 0 then continue; + InterpString(Line); + end; +end; + +begin + if ParamCount > 0 then + begin + Line := ''; + for I := 1 to ParamCount do + begin + Line := Line + ParamStr(I); + end; + InterpString(Line); + end + else + InputLoop; +end. diff --git a/tests/calc1.txt b/tests/calc1.txt new file mode 100644 index 0000000..a343306 --- /dev/null +++ b/tests/calc1.txt @@ -0,0 +1,26 @@ +*** Settings *** +Library Process + +*** Keywords *** +Run Calculator + [Arguments] ${expr} + ${result} = Run Process ${CURDIR}/../calc1 ${expr} + [Return] ${result} + +Calculate + [Arguments] ${expr} + ${rc} = Run Calculator ${expr} + Should Be Equal As Integers ${rc.rc} 0 + ${result} = Get Variable Value ${rc.stdout} + [Return] ${result} + +The result of ${calculation} should be ${expected} + ${result} = Calculate ${calculation} + Should Be Equal As Integers ${expected} ${result} + +*** Test Cases *** +Simple calculations + [Template] The result of ${calculations} should be ${expected} + 1-1 0 + 100-3 97 + 50${SPACE*5}- 5 45 |
