2017-11-25 9 views
0

私は、F#とFsLexYaccライブラリを使って、インタプリタとコンパイラの基礎を勉強しようとしていますが、私はLexerとParserファイルを書く原則を理解するのに苦労しています... this example、 iterpreterのためのいくつかの簡単なSQLクエリを使用しています。私が探しているのは、this grammarをF#を使ってLexerとParserに変換する方法です。 ASTファイル、Lexerファイル、Parserファイルが含まれていれば、それらのファイルが含まれます。FsLexYacc。レキシングとFを使った解析#

これはこれは、レクサー

{ 
module SqlLexer 
open System 
open SqlParser 
open Microsoft.FSharp.Text.Lexing 

let keywords = [ 

    "div", DIV; 
    "or", OR; 
    "and", AND; 
    "not", NOT; 
    "if", IF; 
    "then", THEN; 
    "else", ELSE; 
    "of", OF; 
    "while", WHILE; 
    "do", DO; 
    "array", ARRAY; 
    "procedure", PROCEDURE; 
    "program", PROGRAM; 
    "begin", BEGIN; 
    "end", END; 
    "var", VAR 

] |> Map.ofList 

let ops = [ 

    "+", ADD; 
    "-", SUBTRACT; 
    "*", MULTIPLY; 
    "=", EQUAL; 
    "<>", NOTEQUAL; 
    "<", LESS; 
    "<=", LESSEQUAL; 
    ">", GREATER; 
    ">=", GREATEREQUAL; 
    ":=", ASSIGN; 
    ".", POINT; 
    ",", COMMA; 
    ";", SEMICOLON; 
    ":", COLON; 
    "..", RANGE; 

] |> Map.ofList 
} 

let char    = ['a'-'z' 'A'-'Z'] 
let digit    = ['0'-'9'] 
let int     = '-'?digit+ 
let float    = '-'?digit+ '.' digit+ 
let identifier   = char(char|digit)* 
let whitespece   = [' ' '\t'] 
let newline    = "\n\r" | '\n' | '\r' 
let operator   = "+" | "-" | "*" | "=" | "<>" | "<" | "<=" | ">" | ">=" | ":=" | "." | "," | ";" | ":" | ".." 

rule tokenize = parse 
| whitespace  { tokenize lexbuf } 
| newline   { lexbuf.EndPos <- lexbuf.EndPos.NextLine; tokenise lexbuf; } 
| int    { INT(Int32.Parse(LexBuffer<_>.LexemeString lexbuf)) } 
| float    { FLOAT(Double.Parse(LexBuffer<_>.LexemeString lexbuf) } 
| operator   { ops.[LexBuffer<_>.LexemeString lexbuf] } 
| identifier  { match keywords.TryFind(LexBuffer<_>.LexemeString lexbuf) with 
         | Some(token) -> token 
         | None -> ID(LexBuffer<_>.LexemeString lexbuf)} 
| eof    { EOF } 

であり、これは私のパーサであるAST

module Ast 


type TypeIdentifier = 
    |Boolean of bool 
    |Integer of int 
    |Float of float 
    |String of string 

and BinaryOperators = 
    |Add 
    |Subtract 
    |Multiply 
    |Equal 
    |NotEqual 
    |Less 
    |Greater 
    |LessEqual 
    |GreaterEqual 
    |Semicolon 
    |Colon 
    |Range 
    |Assign 

です:

%{ 
open Sql 
%} 

%token <string> ID 
%token <int> INT 
%token <float> FLOAT 
%token <bool> BOOL 

%token DIV 
%token AND OR NOT 
%token IF THEN ELSE 
%token WHILE DO 
%token ARRAY OF 
%token PROGRAM 
%token PRODEDURE 
%token BEGIN END 
%token VAR 

%token ADD SUBTRACT MULTIPLY 
%token EQUAL NOTEQUAL 
%token LESS LESSEQUAL 
%token GREATER GREATEREQUAL 
%token ASSIGN 
%token POINT COMMA RANGE 
%token SEMICOLON COLON 

%start start 

start: 
    PROGRAM ID ; 
    block . 
    EOF { 
     identifier = {$2} 
     block = {$4} 
    } 

block: 
    |variableDeclarationPart procedureDeclaretionPart statementPart {$1, $2, $3} 

variableDeclarationPart: 
    | {} 
    |VAR variableDeclaration ; {variableDeclaration;} {} 

私は、書かれたコードとの答えを考え見ているわけではありませんいくつかの似たような例やFsLexYaccライブラリを使ってプログラミング言語を解釈するチュートリアルなどパスカル

答えて

1

私はずっと前にこれを苦労してきました。私がやっているのは、FsLexYaccライブラリがlexとyaccに基づいているからです。Cの構文を使用する代わりに、F#に変換して使用する以外は、素人のlexとyacc(またはflex & bison)それは私のテストプロジェクトです。 https://github.com/fsprojects/FsLexYacc/blob/master/docs/content/jsonParserExample.mdの概念を理解した後、私の独自の実装方法をいくつかの難解な言語にしました。

これが役に立ちます。

PS:F#コンパイラはオープンソースで、FsLexYaccを使用しているので、そのようなものも読み込めます。

関連する問題