Calc Demo
Demo下载地址:
https://github.com/TOHKAaaaa/Calc-Demo
找到calcfs文件夹,解压
可以看到demo所需的fsi以及fsy文件
如果成功下载,可以直接跳到最后,若无法下载或下载很慢,下面会给出具体的代码段
Demo代码
scanner.fsl
{
open Parser
open FSharp.Text.Lexing
let lexeme = LexBuffer<_>.LexemeString
}
rule token =
parse [' ' '\t' '\r' '\n'] { token lexbuf }
| '+' { PLUS }
| '-' { MINUS }
| '*' { TIMES }
| '/' { DIVIDE }
| ['0'-'9']+ { LITERAL(int (lexeme lexbuf)) }
| eof { EOF }
parser.fsl
%{
open Ast
%}
%token PLUS MINUS TIMES DIVIDE EOF
%token <int> LITERAL
%left PLUS MINUS
%left TIMES DIVIDE
%start expr
%type <Ast.expr> expr
%%
expr:
expr PLUS expr { Binop($1, Add, $3) }
| expr MINUS expr { Binop($1, Sub, $3) }
| expr TIMES expr { Binop($1, Mul, $3) }
| expr DIVIDE expr { Binop($1, Div, $3) }
| LITERAL { Lit($1) }
Ast.fs
module Ast
type operator = Add | Sub | Mul | Div
type expr =
| Binop of expr * operator * expr
| Lit of int
Calc.fs
open System
open FSharp.Text.Lexing
open Ast
let rec eval = function
Lit(x) -> x
| Binop(e1, op, e2) ->
let v1 = eval e1
let v2 = eval e2 in
match op with
| Add -> v1 + v2
| Sub -> v1 - v2
| Mul -> v1 * v2
| Div -> v1 / v2
[<EntryPoint>]
let main argv =
let rec loop () =
printf "user>"
let input = Console.ReadLine()
let lexbuf = LexBuffer<char>.FromString input
try
let expr = Parser.expr Scanner.token lexbuf in
let result = eval expr in
//printfn "%A" expr;
printfn "%s" (string result)
with e ->
printfn "Errors"
loop ()
loop ()
calcfs.fsproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!--
fslex fsyacc 工具依赖
dotnet run 会自动调用工具fslex fsyacc,并生成 Scanner.fs Parser.fs
-->
<FsLex Include="Scanner.fsl">
<OtherFlags>--module Scanner --unicode</OtherFlags>
</FsLex>
<FsYacc Include="Parser.fsy">
<OtherFlags>--module Parser</OtherFlags>
</FsYacc>
<!--
编译文件列表,注意有前后次序,被依赖的文件放前面,主文件 Calc.fs放在最后
-->
<Compile Include="Ast.fs" />
<Compile Include="Parser.fs" />
<Compile Include="Scanner.fs" />
<Compile Include="Calc.fs" />
<!--
fslexyacc外部包依赖
在项目目录,运行 `dotnet add package fslexyacc` 添加
-->
<PackageReference Include="fslexyacc" Version="10.2.0" />
</ItemGroup>
</Project>
Demo的编译与运行
首先先到达calcfs的目录下,使用dotnet run即生成可执行程序calcfs.exe
运行完成后,在bin目录底下找到calcfs.exe也可以运行。
运行结果如下: