5 people like it.

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

Link:http://fssnip.net/iJ
Posted:7 years ago
Author:devshorts
Tags: fparsec , parsing , ast , expressions