2017-11-25 25 views
0

나는 F # 및 FsLexYacc 라이브러리를 사용하여 통역사 및 컴파일러의 기초를 배우려고 노력하고 있지만 Lexer 및 Parser 파일을 작성하는 원칙을 이해하는 데 어려움을 겪고 있습니다 ... this example, 하지만 iterpreter에 대한 몇 가지 간단한 SQL 쿼리를 사용합니다. 내가 뭘 찾고 있는데, F #을 사용하여 작동하는 Lexer와 Parser로 this grammar을 변환하는 방법입니다. 도움이 필요하면 AST, Lexer 및 Parser 파일을 포함시킵니다. 내가 것,FsLexYacc. Lexing and Farsing with F #

%{ 
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;} {} 

내가 작성한 코드로 답을 찾고 있지 않다 :

는 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 

{ 
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 } 

렉서

입니다 그리고 이것은 내 파서이다 유사한 예제로 된 설명이나 FsLexYacc 라이브러리를 사용하여 프로그래밍 언어를 해석하는 튜토리얼 파스칼

답변

1

저는 꽤 오래 전에 고심하고있었습니다. 내가 끝내는 것은 FsLexYacc 라이브러리가 lex와 yacc에 기반을두고 있기 때문에 맨손의 lex와 yacc (또는 flex & 들소)에 대한 빠른 자습서를 가지고있어 C 구문을 사용하는 대신 F #으로 변환하고 내 테스트 프로젝트에서. 개념을 익히고 나면 https://github.com/fsprojects/FsLexYacc/blob/master/docs/content/jsonParserExample.md을 비롯하여 난해한 언어를 구현했습니다.

희망이 도움이 될 것입니다.

PS : F # 컴파일러는 오픈 소스이며 FsLexYacc를 사용하므로 해당 내용도 읽을 수 있습니다.