5 people like it.
Like the snippet!
Simple AST parser
Parsers a minimal expression tree allowing for functions of the form "func(arg1,arg2,...)->{body}"
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
|
module LanguageCombinator
open FParsec
open System
exception Error of string
type Op =
| Plus
| Minus
type Ast =
| Statement of Ast
| Expression of Ex
| Scope of Ast list
| Function of Argument list option * Ast list option
and Ex =
| Single of Ast
| Full of Ex * Op * Ex
| Float of float
| Int of int
| Literal of string
| Variable of string
and Argument =
| Element of Ex
(* Literals *)
let quote = pstring "\""
let literal = quote >>. manyCharsTill anyChar quote |>> Literal
let floatNum = pfloat |>> Float
let intNum = pint32 |>> Int
(* Variables *)
let variable = many1Chars (satisfy isAsciiLetter) |>> Variable
(* Operators *)
let plus = pstring "+" >>% Plus
let minus = pstring "-" >>% Minus
let op = spaces >>. choice[plus;minus]
(* expressions *)
// create a forward reference
// the expr is what we'll use in our parser combinators
// the exprImpl we'll populate iwth all the recursive options later
let expr, exprImpl = createParserForwardedToRef()
let expression1 = spaces >>? choice[floatNum;intNum;literal;variable]
let between a b p = pstring a >>. p .>> pstring b
let bracketExpression = expr |> between "(" ")"
let lhExpression = choice[expression1; bracketExpression]
let expressionOpration = lhExpression >>=? fun operandL ->
op >>=? fun operator ->
choice[expr;bracketExpression] >>=? fun operandR ->
preturn (operandL, operator, operandR) |>> Full
do exprImpl := spaces >>. choice[attempt expressionOpration <|> attempt bracketExpression <|> expression1 ]
(* Statements *)
let funcInners, funcInnersImpl = createParserForwardedToRef()
let statement = expr .>> pstring ";"
let statements = many1 (spaces >>? statement|>> Expression)
(* Functions *)
let arguments = sepEndBy1 (expr |>> Element) (pstring ",") |> between "(" ")"
let func = parse {
do! skipStringCI "func"
do! spaces
let! arguments = opt arguments
do! skipStringCI "->"
do! spaces
do! skipStringCI "{"
do! spaces
let! text = opt funcInners
do! spaces
do! skipStringCI "}"
do! spaces
return Function(arguments, text)
}
do funcInnersImpl := many1 (spaces >>? choice [func; statement |>> Expression])
(* Program lines *)
let programLines = spaces >>. choice[
func;
statements |>> Scope
]
let program = many programLines
let test input = match run (program .>> eof) input with
| Success(r,_,_) -> r
| Failure(r,_,_) ->
Console.WriteLine r
raise (Error(r))
|
module LanguageCombinator
namespace FParsec
namespace System
Multiple items
exception Error of string
Full name: LanguageCombinator.Error
--------------------
module Error
from FParsec
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
type Op =
| Plus
| Minus
Full name: LanguageCombinator.Op
union case Op.Plus: Op
union case Op.Minus: Op
type Ast =
| Statement of Ast
| Expression of Ex
| Scope of Ast list
| Function of Argument list option * Ast list option
Full name: LanguageCombinator.Ast
union case Ast.Statement: Ast -> Ast
union case Ast.Expression: Ex -> Ast
type Ex =
| Single of Ast
| Full of Ex * Op * Ex
| Float of float
| Int of int
| Literal of string
| Variable of string
Full name: LanguageCombinator.Ex
union case Ast.Scope: Ast list -> Ast
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
union case Ast.Function: Argument list option * Ast list option -> Ast
type Argument = | Element of Ex
Full name: LanguageCombinator.Argument
type 'T option = Option<'T>
Full name: Microsoft.FSharp.Core.option<_>
Multiple items
union case Ex.Single: Ast -> Ex
--------------------
type Single =
struct
member CompareTo : value:obj -> int + 1 overload
member Equals : obj:obj -> bool + 1 overload
member GetHashCode : unit -> int
member GetTypeCode : unit -> TypeCode
member ToString : unit -> string + 3 overloads
static val MinValue : float32
static val Epsilon : float32
static val MaxValue : float32
static val PositiveInfinity : float32
static val NegativeInfinity : float32
...
end
Full name: System.Single
union case Ex.Full: Ex * Op * Ex -> Ex
union case Ex.Float: float -> Ex
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
union case Ex.Int: int -> Ex
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
Multiple items
union case Ex.Literal: string -> Ex
--------------------
type LiteralAttribute =
inherit Attribute
new : unit -> LiteralAttribute
Full name: Microsoft.FSharp.Core.LiteralAttribute
--------------------
new : unit -> LiteralAttribute
union case Ex.Variable: string -> Ex
union case Argument.Element: Ex -> Argument
val quote : Parser<string,unit>
Full name: LanguageCombinator.quote
val pstring : string -> Parser<string,'u>
Full name: FParsec.CharParsers.pstring
val literal : Parser<Ex,unit>
Full name: LanguageCombinator.literal
val manyCharsTill : Parser<char,'u> -> Parser<'b,'u> -> Parser<string,'u>
Full name: FParsec.CharParsers.manyCharsTill
val anyChar : Parser<char,'u>
Full name: FParsec.CharParsers.anyChar
val floatNum : Parser<Ex,unit>
Full name: LanguageCombinator.floatNum
val pfloat : Parser<float,'u>
Full name: FParsec.CharParsers.pfloat
val intNum : Parser<Ex,unit>
Full name: LanguageCombinator.intNum
val pint32 : Parser<int32,'u>
Full name: FParsec.CharParsers.pint32
val variable : Parser<Ex,unit>
Full name: LanguageCombinator.variable
val many1Chars : Parser<char,'u> -> Parser<string,'u>
Full name: FParsec.CharParsers.many1Chars
val satisfy : (char -> bool) -> Parser<char,'u>
Full name: FParsec.CharParsers.satisfy
val isAsciiLetter : char -> bool
Full name: FParsec.CharParsers.isAsciiLetter
val plus : Parser<Op,unit>
Full name: LanguageCombinator.plus
val minus : Parser<Op,unit>
Full name: LanguageCombinator.minus
val op : Parser<Op,unit>
Full name: LanguageCombinator.op
val spaces : Parser<unit,'u>
Full name: FParsec.CharParsers.spaces
val choice : seq<Parser<'a,'u>> -> Parser<'a,'u>
Full name: FParsec.Primitives.choice
val expr : Parser<Ex,unit>
Full name: LanguageCombinator.expr
val exprImpl : Parser<Ex,unit> ref
Full name: LanguageCombinator.exprImpl
val createParserForwardedToRef : unit -> Parser<'a,'u> * Parser<'a,'u> ref
Full name: FParsec.Primitives.createParserForwardedToRef
val expression1 : Parser<Ex,unit>
Full name: LanguageCombinator.expression1
val between : a:string -> b:string -> p:Parser<'a,'b> -> Parser<'a,'b>
Full name: LanguageCombinator.between
val a : string
val b : string
val p : Parser<'a,'b>
val bracketExpression : Parser<Ex,unit>
Full name: LanguageCombinator.bracketExpression
val lhExpression : (CharStream<unit> -> Reply<Ex>)
Full name: LanguageCombinator.lhExpression
val expressionOpration : Parser<Ex,unit>
Full name: LanguageCombinator.expressionOpration
val operandL : Ex
val operator : Op
val operandR : Ex
val preturn : 'a -> Parser<'a,'u>
Full name: FParsec.Primitives.preturn
val attempt : Parser<'a,'u> -> Parser<'a,'u>
Full name: FParsec.Primitives.attempt
val funcInners : Parser<Ast list,unit>
Full name: LanguageCombinator.funcInners
val funcInnersImpl : Parser<Ast list,unit> ref
Full name: LanguageCombinator.funcInnersImpl
val statement : Parser<Ex,unit>
Full name: LanguageCombinator.statement
val statements : Parser<Ast list,unit>
Full name: LanguageCombinator.statements
val many1 : Parser<'a,'u> -> Parser<'a list,'u>
Full name: FParsec.Primitives.many1
val arguments : Parser<Argument list,unit>
Full name: LanguageCombinator.arguments
val sepEndBy1 : Parser<'a,'u> -> Parser<'b,'u> -> Parser<'a list,'u>
Full name: FParsec.Primitives.sepEndBy1
val func : Parser<Ast,unit>
Full name: LanguageCombinator.func
val parse : ParserCombinator
Full name: FParsec.Primitives.parse
val skipStringCI : string -> Parser<unit,'u>
Full name: FParsec.CharParsers.skipStringCI
val arguments : Argument list option
val opt : Parser<'a,'u> -> Parser<'a option,'u>
Full name: FParsec.Primitives.opt
val text : Ast list option
val programLines : Parser<Ast,unit>
Full name: LanguageCombinator.programLines
val program : Parser<Ast list,unit>
Full name: LanguageCombinator.program
val many : Parser<'a,'u> -> Parser<'a list,'u>
Full name: FParsec.Primitives.many
val test : input:string -> Ast list
Full name: LanguageCombinator.test
val input : string
val run : Parser<'Result,unit> -> string -> ParserResult<'Result,unit>
Full name: FParsec.CharParsers.run
val eof : Parser<unit,'u>
Full name: FParsec.CharParsers.eof
union case ParserResult.Success: 'Result * 'UserState * Position -> ParserResult<'Result,'UserState>
val r : Ast list
union case ParserResult.Failure: string * ParserError * 'UserState -> ParserResult<'Result,'UserState>
val r : string
type Console =
static member BackgroundColor : ConsoleColor with get, set
static member Beep : unit -> unit + 1 overload
static member BufferHeight : int with get, set
static member BufferWidth : int with get, set
static member CapsLock : bool
static member Clear : unit -> unit
static member CursorLeft : int with get, set
static member CursorSize : int with get, set
static member CursorTop : int with get, set
static member CursorVisible : bool with get, set
...
Full name: System.Console
Console.WriteLine() : unit
(+0 other overloads)
Console.WriteLine(value: string) : unit
(+0 other overloads)
Console.WriteLine(value: obj) : unit
(+0 other overloads)
Console.WriteLine(value: uint64) : unit
(+0 other overloads)
Console.WriteLine(value: int64) : unit
(+0 other overloads)
Console.WriteLine(value: uint32) : unit
(+0 other overloads)
Console.WriteLine(value: int) : unit
(+0 other overloads)
Console.WriteLine(value: float32) : unit
(+0 other overloads)
Console.WriteLine(value: float) : unit
(+0 other overloads)
Console.WriteLine(value: decimal) : unit
(+0 other overloads)
val raise : exn:Exception -> 'T
Full name: Microsoft.FSharp.Core.Operators.raise
More information