├── src ├── version.ml ├── syntax │ ├── grammars │ │ ├── tokens.mlypack │ │ ├── parser.mlypack │ │ ├── parserPre.mlypack │ │ ├── _tags │ │ ├── tokens.mly │ │ ├── parserPre.mly │ │ ├── parserCommon.mly │ │ └── parser.mly │ ├── basic │ │ ├── astPre.ml │ │ ├── pos.ml │ │ ├── ops.ml │ │ └── emitter.mli │ ├── config.ml │ ├── lexing │ │ ├── tokenProvider.mli │ │ ├── sedlex_menhir.ml │ │ ├── workList.ml │ │ ├── token.ml │ │ ├── tokenProvider.ml │ │ └── lexer.ml │ ├── ast.ml │ ├── nullEmitter.ml │ ├── parserDriver.ml │ ├── symbolPrinter.ml │ ├── astEmitter.ml │ ├── jsonEmitter.ml │ └── syntaxErrors.ml ├── globals.ml ├── hxparserjs.ml ├── json.ml ├── jsonConverter.ml ├── hxparser.ml └── context │ └── meta.ml ├── deploy_key.enc ├── .merlin ├── .vscode └── settings.json ├── .gitignore ├── Makefile.messages ├── .travis.yml ├── deploy.sh ├── LICENSE.md ├── _oasis └── readme.md /src/version.ml: -------------------------------------------------------------------------------- 1 | let version_extra = None 2 | -------------------------------------------------------------------------------- /src/syntax/grammars/tokens.mlypack: -------------------------------------------------------------------------------- 1 | Tokens 2 | -------------------------------------------------------------------------------- /src/syntax/grammars/parser.mlypack: -------------------------------------------------------------------------------- 1 | Tokens ParserCommon Parser 2 | -------------------------------------------------------------------------------- /src/syntax/grammars/parserPre.mlypack: -------------------------------------------------------------------------------- 1 | Tokens ParserCommon ParserPre -------------------------------------------------------------------------------- /deploy_key.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vshaxe/hxparser/HEAD/deploy_key.enc -------------------------------------------------------------------------------- /.merlin: -------------------------------------------------------------------------------- 1 | S src/** 2 | B _build/src/** 3 | PKG menhirLib 4 | PKG sedlex 5 | PKG js_of_ocaml 6 | PKG js_of_ocaml.ppx -------------------------------------------------------------------------------- /src/syntax/grammars/_tags: -------------------------------------------------------------------------------- 1 | : only_tokens 2 | : external_tokens(Tokens) 3 | : external_tokens(Tokens) -------------------------------------------------------------------------------- /src/syntax/basic/astPre.ml: -------------------------------------------------------------------------------- 1 | open Ops 2 | 3 | type pos = Pos.Range.t 4 | 5 | type expr_def = 6 | | EConst of constant 7 | | EUnop of unop * unop_flag * expr 8 | | EBinop of binop * expr * expr 9 | 10 | and expr = expr_def * pos -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.mly": "ocaml", 4 | "*.ml": "ocaml" 5 | }, 6 | "[ocaml]": { 7 | "editor.tabSize": 4 8 | }, 9 | "files.exclude": { 10 | "**/_build": true 11 | }, 12 | "reason.server.languages": ["ocaml"] 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _build/ 2 | .vscode/ 3 | *.mldylib 4 | *.mllib 5 | META 6 | configure 7 | haxe.messages.backup 8 | myocamlbuild.ml 9 | setup.data 10 | setup.ml 11 | Makefile 12 | /_tags 13 | ignore.txt 14 | setup.log 15 | /bin/* 16 | hxparser.exe 17 | hxparserjs.js 18 | deploy_key 19 | -------------------------------------------------------------------------------- /Makefile.messages: -------------------------------------------------------------------------------- 1 | all: update 2 | 3 | create: 4 | menhir --list-errors --infer src/syntax/parser.mly > haxe.messages 5 | 6 | update: 7 | cp haxe.messages haxe.messages.backup 8 | menhir --update-errors haxe.messages.backup --infer src/syntax/parser.mly > haxe.messages 9 | menhir --compile-errors haxe.messages --infer src/syntax/parser.mly > src/syntax/syntaxErrors.ml -------------------------------------------------------------------------------- /src/syntax/config.ml: -------------------------------------------------------------------------------- 1 | type debug_kind = 2 | | DStart 3 | | DShift 4 | | DReduce 5 | | DOffer 6 | | DInsert 7 | | DAccept 8 | | DReject 9 | 10 | type t = { 11 | mutable debug_flags : debug_kind list; 12 | mutable build_parse_tree : bool; 13 | mutable recover : bool; 14 | } 15 | 16 | let default_config () = { 17 | debug_flags = []; 18 | build_parse_tree = false; 19 | recover = false; 20 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | addons: 4 | apt: 5 | sources: 6 | - avsm 7 | packages: 8 | - ocaml 9 | - opam 10 | 11 | install: 12 | - opam init -n 13 | - eval `opam config env` 14 | - opam install oasis -y 15 | - opam install sedlex -y 16 | - opam install menhir -y 17 | - opam install js_of_ocaml -y 18 | - oasis setup 19 | - sh configure --enable-js 20 | 21 | script: 22 | - make build 23 | 24 | after_success: 25 | - bash deploy.sh -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | if [[ $TRAVIS_BRANCH != 'master' ]]; then 2 | exit 3 | fi 4 | 5 | openssl aes-256-cbc -K $encrypted_4ed650af1ebb_key -iv $encrypted_4ed650af1ebb_iv -in deploy_key.enc -out deploy_key -d 6 | chmod 600 deploy_key 7 | eval `ssh-agent -s` 8 | ssh-add deploy_key 9 | cd .. 10 | ssh -T git@github.com 11 | git clone git@github.com:/vshaxe/haxe-hxparser.git 12 | cd haxe-hxparser 13 | cp ../hxparser/hxparserjs.js . 14 | git config user.name 'Travis CI' 15 | git config user.email '<>' 16 | git add -A 17 | git commit -m "Update for vshaxe/hxparser@$TRAVIS_COMMIT" 18 | git push origin -------------------------------------------------------------------------------- /src/syntax/basic/pos.ml: -------------------------------------------------------------------------------- 1 | module Position = struct 2 | type t = Lexing.position 3 | 4 | let print p = 5 | let open Lexing in 6 | Printf.sprintf "%i:%i" p.pos_lnum (p.pos_cnum - p.pos_bol) 7 | end 8 | 9 | module Location = struct 10 | type t = { 11 | file : string; 12 | position : Position.t; 13 | } 14 | end 15 | 16 | module Range = struct 17 | type t = { 18 | first : Position.t; 19 | last : Position.t; 20 | } 21 | 22 | let make first last = { 23 | first = first; 24 | last = last; 25 | } 26 | 27 | let null = make (Lexing.dummy_pos) (Lexing.dummy_pos) 28 | end -------------------------------------------------------------------------------- /src/syntax/lexing/tokenProvider.mli: -------------------------------------------------------------------------------- 1 | open Token 2 | 3 | type t = { 4 | lexbuf : Sedlex_menhir.lexbuf; 5 | skipped_list : int WorkList.t; 6 | mutable inserted_tokens : work_token list; 7 | mutable token_cache : (placed_token * trivia_flag) WorkList.t; 8 | mutable branches : ((AstPre.expr * bool) * bool * Lexing.position) list; 9 | mutable skipped : int; 10 | mutable in_dead_branch : bool; 11 | mutable blocks : range list; 12 | } 13 | 14 | val next_token : t -> work_token 15 | 16 | val insert_token : t -> work_token -> unit 17 | 18 | val on_shift : t -> work_token -> trivia 19 | 20 | val skip : t -> work_token -> unit 21 | 22 | val create : Sedlex_menhir.lexbuf -> t -------------------------------------------------------------------------------- /src/syntax/basic/ops.ml: -------------------------------------------------------------------------------- 1 | type binop = 2 | | OpAdd 3 | | OpMult 4 | | OpDiv 5 | | OpSub 6 | | OpAssign 7 | | OpEq 8 | | OpNotEq 9 | | OpGt 10 | | OpGte 11 | | OpLt 12 | | OpLte 13 | | OpAnd 14 | | OpOr 15 | | OpXor 16 | | OpBoolAnd 17 | | OpBoolOr 18 | | OpShl 19 | | OpShr 20 | | OpUShr 21 | | OpMod 22 | | OpAssignOp of binop 23 | | OpInterval 24 | | OpArrow 25 | | OpIn 26 | 27 | type unop = 28 | | Increment 29 | | Decrement 30 | | Not 31 | | Neg 32 | | NegBits 33 | 34 | type constant = 35 | | Int of string 36 | | Float of string 37 | | String of string 38 | | Ident of string 39 | | Regexp of string * string 40 | 41 | type unop_flag = 42 | | Prefix 43 | | Postfix -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Simon Krajewski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/globals.ml: -------------------------------------------------------------------------------- 1 | module IntMap = Map.Make(struct type t = int let compare a b = a - b end) 2 | module StringMap = Map.Make(struct type t = string let compare = String.compare end) 3 | 4 | type platform = 5 | | Cross 6 | | Js 7 | | Lua 8 | | Neko 9 | | Flash 10 | | Php 11 | | Cpp 12 | | Cs 13 | | Java 14 | | Python 15 | | Hl 16 | 17 | let version = 3400 18 | let version_major = version / 1000 19 | let version_minor = (version mod 1000) / 100 20 | let version_revision = (version mod 100) 21 | let version_is_stable = version_minor land 1 = 0 22 | 23 | let macro_platform = ref Neko 24 | 25 | let is_windows = Sys.os_type = "Win32" || Sys.os_type = "Cygwin" 26 | 27 | let s_version = 28 | Printf.sprintf "%d.%d.%d%s" version_major version_minor version_revision (match Version.version_extra with None -> "" | Some v -> " " ^ v) 29 | 30 | let platforms = [ 31 | Js; 32 | Lua; 33 | Neko; 34 | Flash; 35 | Php; 36 | Cpp; 37 | Cs; 38 | Java; 39 | Python; 40 | Hl; 41 | ] 42 | 43 | let platform_name = function 44 | | Cross -> "cross" 45 | | Js -> "js" 46 | | Lua -> "lua" 47 | | Neko -> "neko" 48 | | Flash -> "flash" 49 | | Php -> "php" 50 | | Cpp -> "cpp" 51 | | Cs -> "cs" 52 | | Java -> "java" 53 | | Python -> "python" 54 | | Hl -> "hl" 55 | 56 | let s_type_path (p,s) = match p with [] -> s | _ -> String.concat "." p ^ "." ^ s -------------------------------------------------------------------------------- /src/syntax/lexing/sedlex_menhir.ml: -------------------------------------------------------------------------------- 1 | (* 2 | Boilerplate for using sedlex with Menhir, based on 3 | https://github.com/Drup/llvm/blob/3c43000f4e86af5b9b368f50721604957d403750/test/Bindings/OCaml/kaleidoscope/src/syntax.ml 4 | *) 5 | 6 | (** The state of the parser, a stream and a position. *) 7 | type lexbuf = { 8 | stream : Sedlexing.lexbuf ; 9 | mutable pos : Lexing.position ; 10 | } 11 | 12 | (** Initialize with the null position. *) 13 | let create_lexbuf ?(file="") stream = 14 | let pos = {Lexing. 15 | pos_fname = file; 16 | pos_lnum = 1; (* Start lines at 1, not 0 *) 17 | pos_bol = 0; 18 | pos_cnum = 0; 19 | } 20 | in { pos ; stream } 21 | 22 | (** Register a new line in the lexer's position. *) 23 | let new_line lexbuf = 24 | let open Lexing in 25 | let lcp = lexbuf.pos in 26 | lexbuf.pos <- 27 | {lcp with 28 | pos_lnum = lcp.pos_lnum + 1; 29 | pos_bol = lcp.pos_cnum; 30 | } 31 | 32 | let set_line lexbuf n = 33 | let open Lexing in 34 | let lcp = lexbuf.pos in 35 | lexbuf.pos <- 36 | {lcp with 37 | pos_lnum = n; 38 | pos_bol = lcp.pos_cnum; 39 | } 40 | 41 | let lexeme { stream } = Sedlexing.Utf8.lexeme stream 42 | 43 | (** Update the position with the stream. *) 44 | let update lexbuf = 45 | let new_pos = Sedlexing.lexeme_end lexbuf.stream in 46 | let p = lexbuf.pos in 47 | lexbuf.pos <- {p with Lexing.pos_cnum = new_pos } -------------------------------------------------------------------------------- /src/syntax/lexing/workList.ml: -------------------------------------------------------------------------------- 1 | module LinkedNode = struct 2 | type 'a t = { 3 | mutable data:'a; 4 | mutable next:'a t; 5 | } 6 | 7 | let insert node data = 8 | let new_node = { 9 | data = data; 10 | next = node.next; 11 | } in 12 | node.next <- new_node; 13 | new_node 14 | 15 | let advance_by node f i = 16 | let rec loop node acc k = 17 | if k = i then node,List.rev acc else loop node.next (f node :: acc) (k + 1) 18 | in 19 | loop node [] 0 20 | 21 | let to_list f t = 22 | let rec loop acc t = 23 | if t == t.next then acc else loop (f t :: acc) t.next 24 | in 25 | List.rev (loop [] t) 26 | 27 | let print f sep t = 28 | let rec loop t = 29 | (f t.data) ^ (if t == t.next then "" else sep ^ loop t.next) 30 | in 31 | loop t 32 | end 33 | 34 | open LinkedNode 35 | 36 | type 'a t = { 37 | first:'a LinkedNode.t; 38 | mutable insert:'a LinkedNode.t; 39 | mutable work:'a LinkedNode.t; 40 | } 41 | 42 | let create neutral = 43 | let rec node_end = { 44 | data = neutral; 45 | next = node_end; 46 | } in 47 | let rec node_start = { 48 | data = neutral; 49 | next = node_end; 50 | } in 51 | { 52 | first = node_start; 53 | insert = node_start; 54 | work = node_start; 55 | } 56 | 57 | let push t data = 58 | let node = insert t.insert data in 59 | t.insert <- node 60 | 61 | let insert t data = 62 | let node = insert t.work data in 63 | if t.work == t.insert then t.insert <- node 64 | 65 | let advance t = 66 | let node = t.work.next in 67 | let data = fst node.data in 68 | t.work <- node; 69 | data 70 | 71 | let advance_by t f i = 72 | let node,l = LinkedNode.advance_by t.work f i in 73 | t.work <- node; 74 | l 75 | 76 | let current t = 77 | t.work.next -------------------------------------------------------------------------------- /src/syntax/grammars/tokens.mly: -------------------------------------------------------------------------------- 1 | (* Token definitions *) 2 | 3 | %token EOF 4 | %token PACKAGE IMPORT USING PUBLIC CLASS INTERFACE ENUM TYPEDEF ABSTRACT PRIVATE STATIC INLINE MACRO OVERRIDE DYNAMIC EXTERN FUNCTION EXTENDS IMPLEMENTS FROM TO AS IS 5 | %token VAR FINAL CAST THROW NEW IF ELSE WHILE DO FOR TRY CATCH RETURN BREAK CONTINUE SWITCH CASE DEFAULT UNTYPED THIS TRUE FALSE NULL IN 6 | %token BROPEN BRCLOSE POPEN PCLOSE BKOPEN BKCLOSE COMMA COLON SEMICOLON QUESTIONMARK DOT 7 | %token ASSIGN PLUS MINUS STAR SLASH 8 | %token EQUALS NOTEQUALS LT LTE GT GTE BOOLAND BOOLOR SHL SHR USHR ARROW INTERVAL DOUBLEARROW 9 | %token EXCLAMATION PERCENT AND OR XOR DOTSTAR 10 | %token ASSIGNMOD ASSIGNAND ASSIGNOR ASSIGNXOR ASSIGNPLUS ASSIGNMINUS ASSIGNSTAR ASSIGNSLASH ASSIGNSHL ASSIGNSHR ASSIGNUSHR ASSIGNBOOLOR ASSIGNBOOLAND 11 | %token INCREMENT DECREMENT TILDE 12 | %token IDENT DOLLAR_IDENT DOT_IDENT STRING STRING2 INT FLOAT METADATA METADATA_OPEN COMMENT 13 | %token REGEX 14 | (* Comment these out if you generate messages, they are unused. *) 15 | %token COMMENTLINE WHITESPACE NEWLINE NONSENSE 16 | %token SHARPIF SHARPELSE SHARPELSEIF SHARPEND SHARPERROR SHARPLINE 17 | %token UNCLOSED 18 | 19 | (* Precedence *) 20 | 21 | %nonassoc LOWEST 22 | %left COMMA 23 | %right RETURN MACRO 24 | %left CATCH ELSE WHILE IF 25 | %left IN IS 26 | %right ASSIGN ASSIGNMOD ASSIGNAND ASSIGNOR ASSIGNXOR ASSIGNPLUS ASSIGNMINUS ASSIGNSTAR ASSIGNSLASH ASSIGNSHL ASSIGNSHR ASSIGNUSHR ASSIGNBOOLOR ASSIGNBOOLAND 27 | %right DOUBLEARROW 28 | %left BOOLOR 29 | %left BOOLAND 30 | %left INTERVAL 31 | %left EQUALS NOTEQUALS GT LT LTE GTE 32 | %left OR AND XOR 33 | %left SHL SHR USHR 34 | %left PLUS MINUS 35 | %left STAR SLASH 36 | %left PERCENT 37 | %right INCREMENT DECREMENT EXCLAMATION 38 | %left ARROW 39 | %right QUESTIONMARK 40 | %right POPEN BKOPEN BROPEN 41 | %nonassoc NONDOT BRCLOSE 42 | %left DOT_IDENT COLON DOT 43 | 44 | %% -------------------------------------------------------------------------------- /src/syntax/grammars/parserPre.mly: -------------------------------------------------------------------------------- 1 | %{ 2 | open AstPre 3 | 4 | let emit_null p = EConst (Ident "null"),p 5 | let emit_true p = EConst (Ident "true"),p 6 | let emit_false p = EConst (Ident "false"),p 7 | let emit_this p = EConst (Ident "this"),p 8 | let emit_literal_string s = String s 9 | let emit_literal_regex (s1,s2) = Regexp(s1,s2) 10 | let emit_literal_int s = Int s 11 | let emit_literal_float s = Float s 12 | let emit_const_ident s = Ident s 13 | let emit_const_literal lit = lit 14 | let emit_const_expr e p = EConst e,p 15 | let emit_unary_prefix_expr op e1 p = EUnop(op,Prefix,e1),p 16 | let emit_binop_expr e1 op e2 p = EBinop(op,e1,e2),p 17 | %} 18 | 19 | %start sharp_condition 20 | %start sharp_error_message 21 | %start sharp_line_number 22 | 23 | %% 24 | 25 | sharp_condition_both: 26 | | e = const { emit_const_expr e (mk $startpos $endpos) } 27 | | MACRO { emit_const_expr (emit_const_ident "macro") (mk $startpos $endpos) } 28 | | STATIC { emit_const_expr (emit_const_ident "static") (mk $startpos $endpos) } 29 | | e1 = keyword_ident { e1 } 30 | | POPEN; e = sharp_condition_any; PCLOSE { e } 31 | | op = unary_prefix; e1 = sharp_condition { emit_unary_prefix_expr op e1 (mk $startpos $endpos) } 32 | 33 | sharp_condition_any: 34 | | e = sharp_condition_both { e } 35 | | e1 = sharp_condition_any; op = op; e2 = sharp_condition_any { emit_binop_expr e1 op e2 (mk $startpos $endpos) } 36 | | e1 = sharp_condition_any; op = op_assign; e2 = sharp_condition_any %prec ASSIGN { emit_binop_expr e1 op e2 (mk $startpos $endpos) } 37 | | e1 = sharp_condition_any; op = op_bit; e2 = sharp_condition_any %prec OR { emit_binop_expr e1 op e2 (mk $startpos $endpos) } 38 | | e1 = sharp_condition_any; op = op_compare; e2 = sharp_condition_any %prec EQUALS { emit_binop_expr e1 op e2 (mk $startpos $endpos) } 39 | 40 | sharp_condition: 41 | | e = sharp_condition_both { e } 42 | 43 | sharp_error_message: 44 | | s = string { s } 45 | 46 | sharp_line_number: 47 | | i = INT { i } 48 | -------------------------------------------------------------------------------- /_oasis: -------------------------------------------------------------------------------- 1 | Name: Hxparser 2 | Version: 0.0.1 3 | Synopsis: A menhir-based implementation of a parser for the Haxe language 4 | Authors: Simon Krajewski 5 | License: MIT 6 | 7 | Description: A menhir-based implementation of a parser for the Haxe language 8 | Homepage: http://haxe.org 9 | 10 | OASISFormat: 0.4 11 | BuildTools: ocamlbuild 12 | Plugins: META (0.4), DevFiles (0.4) 13 | 14 | AlphaFeatures: 15 | ocamlbuild_more_args 16 | 17 | XOCamlbuildExtraArgs: 18 | -no-ocamlfind 19 | -use-menhir 20 | -yaccflag --infer 21 | -yaccflag --table 22 | -yaccflag --inspection 23 | -yaccflag --unused-tokens 24 | -yaccflag --explain 25 | -yaccflag --log-automaton -yaccflag 1 26 | -ocamlopt ocamlopt.opt 27 | 28 | Flag js 29 | Description: Generate hxparserjs.js using js_of_ocaml 30 | Default: false 31 | 32 | PostBuildCommand: 33 | cp _build/src/hxparser.native hxparser.exe 34 | 35 | if flag(js) 36 | PostBuildCommand: cp _build/src/hxparser.native hxparser.exe & js_of_ocaml --wrap-with-fun=embed -o hxparserjs.js _build/src/hxparserjs.byte 37 | 38 | Executable "hxparser" 39 | Path: src 40 | MainIs: hxparser.ml 41 | CompiledObject: native 42 | BuildDepends: menhirLib,sedlex,haxe-syntax,unix,str 43 | 44 | Executable "hxparserjs" 45 | Path: src 46 | MainIs: hxparserjs.ml 47 | CompiledObject: byte 48 | BuildDepends: menhirLib,sedlex,haxe-syntax,unix,str,js_of_ocaml 49 | Build: false 50 | if flag(js) 51 | Build: true 52 | 53 | Library "haxe-context" 54 | Path: src/context 55 | BuildDepends: haxe-root 56 | Modules: Meta 57 | Install: false 58 | 59 | Library "haxe-root" 60 | Path: src 61 | Modules: Globals,Json 62 | Install: false 63 | 64 | Library "haxe-syntax-basic" 65 | Path: src/syntax/basic 66 | BuildDepends: haxe-context 67 | Modules: AstPre,Ops,Pos 68 | Install: false 69 | 70 | Library "haxe-syntax-grammars" 71 | Path: src/syntax/grammars 72 | BuildDepends: sedlex,haxe-syntax-basic,menhirLib 73 | Modules: Parser,ParserPre 74 | Install: false 75 | 76 | Library "haxe-syntax-lexing" 77 | Path: src/syntax/lexing 78 | BuildDepends: haxe-syntax-grammars 79 | Modules: Lexer,Token 80 | 81 | Library "haxe-syntax" 82 | Path: src/syntax 83 | BuildDepends: menhirLib,haxe-context,haxe-root,haxe-syntax-basic,haxe-syntax-lexing,haxe-syntax-grammars 84 | Modules: ParserDriver 85 | Install: false -------------------------------------------------------------------------------- /src/syntax/grammars/parserCommon.mly: -------------------------------------------------------------------------------- 1 | %{ 2 | open Ops 3 | 4 | let mk = Pos.Range.make 5 | %} 6 | 7 | %% 8 | 9 | (* Operators *) 10 | 11 | %public op_assign: 12 | | ASSIGN { OpAssign } 13 | | ASSIGNMOD { OpAssignOp(OpMod) } 14 | | ASSIGNAND { OpAssignOp(OpAnd) } 15 | | ASSIGNOR { OpAssignOp(OpOr) } 16 | | ASSIGNXOR { OpAssignOp(OpXor) } 17 | | ASSIGNPLUS { OpAssignOp(OpAdd) } 18 | | ASSIGNMINUS { OpAssignOp(OpSub) } 19 | | ASSIGNSTAR { OpAssignOp(OpMult) } 20 | | ASSIGNSLASH { OpAssignOp(OpDiv) } 21 | | ASSIGNSHL { OpAssignOp(OpShl) } 22 | | ASSIGNSHR { OpAssignOp(OpShr) } 23 | | ASSIGNUSHR { OpAssignOp(OpUShr) } 24 | | ASSIGNBOOLOR { OpAssignOp(OpBoolOr) } 25 | | ASSIGNBOOLAND { OpAssignOp(OpBoolAnd) } 26 | 27 | %public op_compare: 28 | | EQUALS { OpEq } 29 | | NOTEQUALS { OpNotEq } 30 | | GT { OpGt } 31 | | LT { OpLt } 32 | | LTE { OpLte } 33 | | GTE { OpGte } 34 | 35 | %public op_bit: 36 | | OR { OpOr } 37 | | AND { OpAnd } 38 | | XOR { OpXor } 39 | 40 | %public %inline op: 41 | | PERCENT { OpMod } 42 | | STAR { OpMult } 43 | | SLASH { OpDiv } 44 | | PLUS { OpAdd } 45 | | MINUS { OpSub } 46 | | SHL { OpShl } 47 | | SHR { OpShr } 48 | | USHR { OpUShr } 49 | | INTERVAL { OpInterval } 50 | | BOOLAND { OpBoolAnd } 51 | | BOOLOR { OpBoolOr } 52 | | DOUBLEARROW { OpArrow } 53 | 54 | %public unary_prefix: 55 | | INCREMENT { Increment } 56 | | DECREMENT { Decrement } 57 | | TILDE { NegBits } 58 | | EXCLAMATION { Not } 59 | | MINUS { Neg } 60 | 61 | %public unary_postfix: 62 | | INCREMENT { Increment } 63 | | DECREMENT { Decrement } 64 | | EXCLAMATION { Not } 65 | 66 | (* Expression *) 67 | 68 | %public ident: 69 | | s = IDENT { s } 70 | | FROM { "from" } 71 | | TO { "to" } 72 | | AS { "as" } 73 | | IS { "is" } 74 | | FINAL { "final" } 75 | 76 | %public string: 77 | | s = STRING | s = STRING2 { s } 78 | 79 | literal_string: 80 | | s = string { emit_literal_string s } 81 | 82 | literal_int: 83 | | s = INT %prec NONDOT { emit_literal_int s } 84 | 85 | literal_float: 86 | | s = FLOAT { emit_literal_float s } 87 | 88 | literal_regex: 89 | | s = REGEX { emit_literal_regex s } 90 | 91 | %public literal: 92 | | literal_string | literal_int | literal_float | literal_regex { $1 } 93 | 94 | %public %inline const: 95 | | s = ident { emit_const_ident s } 96 | | s = literal { emit_const_literal s } 97 | 98 | %public keyword_ident: 99 | | THIS { emit_this (mk $startpos $endpos) } 100 | | TRUE { emit_true (mk $startpos $endpos) } 101 | | FALSE { emit_false (mk $startpos $endpos) } 102 | | NULL { emit_null (mk $startpos $endpos) } -------------------------------------------------------------------------------- /src/hxparserjs.ml: -------------------------------------------------------------------------------- 1 | open Config 2 | 3 | module Parser = Parser.Make(NullEmitter) 4 | 5 | module NullParserEngine = struct 6 | module I = Parser.MenhirInterpreter 7 | let s_xsymbol = SymbolPrinter.s_xsymbol 8 | 9 | type tree = 10 | | Node of I.xsymbol * tree list 11 | | Leaf of Token.token_info 12 | end 13 | 14 | module NullParserDriver = ParserDriver.Make(NullParserEngine) 15 | 16 | open NullParserDriver 17 | 18 | module JsOfOcamlConverter = JsonConverter.TreeToJson(struct 19 | type t = Js.Unsafe.any 20 | let jobject l = Js.Unsafe.inject (Js.Unsafe.obj (Array.of_list l)) 21 | let jarray l = Js.Unsafe.inject (Js.array (Array.of_list l)) 22 | let jfloat f = Js.Unsafe.inject (Js.number_of_float f) 23 | let jint i = Js.Unsafe.inject (Js.number_of_float (float_of_int i)) 24 | let jnull = Js.Unsafe.inject Js.null 25 | let jbool b = Js.Unsafe.inject (Js.bool b) 26 | let jstring s = Js.Unsafe.inject (Js.string s) 27 | end) (NullParserEngine) 28 | 29 | let config = { 30 | debug_flags = []; 31 | build_parse_tree = true; 32 | recover = true; 33 | } 34 | 35 | let parse filename entrypoint s = 36 | let open Sedlex_menhir in 37 | let s = Js.to_string s in 38 | let report_error sl = 39 | Js.Unsafe.inject (Js.string "something went very wrong") 40 | in 41 | let lexbuf = create_lexbuf ~file:filename (Sedlexing.Utf8.from_string s) in 42 | begin try 43 | let _ = Lexer.skip_header lexbuf in 44 | let tp = TokenProvider.create lexbuf in 45 | begin match Js.to_string entrypoint with 46 | | "file" -> 47 | begin match run config tp (Parser.Incremental.file lexbuf.pos) with 48 | | Reject(sl,tree,blocks) -> JsOfOcamlConverter.convert tree tp blocks sl 49 | | Accept(_,tree,blocks) -> JsOfOcamlConverter.convert tree tp blocks [] 50 | end; 51 | | "class_fields" -> 52 | begin match run config tp (Parser.Incremental.class_fields_only lexbuf.pos) with 53 | | Reject(sl,tree,blocks) -> JsOfOcamlConverter.convert tree tp blocks sl 54 | | Accept(_,tree,blocks) -> JsOfOcamlConverter.convert tree tp blocks [] 55 | end; 56 | | "class_decl" -> 57 | begin match run config tp (Parser.Incremental.class_decl_only lexbuf.pos) with 58 | | Reject(sl,tree,blocks) -> JsOfOcamlConverter.convert tree tp blocks sl 59 | | Accept(_,tree,blocks) -> JsOfOcamlConverter.convert tree tp blocks [] 60 | end; 61 | | "block_elements" -> 62 | begin match run config tp (Parser.Incremental.block_elements_only lexbuf.pos) with 63 | | Reject(sl,tree,blocks) -> JsOfOcamlConverter.convert tree tp blocks sl 64 | | Accept(_,tree,blocks) -> JsOfOcamlConverter.convert tree tp blocks [] 65 | end; 66 | | entrypoint -> failwith ("Unknown entry point: " ^ entrypoint) 67 | end 68 | with exc -> 69 | report_error [Printexc.to_string exc]; 70 | end; 71 | ;; 72 | 73 | Js.export "parse" parse 74 | -------------------------------------------------------------------------------- /src/json.ml: -------------------------------------------------------------------------------- 1 | (* 2 | The Haxe Compiler 3 | Copyright (C) 2005-2017 Haxe Foundation 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | *) 19 | 20 | type t = 21 | | JString of string 22 | | JFloat of float 23 | | JInt of int 24 | | JObject of (string * t) list 25 | | JArray of t list 26 | | JBool of bool 27 | | JNull 28 | 29 | let write_iter f_el f_sep l = 30 | let rec rest = function 31 | | [] -> () 32 | | v :: l -> 33 | f_sep(); 34 | f_el v; 35 | rest l 36 | in 37 | match l with 38 | | [] -> () 39 | | v :: l -> 40 | f_el v; 41 | rest l 42 | 43 | let write_sep w = 44 | w "," 45 | 46 | let rec write_json w v = 47 | match v with 48 | | JNull -> write_null w 49 | | JBool b -> write_bool w b 50 | | JString s -> write_string w s 51 | | JFloat f -> write_float w f 52 | | JInt i -> write_int w i 53 | | JObject o -> write_object w o 54 | | JArray a -> write_array w a 55 | 56 | and write_null w = 57 | w "null" 58 | 59 | and write_bool w b = 60 | w (if b then "true" else "false") 61 | 62 | and write_string w s = 63 | w "\""; 64 | let b = Buffer.create (String.length s) in 65 | for i = 0 to String.length s - 1 do 66 | match String.unsafe_get s i with 67 | | '"' -> Buffer.add_string b "\\\"" 68 | | '\t' -> Buffer.add_string b "\\t" 69 | | '\r' -> Buffer.add_string b "\\r" 70 | | '\b' -> Buffer.add_string b "\\b" 71 | | '\n' -> Buffer.add_string b "\\n" 72 | | '\012' -> Buffer.add_string b "\\f" 73 | | '\\' -> Buffer.add_string b "\\\\" 74 | | '\x00'..'\x1F' | '\x7F' as c -> Buffer.add_string b (Printf.sprintf "\\u%04X" (int_of_char c)) 75 | | c -> Buffer.add_char b c 76 | done; 77 | w (Buffer.contents b); 78 | w "\"" 79 | 80 | and write_int w i = 81 | w (string_of_int i) 82 | 83 | and write_float w f = 84 | match classify_float f with 85 | | FP_nan | FP_infinite -> failwith "NaN and infinity floats are unsupported in JSON" 86 | | _ -> 87 | let s = Printf.sprintf "%.16g" f in 88 | let s = if float_of_string s = f then s else Printf.sprintf "%.17g" f in 89 | w s 90 | 91 | and write_array w a = 92 | w "["; 93 | write_iter (write_json w) (fun() -> write_sep w) a; 94 | w "]" 95 | 96 | and write_object w o = 97 | let write_el (k, v) = 98 | write_string w k; 99 | w ":"; 100 | write_json w v 101 | in 102 | w "{"; 103 | write_iter write_el (fun() -> write_sep w) o; 104 | w "}" 105 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/vshaxe/hxparser.svg?branch=master)](https://travis-ci.org/vshaxe/hxparser) 2 | 3 | ## Dependencies 4 | 5 | * oasis (for compilation) 6 | * menhir 7 | * sedlex 8 | * js_of_ocaml (only for generating .js) 9 | 10 | ## Preparation 11 | 12 | ``` 13 | opam install oasis 14 | opam install sedlex 15 | opam install menhir 16 | ``` 17 | 18 | ## Compilation 19 | 20 | ``` 21 | oasis setup 22 | make build 23 | ``` 24 | 25 | ## JS compilation 26 | 27 | Run `sh configure --enable-js`, then compile as usual. 28 | 29 | ## Usage 30 | 31 | The most common command is 32 | 33 | ``` 34 | hxparser --json --print-reject YourFile.hx 35 | ``` 36 | 37 | You can also specify a directory, in which case all .hx file are recursively parsed. 38 | 39 | ## Questions 40 | 41 | > Why? 42 | 43 | We are slowly heading towards Haxe 4, so the idea came up to rewrite the parser in a more maintainable way with a strong focus on IDE support. This project is the beginning of said undertaking and, if successful, will be integrated as the official Haxe parser. 44 | 45 | > Performance? 46 | 47 | Performance is not that great at the moment, roughly 50% slower than the current Haxe parser. We are going to investigate and improve on this. 48 | 49 | > I'm a retarded Windows user, how do I opam? 50 | 51 | Check out our [Building on Windows (mingw)](http://haxe.org/documentation/introduction/building-haxe.html) instructions for Haxe. You might have to run the `opam install` commands in a cygwin window, but everything else should work fine. 52 | 53 | > hxparse, haxeparser, hxparser... Are you serious? 54 | 55 | Sorry! 56 | 57 | > What's the difference to the current Haxe parser? 58 | 59 | The current parser is a recursive-descent parser which is implemented using the camlp4o extension to OCaml. It has display support built-in, which is convenient for simple cases but not very flexible overall. 60 | 61 | The new parser uses a [yacc-like grammar definition file](src/syntax/parser.mly), which is much more concise. Parser resuming is to be built into the [parser loop](src/syntax/parserDriver.ml) instead, which allows for a better separation and more flexibility. 62 | 63 | Furthermore, it uses [sedlex](https://github.com/alainfrisch/sedlex) which supports Unicode lexers. 64 | 65 | > Any problems? 66 | 67 | While developing this parser, the author came to the realization that the Haxe grammar is in the LL(2) category due to a specific construct: 68 | 69 | ```haxe 70 | { 71 | if (cond) 72 | e1; 73 | else 74 | e3; 75 | } 76 | ``` 77 | 78 | After parsing `e1`, the current parser looks ahead for 2 tokens to see if there's `; else` coming up. Menhir supports LR(1) grammars, which required a very ugly workaround in the parser loop. 79 | 80 | Another problem is that Haxe allows some optional `;` if they are preceded by a `}` token: 81 | 82 | ```haxe 83 | { 84 | var a = { }; // optional ; 85 | b; 86 | } 87 | ``` 88 | 89 | This seems to be tricky to express in the grammar because if the `;` is omitted, the `}` serves double-purpose: As termination token of the object declaration (or whatever is to be closed) and the block-element. 90 | 91 | It remains to be seen if these are actual issues or if the author is just incompetent. 92 | 93 | > Any good news? 94 | 95 | It successfully parses my GitHub directory recursively and doesn't use much memory. -------------------------------------------------------------------------------- /src/jsonConverter.ml: -------------------------------------------------------------------------------- 1 | module type JsonApi = sig 2 | type t 3 | val (* Ben & *) jarray : t list -> t 4 | val jobject : (string * t) list -> t 5 | val jbool : bool -> t 6 | val jstring : string -> t 7 | val jint : int -> t 8 | val jnull : t 9 | end 10 | 11 | open ParserDriver 12 | 13 | module TreeToJson (Api : JsonApi) (E : Engine) = struct 14 | 15 | open E 16 | open Token 17 | 18 | let pos_to_json p = 19 | let open Lexing in 20 | Api.jint p.pos_cnum 21 | 22 | let range_to_json p1 p2 l = 23 | ("start",pos_to_json p1) :: ("end",pos_to_json p2) :: l 24 | 25 | let rec to_json = function 26 | | Leaf(token,trivia) -> 27 | let acc = ref [] in 28 | let jtoken (tk,p1,p2) l = 29 | ("token",Api.jstring (Token.s_token tk)) :: range_to_json p1 p2 l 30 | in 31 | begin match trivia.tleading with 32 | | [] -> () 33 | | _ -> acc := ("leading",Api.jarray (List.map (fun token -> Api.jobject (jtoken token [])) trivia.tleading)) :: !acc 34 | end; 35 | begin match !(trivia.ttrailing) with 36 | | [] -> () 37 | | l -> acc := ("trailing",Api.jarray (List.map (fun token -> Api.jobject (jtoken token [])) l)) :: !acc 38 | end; 39 | List.iter (function 40 | | TFSkipped -> acc := ("skipped",Api.jbool true) :: !acc 41 | | TFImplicit -> acc := ("implicit",Api.jbool true) :: !acc 42 | | TFInserted -> acc := ("inserted",Api.jbool true) :: !acc 43 | | TFNormal | TFSplit _ -> () 44 | ) trivia.tflags; 45 | let l = ("name",Api.jstring "token") :: jtoken token (match !acc with | [] -> [] | trivia -> ["trivia",Api.jobject trivia ]) in 46 | Api.jobject l 47 | | Node(sym,[]) -> Api.jnull 48 | | Node(sym,[t1]) when (match s_xsymbol sym with "" | "?" -> true | _ -> false) -> to_json t1 49 | | Node(sym,tl) -> 50 | let name = s_xsymbol sym in 51 | begin match List.rev tl with 52 | | Node(sym2, tl2) :: tl when name = (s_xsymbol sym2) -> to_json (Node(sym,(List.rev tl) @ tl2)) 53 | | _ -> 54 | let l = List.map to_json tl in 55 | begin match List.for_all (fun t -> t = Api.jnull) l with 56 | | true -> Api.jnull 57 | | false -> 58 | let j = Api.jarray l in 59 | Api.jobject ["name",Api.jstring name;"sub",j] 60 | end 61 | end 62 | 63 | let convert tree tp blocks errors = 64 | let tree = List.map to_json tree in 65 | let tree = Api.jobject ["name",Api.jstring "tree";"sub",Api.jarray tree] in 66 | let open WorkList in 67 | let open LinkedNode in 68 | let tokens = to_list (fun node -> 69 | let tk,_,_ = fst node.data in 70 | let flag = match snd node.data with 71 | | TFImplicit -> ["flag",Api.jstring "implicit"] 72 | | TFInserted -> ["flag",Api.jstring "inserted"] 73 | | _ -> [] 74 | in 75 | Api.jobject (("token",Api.jstring (s_token tk)) :: flag) 76 | ) tp.TokenProvider.token_cache.first.next in 77 | let skipped = to_list (fun node -> Api.jint node.data) tp.TokenProvider.skipped_list.first.next in 78 | let blocks = List.map (fun (p1,p2) -> Api.jobject (range_to_json p1 p2 [])) blocks in 79 | let errors = List.map (fun s -> Api.jstring s) errors in 80 | let errors = Api.jobject ["name",Api.jstring "errors";"sub",Api.jarray errors] in 81 | let js = Api.jobject ["document",Api.jobject [ 82 | "tree",tree; 83 | "tokens",Api.jarray tokens; 84 | "skipped",Api.jarray skipped; 85 | "blocks",Api.jarray blocks; 86 | "errors",errors 87 | ]] in 88 | js 89 | end -------------------------------------------------------------------------------- /src/syntax/lexing/token.ml: -------------------------------------------------------------------------------- 1 | open Tokens 2 | 3 | type placed_token = (Tokens.token * Lexing.position * Lexing.position) 4 | 5 | type trivia_flag = 6 | | TFNormal 7 | | TFImplicit 8 | | TFInserted 9 | | TFSkipped 10 | | TFSplit of placed_token * placed_token 11 | 12 | type token_info = placed_token * trivia 13 | 14 | and trivia = { 15 | tleading: placed_token list; 16 | ttrailing: placed_token list ref; 17 | tflags : trivia_flag list; 18 | } 19 | 20 | type range = Lexing.position * Lexing.position 21 | 22 | type work_token = placed_token * trivia_flag * int 23 | 24 | let rec s_token tk = match tk with 25 | | COLON -> ":" 26 | | SEMICOLON -> ";" 27 | | COMMA -> "," 28 | | DOT -> "." 29 | | PACKAGE -> "package" 30 | | IDENT s -> s 31 | | DOLLAR_IDENT s -> "$" ^ s 32 | | DOT_IDENT s -> "." ^ s 33 | | STRING s -> "\"" ^ s ^ "\"" 34 | | STRING2 s -> "'" ^ s ^ "'" 35 | | COMMENT s -> "/*" ^ s ^ "*/" 36 | | REGEX(s1,s2) -> "~/" ^ s1 ^ "/" ^ s2 37 | | COMMENTLINE s -> "//" ^ s 38 | | METADATA s -> "@" ^ s 39 | | METADATA_OPEN s -> "@" ^ s ^ "(" 40 | | INT s -> s 41 | | FLOAT s -> s 42 | | SHARPIF -> "#if" 43 | | SHARPELSE -> "#else" 44 | | SHARPELSEIF -> "#elseif" 45 | | SHARPEND -> "#end" 46 | | SHARPERROR -> "#error" 47 | | SHARPLINE -> "#line" 48 | | BRCLOSE -> "}" 49 | | BROPEN -> "{" 50 | | POPEN -> "(" 51 | | PCLOSE -> ")" 52 | | BKOPEN -> "[" 53 | | BKCLOSE -> "]" 54 | | QUESTIONMARK -> "?" 55 | | ASSIGN -> "=" 56 | | PLUS -> "+" 57 | | LT -> "<" 58 | | GT -> ">" 59 | | ASSIGNMOD -> "%=" 60 | | ASSIGNAND -> "&=" 61 | | ASSIGNOR -> "|=" 62 | | ASSIGNXOR -> "^=" 63 | | ASSIGNPLUS -> "+=" 64 | | ASSIGNMINUS -> "-=" 65 | | ASSIGNSTAR -> "*=" 66 | | ASSIGNSLASH -> "/=" 67 | | ASSIGNSHL -> "<<=" 68 | | ASSIGNSHR -> ">>=" 69 | | ASSIGNUSHR -> ">>>=" 70 | | ASSIGNBOOLOR -> "||=" 71 | | ASSIGNBOOLAND -> "&&=" 72 | | INCREMENT -> "++" 73 | | DECREMENT -> "--" 74 | | TILDE -> "~" 75 | | XOR -> "^" 76 | | STAR -> "*" 77 | | SLASH -> "/" 78 | | SHL -> "<<" 79 | | SHR -> ">>" 80 | | USHR -> ">>>" 81 | | PERCENT -> "%" 82 | | OR -> "|" 83 | | NOTEQUALS -> "!=" 84 | | MINUS -> "-" 85 | | LTE -> "<=" 86 | | GTE -> ">=" 87 | | INTERVAL -> "..." 88 | | EXCLAMATION -> "!" 89 | | EQUALS -> "==" 90 | | DOUBLEARROW -> "=>" 91 | | BOOLOR -> "||" 92 | | BOOLAND -> "&&" 93 | | ARROW -> "->" 94 | | AND -> "&" 95 | | FUNCTION -> "function" 96 | | CLASS -> "class" 97 | | INTERFACE -> "interface" 98 | | EXTENDS -> "extends" 99 | | IMPLEMENTS -> "implements" 100 | | VAR -> "var" 101 | | WHILE -> "while" 102 | | USING -> "using" 103 | | UNTYPED -> "untyped" 104 | | TYPEDEF -> "typedef" 105 | | TRY -> "try" 106 | | TRUE -> "true" 107 | | THROW -> "throw" 108 | | THIS -> "this" 109 | | SWITCH -> "switch" 110 | | STATIC -> "static" 111 | | RETURN -> "return" 112 | | PUBLIC -> "public" 113 | | PRIVATE -> "private" 114 | | OVERRIDE -> "override" 115 | | NULL -> "null" 116 | | NEW -> "new" 117 | | MACRO -> "macro" 118 | | INLINE -> "inline" 119 | | IN -> "in" 120 | | IMPORT -> "import" 121 | | IF -> "if" 122 | | FOR -> "for" 123 | | FALSE -> "false" 124 | | EXTERN -> "extern" 125 | | ENUM -> "enum" 126 | | ELSE -> "else" 127 | | DYNAMIC -> "dynamic" 128 | | DOTSTAR -> ".*" 129 | | DO -> "do" 130 | | DEFAULT -> "default" 131 | | CONTINUE -> "continue" 132 | | CATCH -> "catch" 133 | | CAST -> "cast" 134 | | CASE -> "case" 135 | | BREAK -> "break" 136 | | ABSTRACT -> "abstract" 137 | | FROM -> "from" 138 | | TO -> "to" 139 | | AS -> "as" 140 | | IS -> "is" 141 | | FINAL -> "final" 142 | | EOF -> "" 143 | | WHITESPACE s -> s 144 | | NEWLINE s -> s 145 | | NONSENSE s -> s 146 | | UNCLOSED tok -> s_token tok -------------------------------------------------------------------------------- /src/syntax/ast.ml: -------------------------------------------------------------------------------- 1 | (* 2 | The Haxe Compiler 3 | Copyright (C) 2005-2017 Haxe Foundation 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | *) 19 | 20 | open Globals 21 | open Ops 22 | 23 | type pos = Pos.Range.t 24 | type while_flag = 25 | | NormalWhile 26 | | DoWhile 27 | 28 | type quote_status = 29 | | NoQuotes 30 | | DoubleQuotes 31 | 32 | type type_path = { 33 | tpackage : string list; 34 | tname : string; 35 | tparams : type_param_or_const list; 36 | tsub : string option; 37 | } 38 | 39 | and placed_type_path = type_path * pos 40 | 41 | and type_param_or_const = 42 | | TPType of type_hint 43 | | TPExpr of expr 44 | 45 | and complex_type = 46 | | CTPath of type_path 47 | | CTFunction of type_hint list * type_hint 48 | | CTAnonymous of class_field list 49 | | CTParent of type_hint 50 | | CTExtend of placed_type_path list * class_field list 51 | | CTOptional of type_hint 52 | | CTNamed of placed_name * type_hint 53 | 54 | and type_hint = complex_type * pos 55 | 56 | and func = { 57 | f_params : type_param list; 58 | f_args : (placed_name * bool * metadata * type_hint option * expr option) list; 59 | f_type : type_hint option; 60 | f_expr : expr option; 61 | } 62 | 63 | and placed_name = string * pos 64 | 65 | and display_kind = 66 | | DKCall 67 | | DKDot 68 | | DKStructure 69 | | DKToplevel 70 | | DKMarked 71 | 72 | and expr_def = 73 | | EConst of constant 74 | | EArray of expr * expr 75 | | EBinop of binop * expr * expr 76 | | EField of expr * string 77 | | EParenthesis of expr 78 | | EObjectDecl of ((string * pos * quote_status) * expr) list 79 | | EArrayDecl of expr list 80 | | ECall of expr * expr list 81 | | ENew of placed_type_path * expr list 82 | | EUnop of unop * unop_flag * expr 83 | | EVars of (placed_name * type_hint option * expr option) list 84 | | EFunction of string option * func 85 | | EBlock of expr list 86 | | EFor of expr * expr 87 | | EIf of expr * expr * expr option 88 | | EWhile of expr * expr * while_flag 89 | | ESwitch of expr * (expr list * expr option * expr option * pos) list * (expr option * pos) option 90 | | ETry of expr * (placed_name * type_hint * expr * pos) list 91 | | EReturn of expr option 92 | | EBreak 93 | | EContinue 94 | | EUntyped of expr 95 | | EThrow of expr 96 | | ECast of expr * type_hint option 97 | | EDisplay of expr * display_kind 98 | | EDisplayNew of placed_type_path 99 | | ETernary of expr * expr * expr 100 | | ECheckType of expr * type_hint 101 | | EMeta of metadata_entry * expr 102 | 103 | and expr = expr_def * pos 104 | 105 | and type_param = { 106 | tp_name : placed_name; 107 | tp_params : type_param list; 108 | tp_constraints : type_hint list; 109 | tp_meta : metadata; 110 | } 111 | 112 | and documentation = string option 113 | 114 | and metadata_entry = (Meta.strict_meta * expr list * pos) 115 | and metadata = metadata_entry list 116 | 117 | and access = 118 | | APublic 119 | | APrivate 120 | | AStatic 121 | | AOverride 122 | | ADynamic 123 | | AInline 124 | | AMacro 125 | | AFinal 126 | | AExtern 127 | 128 | and placed_access = access * pos 129 | 130 | and class_field_kind = 131 | | FVar of type_hint option * expr option 132 | | FFun of func 133 | | FProp of placed_name * placed_name * type_hint option * expr option 134 | 135 | and class_field = { 136 | cff_name : placed_name; 137 | cff_doc : documentation; 138 | cff_pos : pos; 139 | mutable cff_meta : metadata; 140 | mutable cff_access : placed_access list; 141 | mutable cff_kind : class_field_kind; 142 | } 143 | 144 | type enum_flag = 145 | | EPrivate 146 | | EExtern 147 | 148 | type class_flag = 149 | | HInterface 150 | | HExtern 151 | | HPrivate 152 | | HExtends of placed_type_path 153 | | HImplements of placed_type_path 154 | 155 | type abstract_flag = 156 | | AbPrivate 157 | | AbFrom of type_hint 158 | | AbTo of type_hint 159 | | AbOver of type_hint 160 | | AbExtern 161 | 162 | type enum_constructor = { 163 | ec_name : placed_name; 164 | ec_doc : documentation; 165 | ec_meta : metadata; 166 | ec_args : (string * bool * type_hint) list; 167 | ec_pos : pos; 168 | ec_params : type_param list; 169 | ec_type : type_hint option; 170 | } 171 | 172 | type ('a,'b) definition = { 173 | d_name : placed_name; 174 | d_doc : documentation; 175 | d_params : type_param list; 176 | d_meta : metadata; 177 | d_flags : 'a list; 178 | d_data : 'b; 179 | } 180 | 181 | type import_mode = 182 | | INormal 183 | | IAsName of string 184 | | IAll 185 | 186 | type import = placed_name list * import_mode 187 | 188 | type type_def = 189 | | EClass of (class_flag, class_field list) definition 190 | | EEnum of (enum_flag, enum_constructor list) definition 191 | | ETypedef of (enum_flag, type_hint) definition 192 | | EAbstract of (abstract_flag, class_field list) definition 193 | | EImport of import 194 | | EUsing of placed_name list 195 | 196 | type type_decl = type_def * pos 197 | 198 | type package = string list * type_decl list 199 | 200 | let expr_of_type_path (sl,s) p = 201 | match sl with 202 | | [] -> (EConst(Ident s),p) 203 | | s1 :: sl -> 204 | let e1 = (EConst(Ident s1),p) in 205 | let e = List.fold_left (fun e s -> (EField(e,s),p)) e1 sl in 206 | EField(e,s),p -------------------------------------------------------------------------------- /src/syntax/lexing/tokenProvider.ml: -------------------------------------------------------------------------------- 1 | open Sedlex_menhir 2 | open Tokens 3 | open AstPre 4 | open Ops 5 | open Token 6 | open WorkList.LinkedNode 7 | open WorkList 8 | 9 | type t = { 10 | lexbuf : lexbuf; 11 | skipped_list : int WorkList.t; 12 | mutable inserted_tokens : work_token list; 13 | mutable token_cache : (placed_token * trivia_flag) WorkList.t; 14 | mutable branches : ((expr * bool) * bool * Lexing.position) list; 15 | mutable skipped : int; 16 | mutable in_dead_branch : bool; 17 | mutable blocks : range list; 18 | } 19 | 20 | let create lexbuf = { 21 | lexbuf = lexbuf; 22 | skipped_list = WorkList.create 0; 23 | inserted_tokens = []; 24 | token_cache = begin 25 | let neutral = ((NONSENSE "",Lexing.dummy_pos,Lexing.dummy_pos),TFNormal) in 26 | WorkList.create neutral; 27 | end; 28 | branches = []; 29 | skipped = 0; 30 | in_dead_branch = false; 31 | blocks = []; 32 | } 33 | 34 | let insert_token tp wtoken = 35 | tp.inserted_tokens <- wtoken :: tp.inserted_tokens 36 | 37 | let on_shift tp (token,flag,skipped) = 38 | let trail = ref [] in 39 | let cache = tp.token_cache in 40 | let skip () = 41 | let skipped = tp.skipped + skipped in 42 | tp.skipped <- 0; 43 | WorkList.push tp.skipped_list skipped; 44 | WorkList.advance_by cache (fun node -> fst node.next.data) skipped 45 | in 46 | let leading = match flag with 47 | | TFNormal -> 48 | let leading = skip() in 49 | ignore(advance cache); 50 | leading; 51 | | TFSkipped -> 52 | assert false; 53 | | TFInserted | TFImplicit -> 54 | let leading = skip() in 55 | insert cache (token,flag); 56 | ignore(advance cache); 57 | leading; 58 | | TFSplit(original,token2) -> 59 | let leading = skip() in 60 | (WorkList.current cache).data <- (token,snd (WorkList.current cache).data); 61 | ignore(advance cache); 62 | insert cache (token2,TFNormal); 63 | leading; 64 | in 65 | {tleading = leading; ttrailing = trail; tflags = [flag]} 66 | 67 | let skip tp (_,_,skipped) = 68 | tp.skipped <- tp.skipped + skipped + 1 69 | 70 | let lexer_token tp = 71 | let p1 = tp.lexbuf.pos in 72 | let tk = (if tp.in_dead_branch then Lexer.preprocessor else Lexer.token) tp.lexbuf in 73 | let p2 = tp.lexbuf.pos in 74 | push tp.token_cache ((tk,p1,p2),TFNormal); 75 | (tk,p1,p2) 76 | 77 | let rec fetch_token tp skipped = 78 | let token = lexer_token tp in 79 | process_token tp token skipped 80 | 81 | and process_token tp (tk,p1,p2) skipped = 82 | let not_expr e = EUnop(Not,Prefix,e),snd e in 83 | let preprocess checkpoint = 84 | let skipped = ref 0 in 85 | let cond = ParserPre.MenhirInterpreter.loop (fun () -> 86 | let token,skipped2 = fetch_token tp 0 in 87 | skipped := !skipped + skipped2 + 1; 88 | token 89 | ) checkpoint in 90 | cond,!skipped 91 | in 92 | match tk with 93 | | (WHITESPACE _ | COMMENT _ | NONSENSE _) -> 94 | fetch_token tp (skipped + 1) 95 | | NEWLINE _ | COMMENTLINE _ -> 96 | fetch_token tp (skipped + 1) 97 | | SHARPERROR -> 98 | let message_checkpoint = ParserPre.Incremental.sharp_error_message tp.lexbuf.pos in 99 | let _,skipped2 = preprocess message_checkpoint in 100 | (* TODO: this loses tokens if there is no message *) 101 | fetch_token tp (skipped + skipped2 + 1) 102 | | SHARPLINE -> 103 | let line_number_checkpoint = ParserPre.Incremental.sharp_line_number tp.lexbuf.pos in 104 | let line,skipped2 = preprocess line_number_checkpoint in 105 | set_line tp.lexbuf (try int_of_string line with _ -> assert false); 106 | fetch_token tp (skipped + skipped2 + 1) 107 | | SHARPIF when tp.in_dead_branch -> 108 | (* We have to push _something_ on the stack so the #end can consume it. Parsing the 109 | condition could arrive at the #end immediately. *) 110 | tp.branches <- (((EConst (Ident "false"),Pos.Range.null),true),true,p1) :: tp.branches; 111 | fetch_token tp (skipped + 1) 112 | | SHARPIF -> 113 | let cond_checkpoint = ParserPre.Incremental.sharp_condition tp.lexbuf.pos in 114 | let cond,skipped2 = preprocess cond_checkpoint in 115 | tp.branches <- ((cond,tp.in_dead_branch),tp.in_dead_branch,p1) :: tp.branches; 116 | fetch_token tp (skipped + skipped2 + 1) 117 | | SHARPELSEIF -> 118 | begin match tp.branches with 119 | | ((_,b1),b2,_) :: _ when not b1 || b2 -> 120 | tp.in_dead_branch <- true; 121 | fetch_token tp (skipped + 1) 122 | | ((cond2,dead_branch),dead,p1) :: branches -> 123 | let cond_checkpoint = ParserPre.Incremental.sharp_condition tp.lexbuf.pos in 124 | let cond,skipped2 = preprocess cond_checkpoint in 125 | tp.branches <- ((cond,false),dead,p1) :: branches; 126 | if dead || not dead_branch then tp.in_dead_branch <- true; 127 | fetch_token tp (skipped + skipped2 + 1) 128 | | [] -> assert false 129 | end 130 | | SHARPELSE -> 131 | begin match tp.branches with 132 | | ((cond,dead_branch),dead,p1) :: branches -> 133 | tp.branches <- ((not_expr cond,not dead_branch),dead,p1) :: branches; 134 | if dead || not dead_branch then tp.in_dead_branch <- true; 135 | fetch_token tp (skipped + 1) 136 | | [] -> assert false 137 | end 138 | | SHARPEND -> 139 | begin match tp.branches with 140 | | (_,dead,p1) :: branches -> 141 | tp.blocks <- (p1,p2) :: tp.blocks; 142 | tp.branches <- branches; 143 | tp.in_dead_branch <- dead; 144 | fetch_token tp (skipped + 1) 145 | | [] -> assert false 146 | end 147 | | _ -> 148 | (tk,p1,p2),skipped 149 | 150 | let next_token tp = match tp.inserted_tokens with 151 | | [] -> 152 | let token,skipped = fetch_token tp 0 in 153 | begin match token with 154 | | (SEMICOLON,_,_) -> 155 | begin match fetch_token tp 0 with 156 | | ((ELSE,_,_) as token2),skipped2 -> 157 | token2,TFNormal,skipped + skipped2 + 1 158 | | token2,skipped2 -> 159 | insert_token tp (token2,TFNormal,skipped2); 160 | token,TFNormal,skipped 161 | end 162 | | _ -> token,TFNormal,skipped 163 | end 164 | | (token,flag,skipped) :: tokens -> 165 | tp.inserted_tokens <- tokens; 166 | token,flag,skipped -------------------------------------------------------------------------------- /src/hxparser.ml: -------------------------------------------------------------------------------- 1 | open Config 2 | open Json 3 | 4 | module Parser = Parser.Make(AstEmitter) 5 | 6 | module AstParserEngine = struct 7 | module I = Parser.MenhirInterpreter 8 | let s_xsymbol = Obj.magic SymbolPrinter.s_xsymbol 9 | 10 | type tree = 11 | | Node of I.xsymbol * tree list 12 | | Leaf of Token.token_info 13 | end 14 | 15 | module AstParserDriver = ParserDriver.Make(AstParserEngine) 16 | 17 | module JSONConverter = JsonConverter.TreeToJson(struct 18 | open Json 19 | 20 | type t = Json.t 21 | let jobject l = JObject l 22 | let jarray l = JArray l 23 | let jint i = JInt i 24 | let jstring s = JString s 25 | let jbool b = JBool b 26 | let jnull = JNull 27 | end) (AstParserEngine) 28 | 29 | let config = Config.default_config() 30 | let quit_early = ref true 31 | let output_json = ref false 32 | let num_files = ref 0 33 | let num_errors = ref 0 34 | let compare = ref false 35 | 36 | let stdin_filename = "" 37 | 38 | let load_file f = 39 | let ic = open_in_bin f in 40 | let n = in_channel_length ic in 41 | let s = Bytes.create n in 42 | really_input ic s 0 n; 43 | close_in ic; 44 | s 45 | 46 | (*let print node = 47 | let f (token,flag) = match flag with 48 | | TFNormal | TFSkipped -> let (tk,_,_) = token in "(" ^ s_token tk ^ ")" 49 | | TFImplicit | TFInserted -> "" 50 | | TFSplit _ -> assert false 51 | in 52 | WorkList.LinkedNode.print f "" node*) 53 | 54 | let parse filename = 55 | let open Sedlex_menhir in 56 | incr num_files; 57 | let ch = 58 | if filename = stdin_filename then ( 59 | set_binary_mode_in stdin true; 60 | stdin 61 | ) else 62 | open_in_bin filename 63 | in 64 | let report_error sl = 65 | List.iter prerr_endline sl; 66 | prerr_endline ("while parsing " ^ filename ^ "\n\n"); 67 | incr num_errors; 68 | if !quit_early then begin 69 | close_in ch; 70 | failwith "Failed" 71 | end; 72 | in 73 | let lexbuf = create_lexbuf ~file:filename (Sedlexing.Utf8.from_channel ch) in 74 | begin try 75 | let _ = Lexer.skip_header lexbuf in 76 | let tp = TokenProvider.create lexbuf in 77 | let print_json tree blocks errors = match tree with 78 | | [] -> () 79 | | tl -> 80 | let js = JSONConverter.convert tree tp blocks errors in 81 | let buffer = Buffer.create 0 in 82 | write_json (Buffer.add_string buffer) js; 83 | print_endline (Buffer.contents buffer); 84 | in 85 | let open AstParserDriver in 86 | begin match AstParserDriver.run config tp (Parser.Incremental.file lexbuf.pos) with 87 | | Reject(sl,tree,blocks) -> 88 | if !output_json then begin 89 | print_json tree blocks sl; 90 | exit 0 91 | end; 92 | report_error sl 93 | | Accept(_,tree,blocks) -> 94 | if !output_json then begin 95 | print_json tree blocks []; 96 | exit 0; 97 | end; 98 | end; 99 | with exc -> 100 | report_error [Printexc.to_string exc]; 101 | end; 102 | close_in ch 103 | ;; 104 | 105 | let read_file filename = 106 | let lines = ref [] in 107 | let chan = open_in filename in 108 | try 109 | while true; do 110 | lines := (Str.regexp (input_line chan)) :: !lines 111 | done; !lines 112 | with End_of_file -> 113 | close_in chan; 114 | List.rev !lines 115 | ;; 116 | 117 | let ignores = ref ( 118 | let ignores = 119 | if Sys.file_exists "ignore.txt" then read_file "ignore.txt" 120 | else [] 121 | in 122 | (Str.regexp "\\.git") :: ignores 123 | ) 124 | 125 | let is_ignored s = 126 | List.exists (fun r -> 127 | try ignore(Str.search_forward r s 0); true with Not_found -> false 128 | ) !ignores 129 | 130 | let explore_class_paths path = 131 | let rec loop dir = 132 | try 133 | let entries = Sys.readdir dir in 134 | Array.iter (fun file -> 135 | match file with 136 | | _ when is_ignored (dir ^ file) -> 137 | () 138 | | "." | ".." -> 139 | () 140 | | _ when Sys.is_directory (dir ^ file) -> 141 | loop (dir ^ file ^ "/") 142 | | _ -> 143 | let l = String.length file in 144 | if l > 3 && String.sub file (l - 3) 3 = ".hx" then begin 145 | let filename = dir ^ file in 146 | parse filename 147 | end 148 | ) entries; 149 | with Sys_error _ -> 150 | () 151 | in 152 | loop path; 153 | ;; 154 | 155 | let usage = Printf.sprintf "haxe.native [options] [files]" 156 | let args_spec = [ 157 | ("--json", Arg.Unit (fun () -> 158 | config.build_parse_tree <- true; 159 | output_json := true; 160 | ),"generate JSON parse tree"); 161 | ("--build-parse-tree", Arg.Unit (fun () -> 162 | config.build_parse_tree <- true; 163 | ),"build parse tree"); 164 | ("--print-accept", Arg.Unit (fun () -> 165 | config.build_parse_tree <- true; 166 | config.debug_flags <- DAccept :: config.debug_flags; 167 | ),"print parse tree on accept"); 168 | ("--print-sr", Arg.Unit (fun () -> 169 | config.debug_flags <- DShift :: DReduce :: config.debug_flags; 170 | ),"print shift/reduce"); 171 | ("--print-offer", Arg.Unit (fun () -> 172 | config.debug_flags <- DOffer :: config.debug_flags; 173 | ),"print offer"); 174 | ("--print-insert", Arg.Unit (fun () -> 175 | config.debug_flags <- DInsert :: config.debug_flags; 176 | ),"print insertions"); 177 | ("--print-reject", Arg.Unit (fun () -> 178 | config.debug_flags <- DReject :: config.debug_flags; 179 | ),"print rejections"); 180 | ("--print-start", Arg.Unit (fun () -> 181 | config.debug_flags <- DStart :: config.debug_flags; 182 | ),"print start"); 183 | ("--keep-going", Arg.Unit (fun () -> 184 | quit_early := false 185 | ),"don't quit if there's an exception"); 186 | ("--compare", Arg.Unit (fun () -> 187 | compare := true; 188 | config.build_parse_tree <- true; 189 | ),"compare roundtripped parse result with source file"); 190 | ("--recover", Arg.Unit (fun () -> 191 | config.recover <- true; 192 | ),"silently recover if possible"); 193 | ] 194 | let paths = ref [] 195 | let process args = 196 | let current = ref 0 in 197 | let args_callback s = 198 | paths := s :: !paths 199 | in 200 | begin try 201 | Arg.parse_argv ~current (Array.of_list ("" :: args)) args_spec args_callback usage; 202 | with 203 | | Arg.Bad _ -> 204 | () 205 | | Arg.Help message -> 206 | () 207 | end 208 | ;; 209 | let args = (List.tl (Array.to_list Sys.argv)) in 210 | process args;; 211 | if !paths = [] then 212 | Arg.usage args_spec usage 213 | else begin 214 | let now = Sys.time () in 215 | List.iter (fun s -> 216 | if s = stdin_filename then 217 | parse s 218 | else if not (Sys.file_exists s) then 219 | prerr_endline ("No such file or directory: " ^ s) 220 | else begin 221 | if Sys.is_directory s then begin 222 | prerr_endline ("Reading directory " ^ s); 223 | explore_class_paths (s ^ "/") 224 | end 225 | else parse s 226 | end 227 | ) !paths; 228 | prerr_endline (Printf.sprintf "Parsed %i files, %i failed" !num_files !num_errors); 229 | prerr_endline (string_of_float (Sys.time () -. now) ^ "s"); 230 | end -------------------------------------------------------------------------------- /src/syntax/nullEmitter.ml: -------------------------------------------------------------------------------- 1 | type 'a t_pos = 'a * Pos.Range.t 2 | type t_metadata_entry = unit 3 | type t_annotations = unit 4 | type t_path = unit 5 | type t_pos_path = unit 6 | type t_literal = unit 7 | type t_const = unit 8 | 9 | type t_block_element = unit 10 | type t_object_field_name = unit 11 | type t_object_field = unit 12 | type t_call_args = unit 13 | type t_var_declaration = unit 14 | type t_catch = unit 15 | type t_case = unit 16 | type t_expr = unit 17 | 18 | type t_constraint = unit 19 | type t_type_path_parameter_kind = unit 20 | type t_type_path = unit 21 | type t_complex_type = unit 22 | 23 | type t_function_argument = unit 24 | type t_function = unit 25 | type t_field_expr = unit 26 | type t_modifier = unit 27 | type t_function_name = unit 28 | type t_property_ident = unit 29 | type t_class_field = unit 30 | type t_enum_field_arg = unit 31 | type t_enum_field = unit 32 | type t_anonymous_field = unit 33 | type t_anonymous_type_fields = unit 34 | 35 | type t_type_decl_parameter = unit 36 | type t_import_mode = unit 37 | type t_abstract_relation = unit 38 | type t_class_relation = unit 39 | type t_common_flag = unit 40 | type t_class_flag = unit 41 | type t_class = unit 42 | type t_decl = unit 43 | type t_package = unit 44 | 45 | let emit_path ident idents = () 46 | 47 | let emit_pos_path ident idents = () 48 | 49 | let emit_metadata_entry meta p = () 50 | 51 | let emit_metadata_entry_with_args meta el p = () 52 | 53 | let emit_function name tl args cto e = () 54 | 55 | let emit_lambda_arg arg = [] 56 | 57 | let emit_annotations so metadata = () 58 | 59 | let emit_literal_string s = () 60 | 61 | let emit_literal_int s = () 62 | 63 | let emit_literal_float s = () 64 | 65 | let emit_literal_regex (s1,s2) = () 66 | 67 | let emit_const_ident s = () 68 | 69 | let emit_const_literal lit = () 70 | 71 | let emit_call_args el = () 72 | 73 | let emit_assignment e = () 74 | 75 | let emit_var_declaration name cto eo = () 76 | 77 | let emit_catch name ct e p = () 78 | 79 | let emit_case el1 eo el2 p = () 80 | 81 | let emit_default el p = () 82 | 83 | let emit_object_field name e = () 84 | 85 | let emit_object_field_name_ident s p = () 86 | 87 | let emit_object_field_name_string s p = () 88 | 89 | let emit_unknown p = () 90 | 91 | let emit_block_element_var vl p = () 92 | 93 | let emit_block_element_inline_function f p = () 94 | 95 | let emit_block_element_expr e p = () 96 | 97 | let emit_this p = () 98 | 99 | let emit_true p = () 100 | 101 | let emit_false p = () 102 | 103 | let emit_null p = () 104 | 105 | let emit_block_expr el p = () 106 | 107 | let emit_var_declaration_expr v p = () 108 | 109 | let emit_metadata_expr meta e p = () 110 | 111 | let emit_throw_expr e p = () 112 | 113 | let emit_if_expr e1 e2 eo p = () 114 | 115 | let emit_return_expr eo p = () 116 | 117 | let emit_break_expr p = () 118 | 119 | let emit_continue_expr p = () 120 | 121 | let emit_do_expr e1 e2 p = () 122 | 123 | let emit_try_expr e catches p = () 124 | 125 | let emit_switch_expr e cases p = () 126 | 127 | let emit_for_expr e1 e2 p = () 128 | 129 | let emit_while_expr e1 e2 p = () 130 | 131 | let emit_untyped_expr e p = () 132 | 133 | let emit_object_decl_expr fl p = () 134 | 135 | let emit_unsafe_cast_expr e p = () 136 | 137 | let emit_safe_cast_expr e ct p = () 138 | 139 | let emit_new_expr path el p = () 140 | 141 | let emit_parenthesis_expr e p = () 142 | 143 | let emit_typecheck_expr e ct p = () 144 | 145 | let emit_is_expr e path p_is p = () 146 | 147 | let emit_array_decl_expr el p = () 148 | 149 | let emit_function_expr f p = () 150 | 151 | let emit_unary_prefix_expr op e p = () 152 | 153 | let emit_field_expr e s p = () 154 | 155 | let emit_call_expr e el p = () 156 | 157 | let emit_array_expr e1 e2 p = () 158 | 159 | let emit_binop_expr e1 op e2 p = () 160 | 161 | let emit_unary_postfix_expr e op p = () 162 | 163 | let emit_ternary_expr e1 e2 e3 p = () 164 | 165 | let emit_in_expr e1 e2 p = () 166 | 167 | let emit_dotint_expr s p = () 168 | 169 | let emit_dollarident_expr name p = () 170 | 171 | let emit_macro_escape_expr name e p = () 172 | 173 | let emit_macro_expr e p = () 174 | 175 | let emit_const_expr const p = () 176 | 177 | (* Type hints *) 178 | 179 | let emit_type_path (path : t_path) params p = () 180 | 181 | let emit_complex_type_path path p = () 182 | let emit_complex_type_parent ct p = () 183 | let emit_complex_type_extension paths fields p = () 184 | let emit_complex_type_anonymous fields p = () 185 | let emit_complex_type_optional ct p = () 186 | 187 | let emit_complex_type_function ct1 ct2 p = () 188 | 189 | let emit_complex_type_named n ct p = () 190 | 191 | let emit_complex_type_named_function ctl ct p = () 192 | 193 | let emit_type_path_parameter_complex_type ct = () 194 | 195 | let emit_type_path_parameter_bracket el p = () 196 | 197 | let emit_type_path_parameter_literal lit p = () 198 | 199 | let emit_type_path_parameter_bool _ p = () 200 | 201 | (* Fields *) 202 | 203 | let emit_function_argument annotations opt name cto eo = () 204 | 205 | let emit_field_expr_none = () 206 | let emit_field_expr_block e = () 207 | let emit_field_expr_expr e = () 208 | 209 | let emit_static_modifier _ = () 210 | let emit_macro_modifier _ = () 211 | let emit_public_modifier _ = () 212 | let emit_private_modifier _ = () 213 | let emit_override_modifier _ = () 214 | let emit_dynamic_modifier _ = () 215 | let emit_inline_modifier _ = () 216 | let emit_extern_modifier _ = () 217 | 218 | let emit_function_field annotations modifiers name tl args cto e p = () 219 | 220 | let emit_variable_field annotations modifiers name cto eo p = () 221 | 222 | let emit_property_field annotations modifiers name get set cto eo p = () 223 | 224 | let emit_enum_field_arg opt name ct = () 225 | 226 | let emit_enum_field annotations name tl args cto p = () 227 | 228 | let emit_anonymous_class_fields fields = () 229 | let emit_anonymous_type_fields fields = () 230 | 231 | let emit_anonymous_type_field opt name ct p = () 232 | 233 | (* Type declaration *) 234 | 235 | let emit_constraints_none = () 236 | 237 | let emit_constraints_single ct = () 238 | 239 | let emit_constraints_multiple ctl = () 240 | 241 | let emit_type_decl_parameter annotations name constraints = () 242 | 243 | let emit_class_flag_interface = () 244 | 245 | let emit_class_flag_class = () 246 | 247 | let emit_common_flag_extern = () 248 | 249 | let emit_common_flag_private = () 250 | 251 | let emit_class_relation_extends path = () 252 | 253 | let emit_class_relation_implements path = () 254 | 255 | let emit_abstract_relation_from ct = () 256 | 257 | let emit_abstract_relation_to ct = () 258 | 259 | let emit_import_mode_all = () 260 | 261 | let emit_import_mode_alias name = () 262 | 263 | let emit_import_mode_normal = () 264 | 265 | let emit_import path mode p = () 266 | 267 | let emit_using path p = () 268 | 269 | let emit_class flags name tl rl l = () 270 | 271 | let emit_class_decl annotations flags c p = () 272 | 273 | let emit_enum_decl annotations flags name tl l p = () 274 | 275 | let emit_typedef_decl annotations flags name tl ct p = () 276 | 277 | let emit_abstract_decl annotations flags name tl st rl l p = () 278 | 279 | let emit_package path = () -------------------------------------------------------------------------------- /src/syntax/parserDriver.ml: -------------------------------------------------------------------------------- 1 | open Tokens 2 | open Token 3 | open TokenProvider 4 | 5 | module type Engine = sig 6 | module I : MenhirLib.IncrementalEngine.EVERYTHING with type token = token 7 | val s_xsymbol : I.xsymbol -> string 8 | 9 | type tree = 10 | | Node of I.xsymbol * tree list 11 | | Leaf of token_info 12 | end 13 | 14 | module Make (E : Engine) = struct 15 | 16 | open E 17 | module M = MenhirLib.General 18 | 19 | module State = struct 20 | type 'a t = { 21 | recover_state : 'a t; 22 | checkpoint : 'a I.checkpoint; 23 | last_offer : work_token; 24 | last_shift : placed_token; 25 | tree : tree list; 26 | } 27 | 28 | let create checkpoint = 29 | let dummy_token = (EOF,Lexing.dummy_pos,Lexing.dummy_pos) in 30 | let rec state = { 31 | checkpoint = checkpoint; 32 | last_offer = (dummy_token,TFNormal,0); 33 | last_shift = dummy_token; 34 | recover_state = state; 35 | tree = []; 36 | } in 37 | state 38 | end 39 | 40 | type 'a result = 41 | | Accept of 'a * tree list * range list 42 | | Reject of string list * tree list * range list 43 | 44 | let print_position = Pos.Position.print 45 | 46 | let print_token (token,p1,p2) = 47 | Printf.sprintf "%s (%s - %s)" (s_token token) (print_position p1) (print_position p2) 48 | 49 | open State 50 | open Config 51 | 52 | let has_debug config flag = List.mem flag config.debug_flags 53 | 54 | let offer config state flag skipped token = 55 | if has_debug config DOffer then begin 56 | prerr_endline (Printf.sprintf "[OFFER ] %s" (print_token token)); 57 | end; 58 | let checkpoint = I.offer state.checkpoint token in 59 | let state = {state with last_offer = (token,flag,skipped); checkpoint = checkpoint; recover_state = state} in 60 | state 61 | 62 | let shift (config,tp) state = 63 | let token,_,_ = state.last_offer in 64 | if has_debug config DShift then begin 65 | let ((tk,_,_)) = token in prerr_endline (Printf.sprintf "[SHIFT ] %s" (s_token tk)); 66 | end; 67 | let state = 68 | if config.build_parse_tree then {state with tree = Leaf(token,TokenProvider.on_shift tp state.last_offer) :: state.tree} 69 | else state 70 | in 71 | state,token 72 | 73 | let rec loop (config,tp) state = match state.checkpoint with 74 | | I.Accepted v -> 75 | if has_debug config DAccept then begin 76 | prerr_endline "[ACCEPT]" 77 | end; 78 | Accept(v,state.tree,tp.TokenProvider.blocks) 79 | | I.InputNeeded _ -> 80 | let token,flag,skipped = TokenProvider.next_token tp in 81 | let state = offer config state flag skipped token in 82 | loop (config,tp) state 83 | | I.Shifting _ -> 84 | let state,token = shift (config,tp) state in 85 | let state = {state with checkpoint = I.resume state.checkpoint; last_shift = token} in 86 | loop (config,tp) state 87 | | I.AboutToReduce(_,production) -> 88 | if has_debug config DReduce then begin match I.rhs production with 89 | | [] -> () 90 | | rhs -> prerr_endline (Printf.sprintf "[REDUCE] %s <- %s" (E.s_xsymbol (I.lhs production)) (String.concat " " (List.map E.s_xsymbol rhs))); 91 | end; 92 | let state = {state with checkpoint = I.resume state.checkpoint} in 93 | let state = if config.build_parse_tree then begin 94 | let l = List.length (I.rhs production) in 95 | let rec loop i acc nodes = 96 | if i >= l then acc,nodes 97 | else match nodes with 98 | | hd :: tl -> loop (i + 1) (hd :: acc) tl 99 | | [] -> assert false 100 | in 101 | let nodes1,nodes2 = loop 0 [] state.tree in 102 | {state with tree = ((Node((I.lhs production),nodes1)) :: nodes2)} 103 | end else 104 | state 105 | in 106 | loop (config,tp) state 107 | | I.HandlingError env -> 108 | let insert token allowed p = 109 | if has_debug config DInsert then begin 110 | prerr_endline (Printf.sprintf "[INSERT] %s" (s_token token)); 111 | end; 112 | let last_offer = state.last_offer in 113 | let token = (token,p,p) in 114 | let state = offer config state.recover_state (if allowed then TFImplicit else TFInserted) 0 token in 115 | TokenProvider.insert_token tp last_offer; 116 | (config,tp),state 117 | in 118 | let token,_,skipped = state.last_offer in 119 | let split (p1,p2) new1 new2 = 120 | let open Lexing in 121 | let p1' = {p1 with pos_cnum = p1.pos_cnum + 1} in 122 | let token1 = (new1,p1,p1') in 123 | let token2 = (new2,p1',p2) in 124 | TokenProvider.insert_token tp (token2,TFNormal,0); 125 | TokenProvider.insert_token tp (token1,(TFSplit(token,token2)),skipped); 126 | (config,tp),state.recover_state 127 | in 128 | let acceptable token = I.acceptable state.recover_state.checkpoint token in 129 | let fail () = 130 | loop (config,tp) {state with checkpoint = I.resume state.checkpoint} 131 | in 132 | begin match state.last_shift,token with 133 | | ((BRCLOSE,_,p)),_ when acceptable SEMICOLON p -> 134 | let fst,snd = insert SEMICOLON true p in 135 | loop fst snd 136 | | _,((SHR,p1,p2)) when acceptable GT p1 -> (let (fst,snd) = split (p1,p2) GT GT in loop fst snd) 137 | | _,((USHR,p1,p2)) when acceptable GT p1 -> (let (fst,snd) = split (p1,p2) GT SHR in loop fst snd) 138 | | _,((GTE,p1,p2)) when acceptable GT p1 -> (let (fst,snd) = split (p1,p2) GT ASSIGN in loop fst snd) 139 | | _,((ASSIGNSHR,p1,p2)) when acceptable GT p1 -> (let (fst,snd) = split (p1,p2) GT GTE in loop fst snd) 140 | | _,((ASSIGNUSHR,p1,p2)) when acceptable GT p1 -> (let (fst,snd) = split (p1,p2) GT ASSIGNSHR in loop fst snd) 141 | | _ when not config.recover -> fail() 142 | | ((tk,_,p)),_ -> 143 | if acceptable SEMICOLON p then (let (fst,snd) = insert SEMICOLON false p in loop fst snd) 144 | else if acceptable PCLOSE p then (let (fst,snd) = insert PCLOSE false p in loop fst snd) 145 | else if acceptable BKCLOSE p then (let (fst,snd) = insert BKCLOSE false p in loop fst snd) 146 | else if tk <> SEMICOLON && acceptable (IDENT "_") p then (let (fst,snd) = insert (IDENT "_") false p in loop fst snd) 147 | else begin match token with 148 | | ((EOF,_,_)) -> 149 | if acceptable BRCLOSE p then (let (fst,snd) = insert BRCLOSE false p in loop fst snd) 150 | else fail() 151 | | token -> 152 | TokenProvider.skip tp state.last_offer; 153 | loop (config,tp) state.recover_state 154 | end 155 | (*let so = match Lazy.force (I.stack env) with 156 | | M.Cons(I.Element(lrstate,_,_,_),_) -> (try Some (SyntaxErrors.message (I.number lrstate)) with Not_found -> None) 157 | | _ -> None 158 | in 159 | begin match so with 160 | | Some s -> prerr_endline s; 161 | | None -> () 162 | end;*) 163 | end; 164 | | I.Rejected -> 165 | let messages = ref [] in 166 | if has_debug config DReject then begin 167 | messages := (Printf.sprintf "[REJECT] %s" (print_token (let token,_,_ = state.last_offer in token))) :: !messages; 168 | end else 169 | messages := "[REJECT]" :: !messages; 170 | let state = 171 | (* In recover mode we only fail if the last offer was EOF. Since that wasn't shifted, 172 | let's append it to the rejected tree. *) 173 | if config.recover then fst (shift (config,tp) state) 174 | else state 175 | in 176 | Reject(!messages,List.rev state.tree,tp.TokenProvider.blocks) 177 | 178 | let start (config,tp) checkpoint = 179 | if has_debug config DStart then begin 180 | prerr_endline "[START ]" 181 | end; 182 | let state = State.create checkpoint in 183 | loop (config,tp) state 184 | 185 | let run config tp checkpoint = 186 | start (config,tp) checkpoint 187 | end -------------------------------------------------------------------------------- /src/syntax/basic/emitter.mli: -------------------------------------------------------------------------------- 1 | type pos = Pos.Range.t 2 | 3 | module type Sig = sig 4 | type 'a t_pos = 'a * pos 5 | type t_metadata_entry 6 | type t_annotations 7 | type t_path 8 | type t_pos_path 9 | type t_literal 10 | type t_const 11 | 12 | (* Expr *) 13 | 14 | type t_block_element 15 | type t_object_field_name 16 | type t_object_field 17 | type t_call_args 18 | type t_var_declaration 19 | type t_catch 20 | type t_case 21 | type t_expr 22 | 23 | (* Type hints *) 24 | 25 | type t_constraint 26 | type t_type_path_parameter_kind 27 | type t_type_path 28 | type t_complex_type 29 | 30 | (* Fields *) 31 | 32 | type t_function_argument 33 | type t_function 34 | type t_field_expr 35 | type t_modifier 36 | type t_class_field 37 | type t_enum_field_arg 38 | type t_enum_field 39 | type t_anonymous_field 40 | type t_anonymous_type_fields 41 | 42 | (* Type declaration *) 43 | 44 | type t_type_decl_parameter 45 | type t_import_mode 46 | type t_abstract_relation 47 | type t_class_relation 48 | type t_common_flag 49 | type t_class_flag 50 | type t_class 51 | type t_decl 52 | type t_package 53 | 54 | val emit_path : string -> string list -> t_path 55 | val emit_pos_path : string t_pos -> string t_pos list -> t_pos_path 56 | val emit_metadata_entry : Meta.strict_meta -> Pos.Range.t -> t_metadata_entry 57 | val emit_metadata_entry_with_args : Meta.strict_meta -> t_expr list -> Pos.Range.t -> t_metadata_entry 58 | val emit_function : string option -> t_type_decl_parameter list -> t_function_argument list -> t_complex_type option -> t_expr -> t_function 59 | val emit_lambda_arg : (t_expr * bool * t_metadata_entry list * t_complex_type option * t_expr option) * t_function_argument list -> t_function_argument list 60 | val emit_annotations : string option -> t_metadata_entry list -> t_annotations 61 | 62 | (* Expr *) 63 | 64 | val emit_literal_string : string -> t_literal 65 | val emit_literal_int : string -> t_literal 66 | val emit_literal_float : string -> t_literal 67 | val emit_literal_regex : (string * string) -> t_literal 68 | val emit_const_ident : string -> t_const 69 | val emit_const_literal : t_literal -> t_const 70 | 71 | val emit_call_args : t_expr list -> t_call_args 72 | val emit_assignment : t_expr -> t_expr 73 | val emit_var_declaration : string t_pos -> t_complex_type option -> t_expr option -> t_var_declaration 74 | 75 | val emit_catch : string t_pos -> t_complex_type -> t_expr -> pos -> t_catch 76 | val emit_case : t_expr list -> t_expr option -> t_block_element list -> pos -> t_case 77 | val emit_default : t_block_element list -> pos -> t_case 78 | val emit_object_field : t_object_field_name -> t_expr -> t_object_field 79 | val emit_object_field_name_ident : string -> pos -> t_object_field_name 80 | val emit_object_field_name_string : string -> pos -> t_object_field_name 81 | val emit_unknown : pos -> t_expr 82 | 83 | val emit_block_element_var : t_var_declaration list -> pos -> t_block_element 84 | val emit_block_element_inline_function : t_function -> pos -> t_block_element 85 | val emit_block_element_expr : t_expr -> pos -> t_block_element 86 | 87 | val emit_this : pos -> t_expr 88 | val emit_true : pos -> t_expr 89 | val emit_false : pos -> t_expr 90 | val emit_null : pos -> t_expr 91 | val emit_block_expr : t_block_element list -> pos -> t_expr 92 | val emit_var_declaration_expr : t_var_declaration -> pos -> t_expr 93 | val emit_metadata_expr : t_metadata_entry -> t_expr -> pos -> t_expr 94 | val emit_throw_expr : t_expr -> pos -> t_expr 95 | val emit_if_expr : t_expr -> t_expr -> t_expr option -> pos -> t_expr 96 | val emit_return_expr : t_expr option -> pos -> t_expr 97 | val emit_break_expr : pos -> t_expr 98 | val emit_continue_expr : pos -> t_expr 99 | val emit_do_expr : t_expr -> t_expr -> pos -> t_expr 100 | val emit_try_expr : t_expr -> t_catch list -> pos -> t_expr 101 | val emit_switch_expr : t_expr -> t_case list -> pos -> t_expr 102 | val emit_for_expr : t_expr -> t_expr -> pos -> t_expr 103 | val emit_while_expr : t_expr -> t_expr -> pos -> t_expr 104 | val emit_untyped_expr : t_expr -> pos -> t_expr 105 | val emit_object_decl_expr : t_object_field list -> pos -> t_expr 106 | val emit_unsafe_cast_expr : t_expr -> pos -> t_expr 107 | val emit_safe_cast_expr : t_expr -> t_complex_type -> pos -> t_expr 108 | val emit_new_expr : t_type_path -> t_call_args -> pos -> t_expr 109 | val emit_parenthesis_expr : t_expr -> pos -> t_expr 110 | val emit_typecheck_expr : t_expr -> t_complex_type -> pos -> t_expr 111 | val emit_is_expr : t_expr -> t_type_path -> pos -> pos -> t_expr 112 | val emit_array_decl_expr : t_expr list -> pos -> t_expr 113 | val emit_function_expr : t_function -> pos -> t_expr 114 | val emit_unary_prefix_expr : Ops.unop -> t_expr -> pos -> t_expr 115 | val emit_field_expr : t_expr -> string -> pos -> t_expr 116 | val emit_call_expr : t_expr -> t_call_args -> pos -> t_expr 117 | val emit_array_expr : t_expr -> t_expr -> pos -> t_expr 118 | val emit_binop_expr : t_expr -> Ops.binop -> t_expr -> pos -> t_expr 119 | val emit_unary_postfix_expr : t_expr -> Ops.unop -> pos -> t_expr 120 | val emit_ternary_expr : t_expr -> t_expr -> t_expr -> pos -> t_expr 121 | val emit_in_expr : t_expr -> t_expr -> pos -> t_expr 122 | val emit_dotint_expr : string -> pos -> t_expr 123 | val emit_dollarident_expr : string -> pos -> t_expr 124 | val emit_macro_escape_expr : string t_pos -> t_expr -> pos -> t_expr 125 | val emit_macro_expr : t_expr -> pos -> t_expr 126 | val emit_const_expr : t_const -> pos -> t_expr 127 | 128 | (* Type hints *) 129 | 130 | val emit_type_path : t_path -> t_type_path_parameter_kind list -> pos -> t_type_path 131 | 132 | val emit_complex_type_path : t_type_path -> pos -> t_complex_type 133 | val emit_complex_type_parent : t_complex_type -> pos -> t_complex_type 134 | val emit_complex_type_extension : t_type_path list -> t_anonymous_type_fields -> pos -> t_complex_type 135 | val emit_complex_type_anonymous : t_anonymous_type_fields -> pos -> t_complex_type 136 | val emit_complex_type_optional : t_complex_type -> pos -> t_complex_type 137 | val emit_complex_type_function : t_complex_type -> t_complex_type -> pos -> t_complex_type 138 | val emit_complex_type_named : string t_pos -> t_complex_type -> pos -> t_complex_type 139 | val emit_complex_type_named_function : t_complex_type list -> t_complex_type -> pos -> t_complex_type 140 | 141 | val emit_type_path_parameter_complex_type : t_complex_type -> t_type_path_parameter_kind 142 | val emit_type_path_parameter_bracket : t_expr list -> pos -> t_type_path_parameter_kind 143 | val emit_type_path_parameter_literal : t_literal -> pos -> t_type_path_parameter_kind 144 | val emit_type_path_parameter_bool : bool -> pos -> t_type_path_parameter_kind 145 | 146 | (* Fields *) 147 | 148 | val emit_function_argument : t_annotations -> unit option -> string t_pos -> t_complex_type option -> t_expr option -> t_function_argument 149 | 150 | val emit_field_expr_none : t_field_expr 151 | val emit_field_expr_block : t_expr -> t_field_expr 152 | val emit_field_expr_expr : t_expr -> t_field_expr 153 | 154 | val emit_static_modifier : pos -> t_modifier 155 | val emit_macro_modifier : pos -> t_modifier 156 | val emit_public_modifier : pos -> t_modifier 157 | val emit_private_modifier : pos -> t_modifier 158 | val emit_override_modifier : pos -> t_modifier 159 | val emit_dynamic_modifier : pos -> t_modifier 160 | val emit_inline_modifier : pos -> t_modifier 161 | val emit_extern_modifier : pos -> t_modifier 162 | 163 | val emit_function_field : t_annotations -> t_modifier list -> string t_pos -> t_type_decl_parameter list -> t_function_argument list -> t_complex_type option -> t_field_expr -> pos -> t_class_field 164 | val emit_variable_field : t_annotations -> t_modifier list -> string t_pos -> t_complex_type option -> t_expr option -> pos -> t_class_field 165 | val emit_property_field : t_annotations -> t_modifier list -> string t_pos -> string t_pos -> string t_pos -> t_complex_type option -> t_expr option -> pos -> t_class_field 166 | 167 | val emit_enum_field_arg : unit option -> string -> t_complex_type -> t_enum_field_arg 168 | val emit_enum_field : t_annotations -> string t_pos -> t_type_decl_parameter list -> t_enum_field_arg list -> t_complex_type option -> pos -> t_enum_field 169 | 170 | val emit_anonymous_class_fields : t_class_field list -> t_anonymous_type_fields 171 | val emit_anonymous_type_fields : t_anonymous_field list -> t_anonymous_type_fields 172 | val emit_anonymous_type_field : unit option -> string t_pos -> t_complex_type -> pos -> t_anonymous_field 173 | 174 | (* Type declaration *) 175 | 176 | val emit_constraints_none : t_constraint 177 | val emit_constraints_single : t_complex_type -> t_constraint 178 | val emit_constraints_multiple : t_complex_type list -> t_constraint 179 | val emit_type_decl_parameter : t_annotations -> string t_pos -> t_constraint -> t_type_decl_parameter 180 | 181 | val emit_common_flag_extern : t_common_flag 182 | val emit_common_flag_private : t_common_flag 183 | val emit_class_flag_class : t_class_flag 184 | val emit_class_flag_interface : t_class_flag 185 | val emit_class_relation_extends : t_type_path -> t_class_relation 186 | val emit_class_relation_implements : t_type_path -> t_class_relation 187 | val emit_abstract_relation_from : t_complex_type -> t_abstract_relation 188 | val emit_abstract_relation_to : t_complex_type -> t_abstract_relation 189 | 190 | val emit_import_mode_alias : string -> t_import_mode 191 | val emit_import_mode_all : t_import_mode 192 | val emit_import_mode_normal : t_import_mode 193 | val emit_import : t_pos_path -> t_import_mode -> pos -> t_decl 194 | val emit_using : t_pos_path -> pos -> t_decl 195 | val emit_class : t_class_flag -> string t_pos option -> t_type_decl_parameter list -> t_class_relation list -> t_class_field list -> t_class 196 | val emit_class_decl : t_annotations -> t_common_flag list -> t_class -> pos -> t_decl 197 | val emit_enum_decl : t_annotations -> t_common_flag list -> string t_pos -> t_type_decl_parameter list -> t_enum_field list -> pos -> t_decl 198 | val emit_typedef_decl : t_annotations -> t_common_flag list -> string t_pos -> t_type_decl_parameter list -> t_complex_type -> pos -> t_decl 199 | val emit_abstract_decl : t_annotations -> t_common_flag list -> string t_pos -> t_type_decl_parameter list -> t_complex_type option -> t_abstract_relation list -> t_class_field list -> pos -> t_decl 200 | 201 | (* File *) 202 | 203 | val emit_package : t_path option -> t_package 204 | end -------------------------------------------------------------------------------- /src/syntax/symbolPrinter.ml: -------------------------------------------------------------------------------- 1 | open Tokens 2 | 3 | module Parser = Parser.Make(NullEmitter) 4 | open Parser.MenhirInterpreter 5 | 6 | let s_xsymbol x = 7 | match x with 8 | | X (T x) -> 9 | begin match x with 10 | | T_COLON -> ":" 11 | | T_SEMICOLON -> ";" 12 | | T_COMMA -> "," 13 | | T_DOT -> "." 14 | | T_PACKAGE -> "package" 15 | | T_IDENT -> "IDENT" 16 | | T_DOT_IDENT -> "DOT_IDENT" 17 | | T_DOLLAR_IDENT -> "DOLLAR_IDENT" 18 | | T_STRING -> "STRING" 19 | | T_STRING2 -> "STRING2" 20 | | T_METADATA -> "METADATA" 21 | | T_METADATA_OPEN -> "METADATA_OPEN" 22 | | T_INT -> "INT" 23 | | T_FLOAT -> "FLOAT" 24 | | T_SHARPIF -> "#if" 25 | | T_SHARPELSE -> "#else" 26 | | T_SHARPELSEIF -> "#elseif" 27 | | T_SHARPEND -> "#end" 28 | | T_SHARPERROR -> "#error" 29 | | T_SHARPLINE -> "#line" 30 | | T_BRCLOSE -> "}" 31 | | T_BROPEN -> "{" 32 | | T_POPEN -> "(" 33 | | T_PCLOSE -> ")" 34 | | T_BKOPEN -> "[" 35 | | T_BKCLOSE -> "]" 36 | | T_QUESTIONMARK -> "?" 37 | | T_ASSIGN -> "=" 38 | | T_PLUS -> "+" 39 | | T_LT -> "<" 40 | | T_GT -> ">" 41 | | T_ASSIGNMOD -> "%=" 42 | | T_ASSIGNAND -> "&=" 43 | | T_ASSIGNOR -> "|=" 44 | | T_ASSIGNXOR -> "^=" 45 | | T_ASSIGNPLUS -> "+=" 46 | | T_ASSIGNMINUS -> "-=" 47 | | T_ASSIGNSTAR -> "*=" 48 | | T_ASSIGNSLASH -> "/=" 49 | | T_ASSIGNSHL -> "<<=" 50 | | T_ASSIGNSHR -> ">>=" 51 | | T_ASSIGNUSHR -> ">>>=" 52 | | T_ASSIGNBOOLOR -> "||=" 53 | | T_ASSIGNBOOLAND -> "&&=" 54 | | T_INCREMENT -> "++" 55 | | T_DECREMENT -> "--" 56 | | T_TILDE -> "~" 57 | | T_XOR -> "^" 58 | | T_STAR -> "*" 59 | | T_SLASH -> "/" 60 | | T_SHL -> "<<" 61 | | T_SHR -> ">>" 62 | | T_USHR -> ">>>" 63 | | T_PERCENT -> "%" 64 | | T_OR -> "|" 65 | | T_NOTEQUALS -> "!=" 66 | | T_MINUS -> "-" 67 | | T_LTE -> "<=" 68 | | T_GTE -> ">=" 69 | | T_INTERVAL -> "..." 70 | | T_EXCLAMATION -> "!" 71 | | T_EQUALS -> "==" 72 | | T_DOUBLEARROW -> "=>" 73 | | T_BOOLOR -> "||" 74 | | T_BOOLAND -> "&&" 75 | | T_ARROW -> "->" 76 | | T_AND -> "&" 77 | | T_FUNCTION -> "function" 78 | | T_CLASS -> "class" 79 | | T_INTERFACE -> "interface" 80 | | T_EXTENDS -> "extends" 81 | | T_IMPLEMENTS -> "implements" 82 | | T_VAR -> "var" 83 | | T_EOF -> "#eof" 84 | | T_WHITESPACE -> "#whitespace" 85 | | T_NEWLINE -> "#newline" 86 | | T_COMMENT -> "#comment" 87 | | T_REGEX -> "#regex" 88 | | T_COMMENTLINE -> "#commentline" 89 | | T_WHILE -> "while" 90 | | T_USING -> "using" 91 | | T_UNTYPED -> "untyped" 92 | | T_TYPEDEF -> "typedef" 93 | | T_TRY -> "try" 94 | | T_TRUE -> "true" 95 | | T_THROW -> "throw" 96 | | T_THIS -> "this" 97 | | T_SWITCH -> "switch" 98 | | T_STATIC -> "static" 99 | | T_RETURN -> "return" 100 | | T_PUBLIC -> "public" 101 | | T_PRIVATE -> "private" 102 | | T_OVERRIDE -> "override" 103 | | T_NULL -> "null" 104 | | T_NEW -> "new" 105 | | T_MACRO -> "macro" 106 | | T_INLINE -> "inline" 107 | | T_IN -> "in" 108 | | T_IMPORT -> "import" 109 | | T_IF -> "if" 110 | | T_FOR -> "for" 111 | | T_FALSE -> "false" 112 | | T_EXTERN -> "extern" 113 | | T_ENUM -> "enum" 114 | | T_ELSE -> "else" 115 | | T_DYNAMIC -> "dynamic" 116 | | T_DOTSTAR -> ".*" 117 | | T_DO -> "do" 118 | | T_DEFAULT -> "default" 119 | | T_CONTINUE -> "continue" 120 | | T_CATCH -> "catch" 121 | | T_CAST -> "cast" 122 | | T_CASE -> "case" 123 | | T_BREAK -> "break" 124 | | T_ABSTRACT -> "abstract" 125 | | T_FROM -> "from" 126 | | T_TO -> "to" 127 | | T_AS -> "as" 128 | | T_IS -> "is" 129 | | T_FINAL -> "final" 130 | | T_NONSENSE -> "#nonsense" 131 | | T_error -> "#error" 132 | | T_UNCLOSED -> "#unclosed" 133 | end 134 | | X (N x) -> 135 | begin match x with 136 | | N_file -> "file" 137 | | N_package -> "package" 138 | | N_function_field -> "function_field" 139 | | N_variable_field -> "variable_field" 140 | | N_property_field -> "property_field" 141 | | N_final_field -> "final_field" 142 | | N_using_decl -> "using_decl" 143 | | N_import_decl -> "import_decl" 144 | | N_typedef_decl -> "typedef_decl" 145 | | N_abstract_decl -> "abstract_decl" 146 | | N_literal_string -> "literal_string" 147 | | N_literal_float -> "literal_float" 148 | | N_literal_int -> "literal_int" 149 | | N_literal_regex -> "literal_regex" 150 | | N_enum_decl -> "enum_decl" 151 | | N_ident -> "ident" 152 | | N_class_decl -> "class_decl" 153 | | N_expr_open -> "" 154 | | N_expr_closed -> "" 155 | | N_block_element_var -> "block_element_var" 156 | | N_block_element_inline_function -> "block_element_inline_function" 157 | | N_block_element_expr -> "block_element_expr" 158 | | N_object_field -> "object_field" 159 | | N_string -> "string" 160 | | N_expr_only -> "expr_only" 161 | | N_documentation -> "documentation" 162 | | N_annotations -> "annotations" 163 | | N_path -> "path" 164 | | N_op_assign -> "" 165 | | N_op_bit -> "" 166 | | N_op_compare -> "" 167 | | N_unary_prefix -> "" 168 | | N_unary_postfix -> "" 169 | | N_type_path_parameters -> "type_path_parameters" 170 | | N_type_path -> "type_path" 171 | | N_class_relations -> "class_relations" 172 | | N_call_args -> "call_args" 173 | | N_type_hint -> "type_hint" 174 | (* | N_dollar_ident -> "dollar_ident" *) 175 | | N_complex_type -> "complex_type" 176 | | N_anonymous_type_field -> "anonymous_type_field" 177 | | N_var_declaration -> "var_declaration" 178 | | N_assignment -> "assignment" 179 | | N_structural_extension -> "structural_extension" 180 | | N_underlying_type -> "underlying_type" 181 | | N_type_decl_parameters -> "type_decl_parameters" 182 | | N_type_decl_parameter -> "type_decl_parameter" 183 | | N_property_ident -> "property_ident" 184 | | N_modifier -> "" 185 | | N_guard -> "guard" 186 | | N_function_name -> "" 187 | | N_function_argument -> "function_argument" 188 | | N_function_arguments -> "" 189 | | N_constraints_multiple -> "multiple" 190 | | N_constraints_single -> "single" 191 | | N_constraints_none -> "none" 192 | | N_common_flags -> "common_flags" 193 | | N_keyword_ident -> "keyword_ident" 194 | | N_catch -> "catch" 195 | | N_case -> "case" 196 | | N_anonymous_type_fields -> "" 197 | | N_abstract_relations -> "abstract relations" 198 | | N_func -> "function" 199 | | N_enum_field_args -> "enum_field_args" 200 | | N_enum_field_arg -> "enum_field_arg" 201 | | N_enum_field -> "enum_field" 202 | | N_macro_expr -> "macro_expr" 203 | | N_class_or_interface -> "class_or_interface" 204 | | N_literal -> "literal" 205 | | N_object_field_name -> "object_field_name" 206 | | N_else_expr -> "else_expr" 207 | | N_field_expr_none -> "field_expr_none" 208 | | N_field_expr_block -> "field_expr_block" 209 | | N_field_expr_expr -> "field_expr_expr" 210 | | N_expr_empty_block -> "expr_empty_block" 211 | | N_expr_nonempty_block -> "expr_nonempty_block" 212 | | N_lambda_function_argument -> "lambda_function_argument" 213 | | N_lambda_function_arguments -> "lambda_function_arguments" 214 | | N_metadata -> "metadata" 215 | | N_expr -> "" 216 | | N_expr_typechecks -> "expr_typechecks" 217 | | N_expr_lambda -> "expr_lambda" 218 | | N_enum_abstract_decl -> "enum_abstract_decl" 219 | | N_abstract_decl2 -> "abstract_decl2" 220 | | N_dot_ident -> "dot_ident" 221 | | N_class_fields_only -> "class_fields_only" 222 | | N_class_decl_only -> "class_decl_only" 223 | | N_block_elements_only -> "block_elements_only" 224 | | N_expr_metadata -> "expr_metadata" 225 | | N_expr_macro -> "expr_macro" 226 | | N_expr_throw -> "expr_throw" 227 | | N_expr_if -> "expr_if" 228 | | N_expr_return -> "expr_return" 229 | | N_expr_return_value -> "expr_return_value" 230 | | N_expr_break -> "expr_break" 231 | | N_expr_continue -> "expr_continue" 232 | | N_expr_do -> "expr_do" 233 | | N_expr_try -> "expr_try" 234 | | N_expr_switch -> "expr_switch" 235 | | N_expr_for -> "expr_for" 236 | | N_expr_while -> "expr_while" 237 | | N_expr_untyped -> "expr_untyped" 238 | | N_expr_object_declaration -> "expr_object_declaration" 239 | | N_expr_unsafe_cast -> "expr_unsafe_cast" 240 | | N_expr_safe_cast -> "expr_safe_cast" 241 | | N_expr_new -> "expr_new" 242 | | N_expr_is -> "expr_is" 243 | | N_expr_array_declaration -> "expr_array_declaration" 244 | | N_expr_function -> "expr_function" 245 | | N_expr_unary_prefix -> "expr_unary_prefix" 246 | | N_expr_field -> "expr_field" 247 | | N_expr_call -> "expr_call" 248 | | N_expr_array_access -> "expr_array_access" 249 | | N_expr_binop -> "expr_binop" 250 | | N_expr_unary_postfix -> "expr_unary_postfix" 251 | | N_expr_ternary -> "expr_ternary" 252 | | N_expr_in -> "expr_in" 253 | | N_expr_dotint -> "expr_dotint" 254 | | N_expr_dollarident -> "expr_dollarident" 255 | | N_expr_macro_escape -> "expr_macro_escape" 256 | | N_expr_const -> "expr_const" 257 | | N_expr_keyword_ident -> "expr_keyword_ident" 258 | | N_expr_var -> "expr_var" 259 | | N_complex_type_parent -> "parenthesis" 260 | | N_complex_type_extension -> "extension" 261 | | N_complex_type_anonymous -> "anonymous" 262 | | N_complex_type_optional -> "optional" 263 | | N_complex_type_path -> "path" 264 | | N_complex_type_function -> "function" 265 | | N_macro_expr_type_hint -> "macro_type_hint" 266 | | N_macro_expr_var -> "macro_var" 267 | | N_macro_expr_class_decl -> "macro_class_decl" 268 | | N_macro_expr_expr -> "macro_expr_expr" 269 | | N_anonymous_type_fields_short_next -> "short_fields" 270 | | N_anonymous_type_fields_short -> "short_fields" 271 | | N_type_path_parameter_bracket -> "bracket" 272 | | N_type_path_parameter_complex_type -> "complex_type" 273 | | N_type_path_parameter_literal -> "literal" 274 | | N_type_path_parameter_bool -> "bool" 275 | | N_unused -> "" 276 | | N_import_mode_normal -> "normal" 277 | | N_import_mode_all -> "all" 278 | | N_import_mode_alias -> "alias" 279 | | N_case_expr -> "case_expr" 280 | | N_complex_type_named -> "complex_type_named" 281 | | N_complex_type_maybe_named -> "complex_type_maybe_named" 282 | (* options *) 283 | | N_option_package_ -> "?" 284 | | N_option_type_hint_ -> "?" 285 | | N_option_assignment_ -> "?" 286 | | N_option_underlying_type_ -> "?" 287 | | N_option_guard_ -> "?" 288 | | N_option_QUESTIONMARK_ -> "?" 289 | | N_option_dollar_ident_ -> "?" 290 | | N_option_SEMICOLON_ -> "?" 291 | | N_option_pos_dollar_ident__ -> "?" 292 | | N_lpoption_type_hint_ -> "?" 293 | | N_lpoption_assignment_ -> "?" 294 | | N_lpoption_else_expr_ -> "?" 295 | | N_loption_separated_nonempty_list_COMMA_expr__ -> "?" 296 | | N_loption_separated_nonempty_list_COMMA_function_argument__ -> "?" 297 | | N_option_path_ -> "?" 298 | (* lists *) 299 | | N_path_with_pos -> "path" 300 | | N_array_elements -> "elements" 301 | | N_array_elements_next -> "elements" 302 | | N_object_fields -> "object_fields" 303 | | N_object_fields_next -> "object_fields" 304 | | N_var_declarations -> "vars" 305 | | N_var_declarations_next -> "vars" 306 | | N_lplist_pos_dot_ident__ -> "path" 307 | | N_lplist_dot_ident_ -> "path" 308 | | N_lplist_catch_ -> "catches" 309 | | N_list_modifier_ -> "modifiers" 310 | | N_list_common_flags_ -> "flags" 311 | | N_list_case_ -> "cases" 312 | | N_list_block_element_ -> "elements" 313 | | N_list_abstract_relations_ -> "relations" 314 | | N_list_decl_ -> "decls" 315 | | N_list_class_field_ -> "class_fields" 316 | | N_list_metadata_ -> "metadatas" 317 | | N_list_class_relations_ -> "relations" 318 | | N_nonempty_list_structural_extension_ -> "extensions" 319 | | N_nonempty_list_block_element_ -> "elements" 320 | | N_nonempty_list_class_field_ -> "class_fields" 321 | | N_separated_nonempty_list_COMMA_expr_ -> "exprs" 322 | | N_separated_nonempty_list_COMMA_type_path_parameter_ -> "params" 323 | | N_separated_nonempty_list_COMMA_type_decl_parameter_ -> "params" 324 | | N_separated_nonempty_list_COMMA_function_argument_ -> "args" 325 | | N_separated_nonempty_list_COMMA_complex_type_ -> "types" 326 | | N_separated_nonempty_list_COMMA_enum_field_arg_ -> "args" 327 | | N_separated_nonempty_list_COMMA_case_expr_ -> "patterns" 328 | | N_loption_separated_nonempty_list_COMMA_enum_field_arg__ -> "args" 329 | | N_list_enum_field_ -> "enum_fields" 330 | | N_separated_nonempty_list_COMMA_complex_type_maybe_named_-> "args" 331 | end -------------------------------------------------------------------------------- /src/syntax/astEmitter.ml: -------------------------------------------------------------------------------- 1 | open Ast 2 | open Ops 3 | 4 | type 'a t_pos = 'a * Pos.Range.t 5 | type t_metadata_entry = metadata_entry 6 | type t_annotations = string option * metadata 7 | type t_path = string list 8 | type t_pos_path = placed_name list 9 | type t_literal = constant 10 | type t_const = constant 11 | 12 | type t_block_element = expr 13 | type t_object_field_name = (string * pos * Ast.quote_status) 14 | type t_object_field = (t_object_field_name * expr) 15 | type t_call_args = expr list 16 | type t_var_declaration = (placed_name * type_hint option * expr option) 17 | type t_catch = (placed_name * type_hint * expr * pos) 18 | type t_case = (expr list * expr option * expr option * pos) 19 | type t_expr = expr 20 | 21 | type t_constraint = type_hint list 22 | type t_type_path_parameter_kind = type_param_or_const 23 | type t_type_path = placed_type_path 24 | type t_complex_type = type_hint 25 | 26 | type t_function_argument = (placed_name * bool * metadata * type_hint option * expr option) 27 | type t_function = string option * func 28 | type t_field_expr = expr option 29 | type t_modifier = placed_access 30 | type t_class_field = class_field 31 | type t_enum_field_arg = (string * bool * type_hint) 32 | type t_enum_field = enum_constructor 33 | type t_anonymous_field = class_field 34 | type t_anonymous_type_fields = class_field list 35 | 36 | type t_type_decl_parameter = type_param 37 | type t_import_mode = import_mode 38 | type t_abstract_relation = abstract_flag 39 | type t_class_relation = class_flag 40 | type t_common_flag = enum_flag 41 | type t_class_flag = class_flag 42 | type t_class = (t_class_flag * string t_pos option * t_type_decl_parameter list * t_class_relation list * t_class_field list) 43 | type t_decl = type_decl 44 | type t_package = string list 45 | 46 | type t_lambda_arg = (t_expr * bool * unit list * t_complex_type option * t_expr option) * t_function_argument list 47 | 48 | let emit_path ident idents = 49 | (ident :: idents) 50 | 51 | let emit_pos_path ident idents = 52 | (ident :: idents) 53 | 54 | let emit_metadata_entry meta p = 55 | (meta,[],p) 56 | 57 | let emit_metadata_entry_with_args meta el p = 58 | (meta,el,p) 59 | 60 | let emit_function name tl args cto e = 61 | let f = { 62 | f_params = tl; 63 | f_type = cto; 64 | f_args = args; 65 | f_expr = Some e; 66 | } in 67 | name,f 68 | 69 | let emit_lambda_arg args = 70 | let rec loop acc eo e = match fst e with 71 | | EMeta(meta,e) -> loop (meta :: acc) eo e 72 | | EConst(Ident s) -> (s,snd e),eo,List.rev acc 73 | | EBinop(OpAssign,(EConst(Ident s),p),e1) -> (s,snd e),Some e1,List.rev acc 74 | | _ -> assert false 75 | in 76 | let e,opt,_,ct,eo = fst args in 77 | let e,eo,meta = loop [] eo e in 78 | let args = (e,opt,meta,ct,eo) :: (snd args) in 79 | args 80 | 81 | let emit_function2 name tl args cto e = 82 | let f = { 83 | f_params = tl; 84 | f_type = cto; 85 | f_args = args; 86 | f_expr = Some e; 87 | } in 88 | name,f 89 | 90 | let emit_annotations so metadata = 91 | (so,metadata) 92 | 93 | let emit_literal_string s = 94 | String s 95 | 96 | let emit_literal_int s = 97 | Int s 98 | 99 | let emit_literal_float s = 100 | Float s 101 | 102 | let emit_literal_regex (s1,s2) = 103 | Regexp(s1,s2) 104 | 105 | let emit_const_ident s = 106 | Ident s 107 | 108 | let emit_const_literal lit = 109 | lit 110 | 111 | let emit_call_args el = 112 | el 113 | 114 | let emit_assignment e = 115 | e 116 | 117 | let emit_var_declaration name cto eo = 118 | (name,cto,eo) 119 | 120 | let emit_catch name ct e p = 121 | (name,ct,e,p) 122 | 123 | let emit_case el1 eo el2 p = 124 | let b = match el2 with [] -> None | _ -> Some (EBlock el2,p) in 125 | (el1,eo,b,p) 126 | 127 | let emit_default el p = 128 | let b = match el with [] -> None | _ -> Some (EBlock el,p) in 129 | [EConst(Ident "_"),p],None,b,p 130 | 131 | let emit_object_field name e = 132 | (name,e) 133 | 134 | let emit_object_field_name_ident s p = 135 | s,p,NoQuotes 136 | 137 | let emit_object_field_name_string s p = 138 | s,p,DoubleQuotes 139 | 140 | let emit_unknown p = 141 | EConst(Ident "null"),p 142 | 143 | let emit_block_element_var vl p = 144 | EVars vl,p 145 | 146 | let emit_block_element_inline_function f p = 147 | EFunction(fst f,snd f),p 148 | 149 | let emit_block_element_expr e p = 150 | e 151 | 152 | let emit_this p = 153 | EConst(Ident "this"),p 154 | 155 | let emit_true p = 156 | EConst(Ident "true"),p 157 | 158 | let emit_false p = 159 | EConst(Ident "false"),p 160 | 161 | let emit_null p = 162 | EConst(Ident "null"),p 163 | 164 | let emit_block_expr el p = 165 | EBlock el,p 166 | 167 | let emit_var_declaration_expr v p = 168 | EVars [v],p 169 | 170 | let emit_metadata_expr meta e p = 171 | EMeta(meta,e),p 172 | 173 | let emit_throw_expr e p = 174 | EThrow e,p 175 | 176 | let emit_if_expr e1 e2 eo p = 177 | EIf(e1,e2,eo),p 178 | 179 | let emit_return_expr eo p = 180 | EReturn eo,p 181 | 182 | let emit_break_expr p = 183 | EBreak,p 184 | 185 | let emit_continue_expr p = 186 | EContinue,p 187 | 188 | let emit_do_expr e1 e2 p = 189 | EWhile(e1,e2,DoWhile),p 190 | 191 | let emit_try_expr e catches p = 192 | ETry(e,catches),p 193 | 194 | let emit_switch_expr e cases p = 195 | ESwitch(e,cases,None),p 196 | 197 | let emit_for_expr e1 e2 p = 198 | EFor(e1,e2),p 199 | 200 | let emit_while_expr e1 e2 p = 201 | EWhile(e1,e2,NormalWhile),p 202 | 203 | let emit_untyped_expr e p = 204 | EUntyped e,p 205 | 206 | let emit_object_decl_expr fl p = 207 | EObjectDecl fl,p 208 | 209 | let emit_unsafe_cast_expr e p = 210 | ECast(e,None),p 211 | 212 | let emit_safe_cast_expr e ct p = 213 | ECast(e,Some ct),p 214 | 215 | let emit_new_expr path el p = 216 | ENew(path,el),p 217 | 218 | let emit_parenthesis_expr e p = 219 | EParenthesis e,p 220 | 221 | let emit_typecheck_expr e ct p = 222 | ECheckType(e,ct),p 223 | 224 | let emit_is_expr e path p_is p = 225 | let t,t_p = path in 226 | let e_is = EField((EConst(Ident "Std"),Pos.Range.null),"is"),p_is in 227 | let e2 = expr_of_type_path (t.tpackage,t.tname) t_p in 228 | ECall(e_is,[e;e2]),p 229 | 230 | let emit_array_decl_expr el p = 231 | EArrayDecl el,p 232 | 233 | let emit_function_expr f p = 234 | EFunction(fst f,snd f),p 235 | 236 | let emit_unary_prefix_expr op e p = 237 | EUnop(op,Prefix,e),p 238 | 239 | let emit_field_expr e s p = 240 | EField(e,s),p 241 | 242 | let emit_call_expr e el p = 243 | ECall(e,el),p 244 | 245 | let emit_array_expr e1 e2 p = 246 | EArray(e1,e2),p 247 | 248 | let emit_binop_expr e1 op e2 p = 249 | EBinop(op,e1,e2),p 250 | 251 | let emit_unary_postfix_expr e op p = 252 | EUnop(op,Postfix,e),p 253 | 254 | let emit_ternary_expr e1 e2 e3 p = 255 | ETernary(e1,e2,e3),p 256 | 257 | let emit_in_expr e1 e2 p = 258 | EBinop(OpIn,e1,e2),p 259 | 260 | let emit_dotint_expr s p = 261 | EConst(Float(s ^ ".")),p 262 | 263 | let emit_dollarident_expr name p = 264 | EConst (Ident name),p 265 | 266 | let emit_macro_escape_expr name e p = 267 | EMeta(((Meta.Custom (fst name)),[],snd name),e),p 268 | 269 | let emit_macro_expr e p = e (* TODO *) 270 | 271 | let emit_const_expr const p = (EConst const,p) 272 | 273 | (* Type hints *) 274 | 275 | let emit_type_path path params p = 276 | match List.rev path with 277 | | [] -> assert false 278 | | name :: pack -> { tpackage = List.rev pack; tname = name; tsub = None; tparams = params },p 279 | 280 | let emit_complex_type_path path p = CTPath (fst path),p 281 | let emit_complex_type_parent ct p = CTParent ct,p 282 | let emit_complex_type_extension paths fields p = CTExtend(paths,fields),p 283 | let emit_complex_type_anonymous fields p = CTAnonymous fields,p 284 | let emit_complex_type_optional ct p = CTOptional ct,p 285 | 286 | let emit_complex_type_function ct1 ct2 p = 287 | match fst ct2 with 288 | | CTFunction (args,r) -> 289 | CTFunction (ct1 :: args,r),p 290 | | _ -> 291 | CTFunction ([ct1],ct2),p 292 | 293 | let emit_complex_type_named n ct p = CTNamed(n,ct),p 294 | 295 | let emit_complex_type_named_function ctl ct p = CTFunction(ctl,ct),p 296 | 297 | let emit_type_path_parameter_complex_type ct = 298 | TPType ct 299 | 300 | let emit_type_path_parameter_bracket el p = 301 | TPExpr (EArrayDecl el,p) 302 | 303 | let emit_type_path_parameter_literal lit p = 304 | TPExpr (EConst lit,p) 305 | 306 | let emit_type_path_parameter_bool b p = 307 | TPExpr (EConst(Ident (if b then "true" else "false")),p) 308 | 309 | (* Fields *) 310 | 311 | let emit_function_argument annotations opt name cto eo = 312 | (name,(match opt with None -> false | Some _ -> true),snd annotations,cto,eo) 313 | 314 | let emit_field_expr_none = None 315 | let emit_field_expr_block e = Some e 316 | let emit_field_expr_expr e = Some e 317 | 318 | let emit_static_modifier p = AStatic,p 319 | let emit_macro_modifier p = AMacro,p 320 | let emit_public_modifier p = APublic,p 321 | let emit_private_modifier p = APrivate,p 322 | let emit_override_modifier p = AOverride,p 323 | let emit_dynamic_modifier p = ADynamic,p 324 | let emit_inline_modifier p = AInline,p 325 | let emit_extern_modifier p = AExtern,p 326 | 327 | let emit_function_field annotations modifiers name tl args cto e p = 328 | let f = { 329 | f_params = tl; 330 | f_args = args; 331 | f_type = cto; 332 | f_expr = e; 333 | } in 334 | let cff = { 335 | cff_name = name; 336 | cff_doc = fst annotations; 337 | cff_pos = p; 338 | cff_meta = snd annotations; 339 | cff_access = modifiers; 340 | cff_kind = FFun f 341 | } in 342 | cff 343 | 344 | let emit_variable_field annotations modifiers name cto eo p = 345 | let cff = { 346 | cff_name = name; 347 | cff_doc = fst annotations; 348 | cff_pos = p; 349 | cff_meta = snd annotations; 350 | cff_access = modifiers; 351 | cff_kind = FVar(cto,eo); 352 | } in 353 | cff 354 | 355 | let emit_property_field annotations modifiers name get set cto eo p = 356 | let cff = { 357 | cff_name = name; 358 | cff_doc = fst annotations; 359 | cff_pos = p; 360 | cff_meta = snd annotations; 361 | cff_access = modifiers; 362 | cff_kind = FProp(get,set,cto,eo); 363 | } in 364 | cff 365 | 366 | let emit_enum_field_arg opt name ct = 367 | (name,(match opt with None -> false | Some _ -> true),ct) 368 | 369 | let emit_enum_field annotations name tl args cto p = 370 | let ef = { 371 | ec_name = name; 372 | ec_doc = fst annotations; 373 | ec_meta = snd annotations; 374 | ec_args = args; 375 | ec_params = tl; 376 | ec_type = cto; 377 | ec_pos = p; 378 | } in 379 | ef 380 | 381 | let emit_anonymous_class_fields fields = fields 382 | let emit_anonymous_type_fields fields = fields 383 | 384 | let emit_anonymous_type_field opt name ct p = 385 | let cff = { 386 | cff_name = name; 387 | cff_meta = (match opt with None -> [] | Some _ -> [Meta.Optional,[],Pos.Range.null]); 388 | cff_access = []; 389 | cff_doc = None; 390 | cff_kind = FVar(Some ct,None); 391 | cff_pos = p; 392 | } in 393 | cff 394 | 395 | (* Type declaration *) 396 | 397 | let emit_constraints_none = [] 398 | 399 | let emit_constraints_single ct = [ct] 400 | 401 | let emit_constraints_multiple ctl = ctl 402 | 403 | let emit_type_decl_parameter annotations name constraints = { 404 | tp_name = name; 405 | tp_params = []; (* TODO! *) 406 | tp_constraints = constraints; 407 | tp_meta = snd annotations; 408 | } 409 | 410 | let emit_class_flag_interface = HInterface 411 | 412 | let emit_class_flag_class = HInterface (* TODO! *) 413 | 414 | let emit_common_flag_extern = EExtern 415 | 416 | let emit_common_flag_private = EPrivate 417 | 418 | let emit_class_relation_extends path = HExtends path 419 | 420 | let emit_class_relation_implements path = HImplements path 421 | 422 | let emit_abstract_relation_from ct = AbFrom ct 423 | 424 | let emit_abstract_relation_to ct = AbTo ct 425 | 426 | let emit_import_mode_all = IAll 427 | 428 | let emit_import_mode_alias name = IAsName name 429 | 430 | let emit_import_mode_normal = INormal 431 | 432 | let emit_import path mode p = 433 | (EImport (path,mode),p) 434 | 435 | let emit_using path p = 436 | (EUsing path,p) 437 | 438 | let emit_class flags name tl rl l = 439 | (flags,name,tl,rl,l) 440 | 441 | let emit_class_decl annotations flags c p = 442 | let (flags2,name,tl,rl,l) = c in 443 | let flags = List.map (function 444 | | EPrivate -> HPrivate 445 | | EExtern -> HExtern 446 | ) flags in 447 | let def = { 448 | d_name = (match name with None -> "",p (* TODO: syntax error... *) | Some name -> name); 449 | d_doc = fst annotations; 450 | d_params = tl; 451 | d_meta = snd annotations; 452 | d_flags = flags2 :: flags @ rl; 453 | d_data = l; 454 | } in 455 | (EClass def,p) 456 | 457 | let emit_enum_decl annotations flags name tl l p = 458 | let def = { 459 | d_name = name; 460 | d_doc = fst annotations; 461 | d_params = tl; 462 | d_meta = snd annotations; 463 | d_flags = flags; 464 | d_data = l; 465 | } in 466 | (EEnum def,p) 467 | 468 | let emit_typedef_decl annotations flags name tl ct p = 469 | let def = { 470 | d_name = name; 471 | d_doc = fst annotations; 472 | d_params = tl; 473 | d_meta = snd annotations; 474 | d_flags = flags; 475 | d_data = ct 476 | } in 477 | (ETypedef def,p) 478 | 479 | let emit_abstract_decl annotations flags name tl st rl l p = 480 | let flags = List.map (fun c -> match c with EPrivate -> AbPrivate | EExtern -> AbExtern) flags in 481 | let flags = (match st with None -> flags | Some t -> AbOver t :: flags) in 482 | let def = { 483 | d_name = name; 484 | d_doc = fst annotations; 485 | d_params = tl; 486 | d_meta = snd annotations; 487 | d_flags = flags @ rl; 488 | d_data = l; 489 | } in 490 | (EAbstract def,p) 491 | 492 | let emit_package path = match path with 493 | | None -> [] 494 | | Some path -> path -------------------------------------------------------------------------------- /src/syntax/lexing/lexer.ml: -------------------------------------------------------------------------------- 1 | (* 2 | The Haxe Compiler 3 | Copyright (C) 2005-2016 Haxe Foundation 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 2 7 | of the License, or (at your option) any later version. 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 15 | *) 16 | 17 | open Sedlex_menhir 18 | open Tokens 19 | 20 | exception Unclosed of string 21 | 22 | let ident_lc = [%sedlex.regexp? 23 | ( 24 | Star '_', 25 | 'a'..'z', 26 | Star ('_' | 'a'..'z' | 'A'..'Z' | '0'..'9') 27 | ) 28 | | 29 | Plus '_' 30 | | 31 | ( 32 | Plus '_', 33 | '0'..'9', 34 | Star ('_' | 'a'..'z' | 'A'..'Z' | '0'..'9') 35 | ) 36 | ] 37 | 38 | let ident_uc = [%sedlex.regexp? Star '_', 'A'..'Z', Star ('_' | 'a'..'z' | 'A'..'Z' | '0'..'9')] 39 | 40 | let ident = [%sedlex.regexp? ident_lc | ident_uc ] 41 | 42 | let integer = [%sedlex.regexp? ('1'..'9', Star ('0'..'9')) | '0'] 43 | 44 | let metadata_ident = [%sedlex.regexp? Opt ':',ident,Star ('.',ident) ] 45 | 46 | let dollar_ident = [%sedlex.regexp? '$',Opt (ident | integer)] 47 | 48 | let dot_ident = [%sedlex.regexp? '.',(dollar_ident | ident)] 49 | 50 | let rec skip_header lexbuf = 51 | let buf = lexbuf.stream in 52 | match%sedlex buf with 53 | | 0xfeff -> skip_header lexbuf 54 | | "#!", Star (Compl ('\n' | '\r')) -> skip_header lexbuf 55 | | "" | eof -> () 56 | | _ -> assert false 57 | 58 | let skip1 s = String.sub s 1 (String.length s - 1) 59 | 60 | let rec preprocessor lexbuf = 61 | let buf = lexbuf.stream in 62 | match%sedlex buf with 63 | | eof -> update lexbuf; EOF 64 | | "#if" -> update lexbuf; SHARPIF 65 | | "#else" -> update lexbuf; SHARPELSE 66 | | "#elseif" -> update lexbuf; SHARPELSEIF 67 | | "#end" -> update lexbuf; SHARPEND 68 | | "\n" | "\r\n" -> update lexbuf; new_line lexbuf; NEWLINE (lexeme lexbuf) 69 | | Plus (Compl ('#' | '\n' | '\r' | '/' | '"' | '~' | '\'')) -> update lexbuf; WHITESPACE (lexeme lexbuf) 70 | | "//", Star (Compl ('\n' | '\r')) -> update lexbuf; WHITESPACE (lexeme lexbuf) 71 | | '/' | '#' | '~' -> update lexbuf; WHITESPACE (lexeme lexbuf) 72 | | "\"" -> update lexbuf; WHITESPACE("\"" ^ (try string (Buffer.create 0) lexbuf with Unclosed s -> s) ^ "\"") 73 | | "\'" -> update lexbuf; WHITESPACE("'" ^ (try string2 (Buffer.create 0) lexbuf with Unclosed s -> s) ^ "'") 74 | | "/*" -> update lexbuf; WHITESPACE("/*" ^ (try comment (Buffer.create 0) lexbuf with Unclosed s -> s) ^ "*/") 75 | | "~/" -> 76 | update lexbuf; 77 | let s1,s2 = try regexp (Buffer.create 0) lexbuf with Unclosed s -> s,"" in 78 | WHITESPACE("~/" ^ s1 ^ "/" ^ s2) 79 | | any -> update lexbuf; NONSENSE (lexeme lexbuf) 80 | | _ -> assert false 81 | 82 | and token lexbuf = 83 | let buf = lexbuf.stream in 84 | match%sedlex buf with 85 | (* whitespace *) 86 | | eof -> update lexbuf; EOF 87 | | Plus (Chars " \t\r") -> update lexbuf; WHITESPACE (lexeme lexbuf) 88 | | "\n" | "\r\n" -> update lexbuf; new_line lexbuf; NEWLINE (lexeme lexbuf) 89 | | "//", Star (Compl ('\n' | '\r')) -> 90 | let s = lexeme lexbuf in 91 | update lexbuf; 92 | COMMENTLINE (String.sub s 2 ((String.length s)-2)) 93 | (* numbers *) 94 | | "0x", Plus ('0'..'9'|'a'..'f'|'A'..'F') -> update lexbuf; INT (lexeme lexbuf) 95 | | integer -> update lexbuf; INT (lexeme lexbuf) 96 | | integer, '.', Plus '0'..'9' -> update lexbuf; FLOAT (lexeme lexbuf) 97 | | '.', Plus '0'..'9' -> update lexbuf; FLOAT (lexeme lexbuf) 98 | | integer, ('e'|'E'), Opt ('+'|'-'), Plus '0'..'9' -> update lexbuf; FLOAT (lexeme lexbuf) 99 | | integer, '.', Star '0'..'9', ('e'|'E'), Opt ('+'|'-'), Plus '0'..'9' -> update lexbuf; FLOAT (lexeme lexbuf) 100 | (* keywords *) 101 | | "package" -> update lexbuf; PACKAGE 102 | | "import" -> update lexbuf; IMPORT 103 | | "using" -> update lexbuf; USING 104 | | "class" -> update lexbuf; CLASS 105 | | "interface" -> update lexbuf; INTERFACE 106 | | "enum" -> update lexbuf; ENUM 107 | | "typedef" -> update lexbuf; TYPEDEF 108 | | "abstract" -> update lexbuf; ABSTRACT 109 | | "private" -> update lexbuf; PRIVATE 110 | | "public" -> update lexbuf; PUBLIC 111 | | "static" -> update lexbuf; STATIC 112 | | "inline" -> update lexbuf; INLINE 113 | | "extern" -> update lexbuf; EXTERN 114 | | "macro" -> update lexbuf; MACRO 115 | | "override" -> update lexbuf; OVERRIDE 116 | | "dynamic" -> update lexbuf; DYNAMIC 117 | | "function" -> update lexbuf; FUNCTION 118 | | "extends" -> update lexbuf; EXTENDS 119 | | "implements" -> update lexbuf; IMPLEMENTS 120 | | "var" -> update lexbuf; VAR 121 | | "cast" -> update lexbuf; CAST 122 | | "throw" -> update lexbuf; THROW 123 | | "new" -> update lexbuf; NEW 124 | | "if" -> update lexbuf; IF 125 | | "else" -> update lexbuf; ELSE 126 | | "while" -> update lexbuf; WHILE 127 | | "do" -> update lexbuf; DO 128 | | "for" -> update lexbuf; FOR 129 | | "try" -> update lexbuf; TRY 130 | | "catch" -> update lexbuf; CATCH 131 | | "return" -> update lexbuf; RETURN 132 | | "break" -> update lexbuf; BREAK 133 | | "continue" -> update lexbuf; CONTINUE 134 | | "switch" -> update lexbuf; SWITCH 135 | | "case" -> update lexbuf; CASE 136 | | "default" -> update lexbuf; DEFAULT 137 | | "untyped" -> update lexbuf; UNTYPED 138 | | "this" -> update lexbuf; THIS 139 | | "true" -> update lexbuf; TRUE 140 | | "false" -> update lexbuf; FALSE 141 | | "null" -> update lexbuf; NULL 142 | | "in" -> update lexbuf; IN 143 | | "from" -> update lexbuf; FROM 144 | | "to" -> update lexbuf; TO 145 | | "as" -> update lexbuf; AS 146 | | "is" -> update lexbuf; IS 147 | | "final" -> update lexbuf; FINAL 148 | (* punctuation *) 149 | | ":" -> update lexbuf; COLON 150 | | ";" -> update lexbuf; SEMICOLON 151 | | "," -> update lexbuf; COMMA 152 | | "{" -> update lexbuf; BROPEN 153 | | "}" -> update lexbuf; BRCLOSE 154 | | "(" -> update lexbuf; POPEN 155 | | ")" -> update lexbuf; PCLOSE 156 | | "[" -> update lexbuf; BKOPEN 157 | | "]" -> update lexbuf; BKCLOSE 158 | | "?" -> update lexbuf; QUESTIONMARK 159 | | ".*" -> update lexbuf; DOTSTAR 160 | | "." -> update lexbuf; DOT 161 | (* ops *) 162 | | "++" -> update lexbuf; INCREMENT 163 | | "--" -> update lexbuf; DECREMENT 164 | | "~" -> update lexbuf; TILDE 165 | | "%=" -> update lexbuf; ASSIGNMOD 166 | | "&=" -> update lexbuf; ASSIGNAND 167 | | "|=" -> update lexbuf; ASSIGNOR 168 | | "^=" -> update lexbuf; ASSIGNXOR 169 | | "+=" -> update lexbuf; ASSIGNPLUS 170 | | "-=" -> update lexbuf; ASSIGNMINUS 171 | | "*=" -> update lexbuf; ASSIGNSTAR 172 | | "/=" -> update lexbuf; ASSIGNSLASH 173 | | "<<=" -> update lexbuf; ASSIGNSHL 174 | | ">>=" -> update lexbuf; ASSIGNSHR 175 | | ">>>=" -> update lexbuf; ASSIGNUSHR 176 | | "||=" -> update lexbuf; ASSIGNBOOLOR 177 | | "&&=" -> update lexbuf; ASSIGNBOOLAND 178 | | "==" -> update lexbuf; EQUALS 179 | | "!=" -> update lexbuf; NOTEQUALS 180 | | "<=" -> update lexbuf; LTE 181 | | ">=" -> update lexbuf; GTE 182 | | "<" -> update lexbuf; LT 183 | | ">" -> update lexbuf; GT 184 | | "&&" -> update lexbuf; BOOLAND 185 | | "||" -> update lexbuf; BOOLOR 186 | | "<<" -> update lexbuf; SHL 187 | | ">>" -> update lexbuf; SHR 188 | | ">>>" -> update lexbuf; USHR 189 | | "->" -> update lexbuf; ARROW 190 | | "..." -> update lexbuf; INTERVAL 191 | | "=>" -> update lexbuf; DOUBLEARROW 192 | | "!" -> update lexbuf; EXCLAMATION 193 | | "%" -> update lexbuf; PERCENT 194 | | "&" -> update lexbuf; AND 195 | | "|" -> update lexbuf; OR 196 | | "^" -> update lexbuf; XOR 197 | | "=" -> update lexbuf; ASSIGN 198 | | "+" -> update lexbuf; PLUS 199 | | "-" -> update lexbuf; MINUS 200 | | "*" -> update lexbuf; STAR 201 | | "/" -> update lexbuf; SLASH 202 | (* sequences *) 203 | | "\"" -> (try STRING (string (Buffer.create 0) lexbuf) with Unclosed s -> UNCLOSED (STRING s)); 204 | | "\'" -> (try STRING2 (string2 (Buffer.create 0) lexbuf) with Unclosed s -> UNCLOSED (STRING2 s)); 205 | | "/*" -> (try COMMENT (comment (Buffer.create 0) lexbuf) with Unclosed s -> UNCLOSED (COMMENT s)); 206 | | "~/" -> (try REGEX (regexp (Buffer.create 0) lexbuf) with Unclosed s -> REGEX(s,"")) 207 | | '@',metadata_ident -> update lexbuf; METADATA (skip1 (lexeme lexbuf)) 208 | | '@',metadata_ident,"(" -> update lexbuf; METADATA_OPEN (let s = lexeme lexbuf in String.sub s 1 (String.length s - 2)) 209 | | ident -> update lexbuf; IDENT (lexeme lexbuf) 210 | | dollar_ident -> update lexbuf; DOLLAR_IDENT (skip1 (lexeme lexbuf)) 211 | | dot_ident -> update lexbuf; DOT_IDENT (skip1 (lexeme lexbuf)) 212 | (* preprocessor *) 213 | | "#if" -> update lexbuf; SHARPIF 214 | | "#else" -> update lexbuf; SHARPELSE 215 | | "#elseif" -> update lexbuf; SHARPELSEIF 216 | | "#end" -> update lexbuf; SHARPEND 217 | | "#error" -> update lexbuf; SHARPERROR 218 | | "#line" -> update lexbuf; SHARPLINE 219 | | any -> update lexbuf; NONSENSE (lexeme lexbuf) 220 | | _ -> assert false (* should not happen *) 221 | 222 | and string buffer lexbuf = 223 | let store () = Buffer.add_string buffer (lexeme lexbuf) in 224 | let buf = lexbuf.stream in 225 | match%sedlex buf with 226 | | eof -> raise (Unclosed (Buffer.contents buffer)); 227 | | '\n' | '\r' | "\r\n" -> new_line lexbuf; store(); string buffer lexbuf 228 | | "\\\"" -> store(); string buffer lexbuf 229 | | "\\\\" -> store(); string buffer lexbuf 230 | | '\\' -> store(); string buffer lexbuf 231 | | '"' -> update lexbuf; Buffer.contents buffer 232 | | Plus (Compl ('"' | '\\' | '\r' | '\n')) -> store(); string buffer lexbuf 233 | | _ -> assert false 234 | 235 | and string2 buffer lexbuf = 236 | let store () = Buffer.add_string buffer (lexeme lexbuf) in 237 | let buf = lexbuf.stream in 238 | match%sedlex buf with 239 | | eof -> raise (Unclosed (Buffer.contents buffer)); 240 | | '\n' | '\r' | "\r\n" -> new_line lexbuf; store(); string2 buffer lexbuf 241 | | '\\' -> store(); string2 buffer lexbuf 242 | | "\\\\" -> store(); string2 buffer lexbuf 243 | | "\\'" -> store(); string2 buffer lexbuf 244 | | "'" -> update lexbuf; Buffer.contents buffer 245 | | "$$" | "\\$" | '$' -> store(); string2 buffer lexbuf 246 | | "${" -> 247 | store(); 248 | let s = code_string (Buffer.create 0) 0 lexbuf in 249 | Buffer.add_string buffer s; 250 | string2 buffer lexbuf 251 | | Plus (Compl ('\'' | '\\' | '\r' | '\n' | '$')) -> store(); string2 buffer lexbuf 252 | | _ -> assert false 253 | 254 | and code_string buffer open_braces lexbuf = 255 | let add s = Buffer.add_string buffer s in 256 | let store () = add (lexeme lexbuf) in 257 | let buf = lexbuf.stream in 258 | match%sedlex buf with 259 | | eof -> raise (Unclosed (Buffer.contents buffer)); 260 | | '\n' | '\r' | "\r\n" -> new_line lexbuf; store(); code_string buffer open_braces lexbuf 261 | | '{' -> store(); code_string buffer (open_braces + 1) lexbuf 262 | | '/' -> store(); code_string buffer open_braces lexbuf 263 | | '}' -> 264 | store(); 265 | if open_braces = 0 then 266 | Buffer.contents buffer 267 | else 268 | code_string buffer (open_braces - 1) lexbuf 269 | | '"' -> 270 | add "\""; 271 | let s = (try string (Buffer.create 0) lexbuf with Unclosed s -> s) in 272 | add s; 273 | add "\""; 274 | code_string buffer open_braces lexbuf 275 | | "'" -> 276 | add "'"; 277 | let s = (try string2 (Buffer.create 0) lexbuf with Unclosed s -> s) in 278 | add s; 279 | add "'"; 280 | code_string buffer open_braces lexbuf 281 | | "/*" -> 282 | let s = (try string (Buffer.create 0) lexbuf with Unclosed s -> s) in 283 | add s; 284 | code_string buffer open_braces lexbuf 285 | | "//", Star (Compl ('\n' | '\r')) -> store(); code_string buffer open_braces lexbuf 286 | | Plus (Compl ('/' | '"' | '\'' | '{' | '}' | '\n' | '\r')) -> store(); code_string buffer open_braces lexbuf 287 | | _ -> assert false 288 | 289 | and comment buffer lexbuf = 290 | let store () = Buffer.add_string buffer (lexeme lexbuf) in 291 | let buf = lexbuf.stream in 292 | match%sedlex buf with 293 | | eof -> raise (Unclosed (Buffer.contents buffer)); 294 | | '\n' | '\r' | "\r\n" -> new_line lexbuf; store(); comment buffer lexbuf 295 | | "*/" -> update lexbuf; Buffer.contents buffer 296 | | '*' -> store(); comment buffer lexbuf 297 | | Plus (Compl ('*' | '\n' | '\r')) -> store(); comment buffer lexbuf 298 | | _ -> assert false 299 | 300 | and regexp buffer lexbuf = 301 | let add s = Buffer.add_string buffer s in 302 | let store () = add (lexeme lexbuf) in 303 | let buf = lexbuf.stream in 304 | match%sedlex buf with 305 | | eof | '\n' | '\r' -> raise (Unclosed (Buffer.contents buffer)); 306 | | '\\', '/' -> add "/"; regexp buffer lexbuf 307 | | '\\', 'r' -> add "\r"; regexp buffer lexbuf 308 | | '\\', 'n' -> add "\n"; regexp buffer lexbuf 309 | | '\\', 't' -> add "\t"; regexp buffer lexbuf 310 | | '\\', ('\\' | '$' | '.' | '*' | '+' | '^' | '|' | '{' | '}' | '[' | ']' | '(' | ')' | '?' | '-' | '0'..'9') -> store(); regexp buffer lexbuf 311 | | '\\', ('w' | 'W' | 'b' | 'B' | 's' | 'S' | 'd' | 'D' | 'x') -> store(); regexp buffer lexbuf 312 | | '\\', ('u' | 'U'), ('0'..'9' | 'a'..'f' | 'A'..'F'), ('0'..'9' | 'a'..'f' | 'A'..'F'), ('0'..'9' | 'a'..'f' | 'A'..'F'), ('0'..'9' | 'a'..'f' | 'A'..'F') -> store(); regexp buffer lexbuf 313 | (*| '\\', Compl '\\' -> error (Invalid_character (lexeme_char lexbuf 0)) (lexeme_end lexbuf - 1)*) 314 | | '/' -> Buffer.contents buffer,regexp_options lexbuf 315 | | Plus (Compl ('\\' | '/' | '\r' | '\n')) -> store(); regexp buffer lexbuf 316 | | _ -> assert false 317 | 318 | and regexp_options lexbuf = 319 | let buf = lexbuf.stream in 320 | match%sedlex buf with 321 | | 'g' | 'i' | 'm' | 's' | 'u' -> 322 | let l = lexeme lexbuf in 323 | l ^ regexp_options lexbuf 324 | (*| 'a'..'z' -> error Invalid_option (lexeme_start lexbuf)*) 325 | | "" -> "" 326 | | _ -> assert false -------------------------------------------------------------------------------- /src/syntax/jsonEmitter.ml: -------------------------------------------------------------------------------- 1 | module type JsonApi = sig 2 | type t 3 | val jarray : t list -> t 4 | val jobject : (string * t) list -> t 5 | val jbool : bool -> t 6 | val jstring : string -> t 7 | val jint : int -> t 8 | val jnull : t 9 | end 10 | 11 | module EnumApi = struct 12 | type enum_api = 13 | | NIdent 14 | | NString 15 | 16 | | PConstIdent 17 | | PConstLiteral 18 | 19 | | Var 20 | | InlineFunction 21 | | Expr 22 | 23 | | Case 24 | | Default 25 | 26 | | EVar 27 | | EMetadata 28 | | EMacro 29 | | EThrow 30 | | EIf 31 | | EReturn 32 | | EReturnExpr 33 | | EBreak 34 | | EContinue 35 | | EDo 36 | | ETry 37 | | ESwitch 38 | | EFor 39 | | EWhile 40 | | EUntyped 41 | | EObjectDecl 42 | | EConst 43 | | EUnsafeCast 44 | | ESafeCast 45 | | ENew 46 | | EParenthesis 47 | | ECheckType 48 | | EIs 49 | | EArrayDecl 50 | | EFunction 51 | | EUnaryPrefix 52 | | EField 53 | | ECall 54 | | EArrayAccess 55 | | EUnaryPostfix 56 | | EBinop 57 | | ETernary 58 | | EIn 59 | | EIntDot 60 | | EDollarIdent 61 | | EMacroEscape 62 | | EBlock 63 | 64 | | Simple 65 | | WithArgs 66 | 67 | | PPrivate 68 | | PExtern 69 | 70 | | PLiteralString 71 | | PLiteralInt 72 | | PLiteralFloat 73 | | PLiteralRegex 74 | 75 | | ArrayExpr 76 | | Type 77 | | Literal 78 | 79 | | Static 80 | | Macro 81 | | Public 82 | | Private 83 | | Override 84 | | Dynamic 85 | | Inline 86 | 87 | | MNone 88 | | MBlock 89 | | MExpr 90 | 91 | | Function 92 | | Variable 93 | | Property 94 | 95 | | ClassNotation 96 | | ShortNotation 97 | 98 | | Parenthesis 99 | | StructuralExtension 100 | | AnonymousStructure 101 | | Optional 102 | | TypePath 103 | | CTFunction 104 | 105 | | CMultiple 106 | | CSingle 107 | | CNone 108 | 109 | | Extends 110 | | Implements 111 | 112 | | To 113 | | From 114 | 115 | | IAs 116 | | IAll 117 | | INormal 118 | 119 | | ImportDecl 120 | | UsingDecl 121 | | ClassDecl 122 | | EnumDecl 123 | | TypedefDecl 124 | | AbstractDecl 125 | 126 | let info = function 127 | | NIdent -> 0,"NIdent" 128 | | NString -> 1,"NString" 129 | 130 | | PConstIdent -> 0,"PConstIdent" 131 | | PConstLiteral -> 1,"PConstLiteral" 132 | 133 | | Var -> 0,"Var" 134 | | InlineFunction -> 1,"InlineFunction" 135 | | Expr -> 2,"Expr" 136 | 137 | | Case -> 0,"Case" 138 | | Default -> 1,"Default" 139 | 140 | | EVar -> 0,"EVar" 141 | | EMetadata -> 1,"EMetadata" 142 | | EMacro -> 2,"EMacro" 143 | | EThrow -> 3,"EThrow" 144 | | EIf -> 4,"EIf" 145 | | EReturn -> 5,"EReturn" 146 | | EReturnExpr -> 6,"EReturnExpr" 147 | | EBreak -> 7,"EBreak" 148 | | EContinue -> 8,"EContinue" 149 | | EDo -> 9,"EDo" 150 | | ETry -> 10,"ETry" 151 | | ESwitch -> 11,"ESwitch" 152 | | EFor -> 12,"EFor" 153 | | EWhile -> 13,"EWhile" 154 | | EUntyped -> 14,"EUntyped" 155 | | EObjectDecl -> 15,"EObjectDecl" 156 | | EConst -> 16,"EConst" 157 | | EUnsafeCast -> 17,"EUnsafeCast" 158 | | ESafeCast -> 18,"ESafeCast" 159 | | ENew -> 19,"ENew" 160 | | EParenthesis -> 20,"EParenthesis" 161 | | ECheckType -> 21,"ECheckType" 162 | | EIs -> 22,"EIs" 163 | | EArrayDecl -> 23,"EArrayDecl" 164 | | EFunction -> 24,"EFunction" 165 | | EUnaryPrefix -> 25,"EUnaryPrefix" 166 | | EField -> 26,"EField" 167 | | ECall -> 27,"ECall" 168 | | EArrayAccess -> 28,"EArrayAccess" 169 | | EUnaryPostfix -> 29,"EUnaryPostfix" 170 | | EBinop -> 30,"EBinop" 171 | | ETernary -> 31,"ETernary" 172 | | EIn -> 32,"EIn" 173 | | EIntDot -> 33,"EIntDot" 174 | | EDollarIdent -> 34,"EDollarIdent" 175 | | EMacroEscape -> 35,"EMacroEscape" 176 | | EBlock -> 36,"EBlock" 177 | 178 | | Simple -> 0,"Simple" 179 | | WithArgs -> 1,"WithArgs" 180 | 181 | | PPrivate -> 0,"PPrivate" 182 | | PExtern -> 1,"PExtern" 183 | 184 | | PLiteralString -> 0,"PLiteralString" 185 | | PLiteralInt -> 1,"PLiteralInt" 186 | | PLiteralFloat -> 2,"PLiteralFloat" 187 | | PLiteralRegex -> 3,"PLiteralRegex" 188 | 189 | | ArrayExpr -> 0,"ArrayExpr" 190 | | Type -> 1,"Type" 191 | | Literal -> 2,"Literal" 192 | 193 | | Static -> 0,"Static" 194 | | Macro -> 1,"Macro" 195 | | Public -> 2,"Public" 196 | | Private -> 3,"Private2" 197 | | Override -> 4,"Override" 198 | | Dynamic -> 5,"Dynamic" 199 | | Inline -> 6,"Inline" 200 | 201 | | MNone -> 0,"None" 202 | | MBlock -> 1,"Block" 203 | | MExpr -> 2,"Expr" 204 | 205 | | Function -> 0,"Function" 206 | | Variable -> 1,"Variable" 207 | | Property -> 2,"Property" 208 | 209 | | ClassNotation -> 0,"ClassNotation" 210 | | ShortNotation -> 1,"ShortNotation" 211 | 212 | | Parenthesis -> 0,"Parenthesis" 213 | | StructuralExtension -> 1,"StructuralExtension" 214 | | AnonymousStructure -> 2,"AnonymousStructure" 215 | | Optional -> 3,"Optional" 216 | | TypePath -> 4,"TypePath" 217 | | CTFunction -> 5,"Function" 218 | 219 | | CMultiple -> 0,"Multiple" 220 | | CSingle -> 1,"Single" 221 | | CNone -> 2,"None" 222 | 223 | | Extends -> 0,"Extends" 224 | | Implements -> 1,"Implements" 225 | 226 | | To -> 0,"To" 227 | | From -> 1,"From" 228 | 229 | | IAs -> 0,"IAs" 230 | | IAll -> 1,"IAll" 231 | | INormal -> 2,"INormal" 232 | 233 | | ImportDecl -> 0,"ImportDecl" 234 | | UsingDecl -> 1,"UsingDecl" 235 | | ClassDecl -> 2,"ClassDecl" 236 | | EnumDecl -> 3,"EnumDecl" 237 | | TypedefDecl -> 4,"TypedefDecl" 238 | | AbstractDecl -> 5,"AbstractDecl" 239 | end 240 | 241 | module JsonEmitter(Api : JsonApi) = struct 242 | open EnumApi 243 | 244 | type 'a t_pos = 'a * Pos.Range.t 245 | type t_metadata_entry = Api.t 246 | type t_annotations = Api.t 247 | type t_path = Api.t 248 | type t_pos_path = Api.t 249 | type t_literal = Api.t 250 | type t_const = Api.t 251 | 252 | type t_block_element = Api.t 253 | type t_object_field_name = Api.t 254 | type t_object_field = Api.t 255 | type t_call_args = Api.t 256 | type t_var_declaration = Api.t 257 | type t_catch = Api.t 258 | type t_case = Api.t 259 | type t_expr = Api.t 260 | 261 | type t_constraint = Api.t 262 | type t_type_path_parameter_kind = Api.t 263 | type t_type_path = Api.t 264 | type t_complex_type = Api.t 265 | 266 | type t_function_argument = Api.t 267 | type t_function = Api.t 268 | type t_field_expr = Api.t 269 | type t_modifier = Api.t 270 | type t_function_name = Api.t 271 | type t_property_ident = Api.t 272 | type t_class_field = Api.t 273 | type t_enum_field_arg = Api.t 274 | type t_enum_field = Api.t 275 | type t_anonymous_field = Api.t 276 | type t_anonymous_type_fields = Api.t 277 | 278 | type t_type_decl_parameter = Api.t 279 | type t_import_mode = Api.t 280 | type t_abstract_relation = Api.t 281 | type t_class_relation = Api.t 282 | type t_common_flag = Api.t 283 | type t_class_flag = Api.t 284 | type t_class = Api.t 285 | type t_decl = Api.t 286 | type t_package = Api.t 287 | 288 | let enum enum_name constructor arguments = 289 | let index,name = EnumApi.info constructor in 290 | Api.jarray ((Api.jint (index)) :: (Api.jstring name) :: arguments) 291 | 292 | let opt = function 293 | | None -> Api.jnull 294 | | Some t -> t 295 | 296 | let tok = Api.jnull 297 | let arr = Api.jarray 298 | let str = Api.jstring 299 | 300 | let arropt = function 301 | | [] -> Api.jnull 302 | | l -> arr l 303 | 304 | let emit_path ident idents = 305 | Api.jobject [ 306 | "ident",str ident; 307 | "idents",arr (List.map str idents); 308 | ] 309 | 310 | let emit_pos_path ident idents = 311 | emit_path (fst ident) (List.map fst idents) 312 | 313 | let emit_metadata_entry meta p = 314 | enum "Metadata" Simple [tok] 315 | 316 | let emit_metadata_entry_with_args meta el p = 317 | enum "Metadata" WithArgs [tok;arr el;tok] 318 | 319 | let emit_function name tl args cto e = 320 | Api.jobject [ 321 | "params",arropt tl; 322 | "args",arropt args; 323 | "typeHint",opt cto; 324 | "expr",e 325 | ] 326 | 327 | let emit_annotations so metadata = 328 | Api.jobject [ 329 | "doc",(match so with None -> Api.jnull | Some s -> str s); 330 | "metadata",arr metadata; 331 | ] 332 | 333 | let emit_literal_string s = 334 | enum "Literal" PLiteralString [str s] 335 | 336 | let emit_literal_int s = 337 | enum "Literal" PLiteralInt [str s] 338 | 339 | let emit_literal_float s = 340 | enum "Literal" PLiteralFloat [str s] 341 | 342 | let emit_literal_regex (s1,s2) = 343 | enum "Literal" PLiteralRegex [str s1;str s2] 344 | 345 | let emit_const_ident s = 346 | enum "NConst" PConstIdent [str s] 347 | 348 | let emit_const_literal lit = 349 | enum "NConst" PConstLiteral [lit] 350 | 351 | let emit_call_args el = 352 | Api.jobject [ 353 | "args",arr el; 354 | ] 355 | 356 | let emit_assignment e = 357 | Api.jobject [ 358 | "expr",e 359 | ] 360 | 361 | let emit_var_declaration name cto eo = 362 | Api.jobject [ 363 | "name",str (fst name); 364 | "typeHint",opt cto; 365 | "assignment",opt eo 366 | ] 367 | 368 | let emit_catch name ct e p = 369 | Api.jobject [ 370 | "typeHint",ct; 371 | "expr",e; 372 | ] 373 | 374 | let emit_case el1 eo el2 p = 375 | enum "Case" Case [tok;arr el1;opt eo;tok;arr el2] 376 | 377 | let emit_default el p = 378 | enum "Case" Default [tok;tok;arr el] 379 | 380 | let emit_object_field name e = 381 | Api.jobject [ 382 | "name",name; 383 | "expr",e 384 | ] 385 | 386 | let emit_object_field_name_ident s p = 387 | enum "ObjectFieldName" NIdent [str s] 388 | 389 | let emit_object_field_name_string s p = 390 | enum "ObjectFieldName" NString [str s] 391 | 392 | let emit_unknown p = Api.jnull 393 | 394 | let emit_block_element_var vl p = 395 | enum "BlockElement" Var [tok;arr vl;tok] 396 | 397 | let emit_block_element_inline_function f p = 398 | enum "BlockElement" InlineFunction [tok;tok;f;tok] 399 | 400 | let emit_block_element_expr e p = 401 | enum "BlockElement" Expr [e;tok] 402 | 403 | let emit_this p = 404 | enum "Expr" EConst [emit_const_ident "this"] 405 | 406 | let emit_true p = 407 | enum "Expr" EConst [emit_const_ident "true"] 408 | 409 | let emit_false p = 410 | enum "Expr" EConst [emit_const_ident "false"] 411 | 412 | let emit_null p = 413 | enum "Expr" EConst [emit_const_ident "null"] 414 | 415 | let emit_block_expr el p = 416 | enum "Expr" EBlock [tok;arr el;tok] 417 | 418 | let emit_var_declaration_expr v p = 419 | enum "Expr" EVar [tok;v] 420 | 421 | let emit_metadata_expr meta e p = 422 | enum "Expr" EMetadata [meta;e] 423 | 424 | let emit_throw_expr e p = 425 | enum "Expr" EThrow [tok;e;] 426 | 427 | let emit_if_expr e1 e2 eo p = 428 | enum "Expr" EIf [tok;tok;e1;tok;e2;opt eo] 429 | 430 | let emit_return_expr eo p = match eo with 431 | | None -> enum "Expr" EReturn [tok] 432 | | Some e -> enum "Expr" EReturnExpr [tok;e] 433 | 434 | let emit_break_expr p = 435 | enum "Expr" EBreak [tok] 436 | 437 | let emit_continue_expr p = 438 | enum "Expr" EContinue [tok] 439 | 440 | let emit_do_expr e1 e2 p = 441 | enum "Expr" EDo [tok;e1;tok;tok;e2;tok] 442 | 443 | let emit_try_expr e catches p = 444 | enum "Expr" ETry [tok;e;arr catches] 445 | 446 | let emit_switch_expr e cases p = 447 | enum "Expr" ESwitch [tok;e;tok;arr cases;tok] 448 | 449 | let emit_for_expr e1 e2 p = 450 | enum "Expr" EFor [tok;tok;e1;tok;e2] 451 | 452 | let emit_while_expr e1 e2 p = 453 | enum "Expr" EWhile [tok;tok;e1;tok;e2] 454 | 455 | let emit_untyped_expr e p = 456 | enum "Expr" EUntyped [tok;e] 457 | 458 | let emit_object_decl_expr fl p = 459 | enum "Expr" EObjectDecl [tok;arr fl;tok] 460 | 461 | let emit_unsafe_cast_expr e p = 462 | enum "Expr" EUnsafeCast [tok;e] 463 | 464 | let emit_safe_cast_expr e ct p = 465 | enum "Expr" ESafeCast [tok;tok;e;tok;ct;tok] 466 | 467 | let emit_new_expr path el p = 468 | enum "Expr" ENew [tok;path;el] 469 | 470 | let emit_parenthesis_expr e p = 471 | enum "Expr" EParenthesis [tok;e;tok] 472 | 473 | let emit_typecheck_expr e ct p = 474 | enum "Expr" ECheckType [tok;e;tok;ct;tok] 475 | 476 | let emit_is_expr e path p_is p = 477 | enum "Expr" EIs [tok;e;tok;path;tok] 478 | 479 | let emit_array_decl_expr el p = 480 | enum "Expr" EArrayDecl [tok;arr el;tok] 481 | 482 | let emit_function_expr f p = 483 | enum "Expr" EFunction [tok;f] 484 | 485 | let emit_unary_prefix_expr op e p = 486 | enum "Expr" EUnaryPrefix [tok;e] 487 | 488 | let emit_field_expr e s p = 489 | enum "Expr" EField [e;str s] 490 | 491 | let emit_call_expr e el p = 492 | enum "Expr" ECall [e;el] 493 | 494 | let emit_array_expr e1 e2 p = 495 | enum "Expr" EArrayAccess [e1;tok;e2;tok] 496 | 497 | let emit_binop_expr e1 op e2 p = 498 | enum "Expr" EBinop [e1;tok;e2] 499 | 500 | let emit_unary_postfix_expr e op p = 501 | enum "Expr" EUnaryPostfix [e;tok] 502 | 503 | let emit_ternary_expr e1 e2 e3 p = 504 | enum "Expr" ETernary [e1;tok;e2;tok;e3] 505 | 506 | let emit_in_expr e1 e2 p = 507 | enum "Expr" EIn [e1;tok;e2] 508 | 509 | let emit_dotint_expr s p = 510 | enum "Expr" EIntDot [str s;tok] 511 | 512 | let emit_dollarident_expr name p = 513 | enum "Expr" EDollarIdent [str name] 514 | 515 | let emit_macro_escape_expr name e p = 516 | enum "Expr" EMacroEscape [str (fst name);tok;e;tok] 517 | 518 | let emit_macro_expr e p = 519 | enum "Expr" EMacro [e] 520 | 521 | let emit_const_expr const p = 522 | enum "Expr" EConst [const] 523 | 524 | (* Type hints *) 525 | 526 | let emit_type_path path params p = 527 | Api.jobject [ 528 | "path",path; 529 | "params",arropt params; 530 | ] 531 | 532 | let emit_complex_type_path path p = 533 | enum "ComplexType" TypePath [path] 534 | 535 | let emit_complex_type_parent ct p = 536 | enum "ComplexType" Parenthesis [tok;ct;tok] 537 | 538 | let emit_complex_type_extension paths fields p = 539 | enum "ComplexType" StructuralExtension [tok;arr paths;fields;tok] 540 | 541 | let emit_complex_type_anonymous fields p = 542 | enum "ComplexType" AnonymousStructure [tok;fields;tok] 543 | 544 | let emit_complex_type_optional ct p = 545 | enum "ComplexType" Optional [tok;ct] 546 | 547 | let emit_complex_type_function ct1 ct2 p = 548 | enum "ComplexType" Function [ct1;tok;ct2] (* TODO: Compose these here? *) 549 | 550 | let emit_type_path_parameter_complex_type ct = 551 | enum "TypePathParameter" Type [ct] 552 | 553 | let emit_type_path_parameter_bracket el p = 554 | enum "TypePathParameter" ArrayExpr [tok;arr el;tok] 555 | 556 | let emit_type_path_parameter_literal lit p = 557 | enum "TypePathParameter" Literal [lit] 558 | 559 | (* Fields *) 560 | 561 | let emit_function_argument annotations optq name cto eo = 562 | Api.jobject [ 563 | "annotations",annotations; 564 | "questionMark",(match optq with None -> Api.jnull | Some _ -> Api.jint 0); (* TODO: This is stupid *) 565 | "name",str (fst name); 566 | "typeHint",opt cto; 567 | "assignment",opt eo 568 | ] 569 | 570 | let emit_field_expr_none = 571 | enum "MethodExpr" MNone [tok] 572 | 573 | let emit_field_expr_block e = 574 | enum "MethodExpr" MBlock [e] 575 | 576 | let emit_field_expr_expr e = 577 | enum "MethodExpr" MExpr [e;tok] 578 | 579 | let emit_static_modifier = 580 | enum "FieldModifier" Static [tok] 581 | 582 | let emit_macro_modifier = 583 | enum "FieldModifier" Macro [tok] 584 | 585 | let emit_public_modifier = 586 | enum "FieldModifier" Public [tok] 587 | 588 | let emit_private_modifier = 589 | enum "FieldModifier" Private [tok] 590 | 591 | let emit_override_modifier = 592 | enum "FieldModifier" Override [tok] 593 | 594 | let emit_dynamic_modifier = 595 | enum "FieldModifier" Dynamic [tok] 596 | 597 | let emit_inline_modifier = 598 | enum "FieldModifier" Inline [tok] 599 | 600 | let emit_function_field annotations modifiers name tl args cto e p = 601 | enum "ClassField" Function [annotations;arr modifiers;str (fst name);arropt tl;arr args;opt cto;e] 602 | 603 | let emit_variable_field annotations modifiers name cto eo p = 604 | enum "ClassField" Variable [annotations;arr modifiers;str (fst name);opt cto;opt eo] 605 | 606 | let emit_property_field annotations modifiers name get set cto eo p = 607 | enum "ClassField" Property [annotations;arr modifiers;tok;str (fst name);tok;str (fst name);tok;str (fst name);tok;opt cto;opt eo] 608 | 609 | let emit_enum_field_arg optq name ct = 610 | Api.jobject [ 611 | "questionMark",(match optq with None -> Api.jnull | Some _ -> Api.jint 0); (* TODO: This is stupid *) 612 | "name",str name; 613 | "typeHint",ct 614 | ] 615 | 616 | let emit_enum_field annotations name tl args cto p = 617 | Api.jobject [ 618 | "annotations",annotations; 619 | "name",str (fst name); 620 | "params",arropt tl; 621 | "args",arropt args; 622 | "typeHint",opt cto; 623 | ] 624 | 625 | let emit_anonymous_class_fields fields = 626 | enum "AnonymousStructureFields" ClassNotation [arr fields] 627 | 628 | let emit_anonymous_type_fields fields = 629 | enum "AnonymousStructureFields" ShortNotation [arr fields] 630 | 631 | let emit_anonymous_type_field optq name ct p = 632 | Api.jobject [ 633 | "questionMark",(match optq with None -> Api.jnull | Some _ -> Api.jint 0); (* TODO: This is stupid *) 634 | "name",str (fst name); 635 | "typeHint",ct 636 | ] 637 | 638 | (* Type declaration *) 639 | 640 | let emit_constraints_none = 641 | enum "Constraints" CNone [] 642 | 643 | let emit_constraints_single ct = 644 | enum "Constraints" CSingle [tok;ct] 645 | 646 | let emit_constraints_multiple ctl = 647 | enum "Constraints" CMultiple [tok;tok;arr ctl;tok] 648 | 649 | let emit_type_decl_parameter annotations name constraints = 650 | Api.jobject [ 651 | "annotations",annotations; 652 | "name",str (fst name); 653 | "constraints",constraints 654 | ] 655 | 656 | (* TODO: Figure these out *) 657 | 658 | let emit_class_flag_interface = Api.jnull 659 | 660 | let emit_class_flag_class = Api.jnull 661 | 662 | let emit_common_flag_extern = 663 | enum "NCommonFlag" PExtern [tok] 664 | 665 | let emit_common_flag_private = 666 | enum "NCommonFlag" PPrivate [tok] 667 | 668 | let emit_class_relation_extends path = 669 | enum "ClassRelation" Extends [tok;path] 670 | 671 | let emit_class_relation_implements path = 672 | enum "ClassRelation" Implements [tok;path] 673 | 674 | let emit_abstract_relation_from ct = 675 | enum "AbstractRelation" From [tok;ct] 676 | 677 | let emit_abstract_relation_to ct = 678 | enum "AbstractRelation" To [tok;ct] 679 | 680 | let emit_import_mode_all = 681 | enum "ImportMode" IAll [tok] 682 | 683 | let emit_import_mode_alias name = 684 | enum "ImportMode" IAs [tok;str name] 685 | 686 | let emit_import_mode_normal = 687 | enum "ImportMode" INormal [] 688 | 689 | let emit_import path mode p = 690 | enum "Decl" ImportDecl [tok;path;mode;tok] 691 | 692 | let emit_using path p = 693 | enum "Decl" UsingDecl [tok;path;tok] 694 | 695 | let emit_class flags name tl rl l = 696 | Api.jobject [ 697 | "params",arropt tl; 698 | "relations",arr rl; 699 | "fields",arr l; 700 | ] 701 | 702 | let emit_class_decl annotations flags c p = 703 | enum "Decl" ClassDecl [annotations;arr flags;c] 704 | 705 | let emit_enum_decl annotations flags name tl l p = 706 | enum "Decl" EnumDecl [annotations;arr flags;tok;str (fst name);arropt tl;tok;arr l;tok] 707 | 708 | let emit_typedef_decl annotations flags name tl ct p = 709 | enum "Decl" TypedefDecl [annotations;arr flags;tok;str (fst name);arropt tl;tok;ct] 710 | 711 | let emit_abstract_decl annotations flags name tl st rl l p = 712 | enum "Decl" AbstractDecl [annotations;arr flags;tok;str (fst name);arropt tl;opt st;arr rl;tok;arr l;tok] 713 | 714 | let emit_package path = 715 | Api.jobject [ 716 | "path",opt path 717 | ] 718 | end -------------------------------------------------------------------------------- /src/syntax/grammars/parser.mly: -------------------------------------------------------------------------------- 1 | (* Start and types *) 2 | 3 | %start file 4 | %start expr_only 5 | %start class_fields_only 6 | %start class_decl_only 7 | %start block_elements_only 8 | %start unused 9 | 10 | %type path 11 | 12 | %on_error_reduce expr_open expr_closed expr 13 | %on_error_reduce path complex_type 14 | 15 | %parameter 16 | 17 | %{ 18 | open Emitter 19 | %} 20 | 21 | %% 22 | 23 | (* Various *) 24 | 25 | lplist(X): 26 | | %prec LOWEST { [] } 27 | | x = X; xs = lplist(X) { x :: xs } 28 | 29 | lpoption(X): 30 | | %prec LOWEST { None } 31 | | x = X { Some x } 32 | 33 | metadata: 34 | | name = METADATA { emit_metadata_entry (Meta.Custom name) (mk $startpos $endpos) } 35 | | name = METADATA_OPEN; el = separated_list(COMMA, expr); PCLOSE { emit_metadata_entry_with_args (Meta.Custom name) el (mk $startpos $endpos) } 36 | 37 | documentation: 38 | | comment = COMMENT { Some comment } 39 | | { None } 40 | 41 | annotations: 42 | | doc = documentation; meta = metadata* { emit_annotations doc meta } 43 | 44 | %inline pos(f): 45 | | x = f { x,mk $startpos $endpos } 46 | 47 | %inline dollar_ident: 48 | | s = ident | s = DOLLAR_IDENT { s } 49 | 50 | dot_ident: 51 | | s = DOT_IDENT { s } 52 | | DOT { "." } 53 | 54 | path: 55 | | ident = dollar_ident; l = lplist(dot_ident) { emit_path ident l } 56 | 57 | path_with_pos: 58 | | ident = pos(dollar_ident); l = lplist(pos(dot_ident)) { emit_pos_path ident l } 59 | 60 | (* Expression *) 61 | 62 | call_args: 63 | | POPEN; el = separated_list(COMMA, expr); PCLOSE { emit_call_args el } 64 | 65 | assignment: 66 | | ASSIGN; e1 = expr { emit_assignment e1 } 67 | 68 | var_declaration: 69 | | name = pos(dollar_ident); ct = lpoption(type_hint); eo = lpoption(assignment) { 70 | emit_var_declaration name ct eo 71 | } 72 | 73 | var_declarations_next: 74 | | %prec LOWEST { [] } 75 | | COMMA; vl = var_declarations { vl } 76 | 77 | var_declarations: 78 | | v = var_declaration; vl = var_declarations_next { v :: vl } 79 | 80 | else_expr: 81 | | ELSE; e1 = expr { e1 } 82 | 83 | catch: 84 | | CATCH; POPEN; name = pos(dollar_ident); ct = type_hint; PCLOSE; e1 = expr { 85 | emit_catch name ct e1 (mk $startpos $endpos) 86 | } 87 | 88 | guard: 89 | | IF; POPEN; e1 = expr; PCLOSE { e1 } 90 | 91 | case_expr: 92 | | VAR; name = pos(dollar_ident) { 93 | let v = emit_var_declaration name None None in 94 | emit_var_declaration_expr v (mk $startpos $endpos) 95 | } 96 | | e = expr_open | e = expr_closed { e } 97 | 98 | case: 99 | | CASE; el = separated_nonempty_list(COMMA,case_expr); eg = guard?; COLON; el2 = block_element* { 100 | emit_case el eg el2 (mk $startpos $endpos) 101 | } 102 | | DEFAULT; COLON; el = block_element* { 103 | emit_default el (mk $startpos $endpos) 104 | } 105 | 106 | func: 107 | | name = dollar_ident?; tl = type_decl_parameters; POPEN; el = separated_list(COMMA,function_argument); PCLOSE; ct = type_hint?; e1 = expr { 108 | emit_function name tl el ct e1 109 | } 110 | 111 | array_elements_next: 112 | | { [] } 113 | | COMMA; el = array_elements { el } 114 | 115 | array_elements: 116 | | { [] } 117 | | e1 = expr; el = array_elements_next { e1 :: el } 118 | 119 | object_field_name: 120 | | name = dollar_ident { emit_object_field_name_ident name (mk $startpos $endpos) } 121 | | name = string { emit_object_field_name_string name (mk $startpos $endpos) } 122 | 123 | object_field: 124 | | name = object_field_name; COLON; e = expr { 125 | emit_object_field name e 126 | } 127 | 128 | object_fields_next: 129 | | { [] } 130 | | COMMA; fl = object_fields { fl } 131 | 132 | object_fields: 133 | | %prec LOWEST { [] } 134 | | f = object_field; fl = object_fields_next { f :: fl } 135 | 136 | macro_expr_type_hint: 137 | | type_hint { emit_unknown (mk $startpos $endpos) } 138 | 139 | macro_expr_var: 140 | | VAR; var_declarations { emit_unknown (mk $startpos $endpos) } 141 | 142 | macro_expr_class_decl: 143 | | class_decl2 { emit_unknown (mk $startpos $endpos) } 144 | 145 | macro_expr_expr: 146 | | expr_open %prec MACRO { emit_unknown (mk $startpos $endpos) } 147 | | expr_closed { emit_unknown (mk $startpos $endpos) } 148 | 149 | macro_expr: 150 | | macro_expr_type_hint | macro_expr_var | macro_expr_class_decl | macro_expr_expr { $1 } 151 | 152 | block_element_var: 153 | | VAR; vl = var_declarations; SEMICOLON { 154 | emit_block_element_var vl (mk $startpos $endpos) 155 | } 156 | 157 | block_element_inline_function: 158 | | INLINE; FUNCTION; f = func; SEMICOLON { 159 | emit_block_element_inline_function f (mk $startpos $endpos) 160 | } 161 | 162 | block_element_expr: 163 | | e = expr_open; SEMICOLON { emit_block_element_expr e (mk $startpos $endpos) } 164 | | e = expr_closed; SEMICOLON { emit_block_element_expr e (mk $startpos $endpos) } 165 | 166 | %inline block_element: 167 | | block_element_var | block_element_inline_function | block_element_expr { $1 } 168 | 169 | field_expr_none: 170 | | SEMICOLON { emit_field_expr_none } 171 | 172 | field_expr_block: 173 | | e = expr_block { emit_field_expr_block e } 174 | 175 | field_expr_expr: 176 | | e = expr; SEMICOLON { emit_field_expr_expr e } 177 | 178 | %inline field_expr: 179 | | field_expr_none | field_expr_block | field_expr_expr { $1 } 180 | 181 | expr_empty_block: 182 | | BROPEN; BRCLOSE { emit_block_expr [] (mk $startpos $endpos) } 183 | 184 | expr_nonempty_block: 185 | | BROPEN; el = nonempty_list(block_element); BRCLOSE { emit_block_expr el (mk $startpos $endpos) } 186 | 187 | %inline expr_block: 188 | | expr_empty_block | expr_nonempty_block { $1 } 189 | 190 | expr_var: 191 | | VAR; v = var_declaration { emit_var_declaration_expr v (mk $startpos $endpos) } 192 | 193 | expr_metadata: 194 | | m = metadata; e1 = expr { emit_metadata_expr m e1 (mk $startpos $endpos) } 195 | 196 | expr_throw: 197 | | THROW; e1 = expr { emit_throw_expr e1 (mk $startpos $endpos) } 198 | 199 | expr_if: 200 | | IF; POPEN; e1 = expr; PCLOSE; e2 = expr; eo = lpoption(else_expr) { emit_if_expr e1 e2 eo (mk $startpos $endpos) } 201 | 202 | expr_return: 203 | | RETURN { emit_return_expr None (mk $startpos $endpos) } 204 | 205 | expr_return_value: 206 | | RETURN; e = expr { emit_return_expr (Some e) (mk $startpos $endpos) } 207 | 208 | expr_break: 209 | | BREAK { emit_break_expr (mk $startpos $endpos) } 210 | 211 | expr_continue: 212 | | CONTINUE { emit_continue_expr (mk $startpos $endpos) } 213 | 214 | expr_do: 215 | | DO; e1 = expr; WHILE; POPEN; e2 = expr; PCLOSE { emit_do_expr e1 e2 (mk $startpos $endpos) } 216 | 217 | expr_try: 218 | | TRY; e1 = expr; catches = lplist(catch); { emit_try_expr e1 catches (mk $startpos $endpos) } 219 | 220 | expr_switch: 221 | | SWITCH; e1 = expr; BROPEN; cases = case*; BRCLOSE { emit_switch_expr e1 cases (mk $startpos $endpos) } 222 | 223 | expr_for: 224 | | FOR; POPEN; e1 = expr; PCLOSE; e2 = expr { emit_for_expr e1 e2 (mk $startpos $endpos) } 225 | 226 | expr_while: 227 | | WHILE; POPEN; e1 = expr; PCLOSE; e2 = expr { emit_while_expr e1 e2 (mk $startpos $endpos) } 228 | 229 | expr_untyped: 230 | | UNTYPED; e1 = expr { emit_untyped_expr e1 (mk $startpos $endpos) } 231 | 232 | expr_object_declaration: 233 | | BROPEN; fl = object_fields; BRCLOSE { emit_object_decl_expr fl (mk $startpos $endpos) } 234 | 235 | expr_unsafe_cast: 236 | | CAST; e1 = expr { emit_unsafe_cast_expr e1 (mk $startpos $endpos) } 237 | 238 | expr_safe_cast: 239 | | CAST; POPEN; e1 = expr; COMMA; ct = complex_type; PCLOSE { emit_safe_cast_expr e1 ct (mk $startpos $endpos) } 240 | 241 | expr_new: 242 | | NEW; tp = type_path; el = call_args { emit_new_expr tp el (mk $startpos $endpos) } 243 | 244 | lambda_function_argument: 245 | | name = expr; ct = lpoption(type_hint); eo = assignment? { (name,(match None with None -> false | Some _ -> true),[],ct,eo) } 246 | | QUESTIONMARK; name = pos(dollar_ident); ct = lpoption(type_hint); eo = assignment? { 247 | let cst = emit_const_ident (fst name) in 248 | let e = emit_const_expr cst (snd name) in 249 | (e,true,[],ct,eo) } 250 | 251 | lambda_function_arguments: 252 | | COMMA; l = separated_nonempty_list(COMMA,function_argument) { l } 253 | | { [] } 254 | 255 | expr_typechecks: 256 | | POPEN; arg = lambda_function_argument; args = lambda_function_arguments; PCLOSE { arg,args } 257 | 258 | expr_is: 259 | | POPEN; e1 = expr; is = pos(IS); tp = type_path; PCLOSE { emit_is_expr e1 tp (snd is) (mk $startpos $endpos) } 260 | 261 | expr_array_declaration: 262 | | BKOPEN; el = array_elements; BKCLOSE { emit_array_decl_expr el (mk $startpos $endpos) } 263 | 264 | expr_function: 265 | | FUNCTION; f = func { emit_function_expr f (mk $startpos $endpos) } 266 | 267 | expr_unary_prefix: 268 | | op = unary_prefix; e1 = expr_inline %prec INCREMENT { emit_unary_prefix_expr op e1 (mk $startpos $endpos) } 269 | 270 | expr_field: 271 | | e1 = expr_open; name = dot_ident { emit_field_expr e1 name (mk $startpos $endpos) } 272 | 273 | expr_call: 274 | | e1 = expr_open; el = call_args { emit_call_expr e1 el (mk $startpos $endpos) } 275 | 276 | expr_array_access: 277 | | e1 = expr_open; BKOPEN; e2 = expr; BKCLOSE { emit_array_expr e1 e2 (mk $startpos $endpos) } 278 | 279 | expr_binop: 280 | | e1 = expr_open; op = op; e2 = expr_inline { emit_binop_expr e1 op e2 (mk $startpos $endpos) } 281 | | e1 = expr_open; op = op_bit; e2 = expr_inline %prec AND { emit_binop_expr e1 op e2 (mk $startpos $endpos) } 282 | | e1 = expr_open; op = op_compare; e2 = expr_inline %prec EQUALS { emit_binop_expr e1 op e2 (mk $startpos $endpos) } 283 | | e1 = expr_open; op = op_assign; e2 = expr_inline %prec ASSIGN { emit_binop_expr e1 op e2 (mk $startpos $endpos) } 284 | 285 | expr_unary_postfix: 286 | | e1 = expr_open; op = unary_postfix { emit_unary_postfix_expr e1 op (mk $startpos $endpos) } 287 | 288 | expr_ternary: 289 | | e1 = expr_open; QUESTIONMARK; e2 = expr; COLON; e3 = expr { 290 | emit_ternary_expr e1 e2 e3 (mk $startpos $endpos) 291 | } 292 | 293 | expr_in: 294 | | e1 = expr_open; IN; e2 = expr { emit_in_expr e1 e2 (mk $startpos $endpos) } 295 | 296 | expr_dotint: 297 | | s = INT; DOT { emit_dotint_expr s (mk $startpos $endpos) } 298 | 299 | expr_dollarident: 300 | | s = DOLLAR_IDENT %prec LOWEST { emit_dollarident_expr s (mk $startpos $endpos) } 301 | 302 | expr_macro_escape: 303 | | s = pos(DOLLAR_IDENT); BROPEN; e1 = expr; BRCLOSE { emit_macro_escape_expr s e1 (mk $startpos $endpos) } 304 | 305 | expr_macro: 306 | | MACRO; e = macro_expr { emit_macro_expr e (mk $startpos $endpos) } 307 | 308 | expr_const: 309 | | const = const { emit_const_expr const (mk $startpos $endpos) } 310 | 311 | expr_keyword_ident: 312 | | e1 = keyword_ident { e1 } 313 | 314 | expr_lambda: 315 | | args = expr_typechecks; ARROW; e1 = expr { 316 | let lambda = emit_lambda_arg args in 317 | let f = emit_function None [] lambda None e1 in 318 | emit_function_expr f (mk $startpos $endpos) 319 | } 320 | | POPEN; PCLOSE; ARROW; e1 = expr { 321 | let f = emit_function None [] [] None e1 in 322 | emit_function_expr f (mk $startpos $endpos) 323 | } 324 | | name = pos(dollar_ident); ARROW; e1 = expr { 325 | let cst = emit_const_ident (fst name) in 326 | let e = emit_const_expr cst (snd name) in 327 | let lambda = emit_lambda_arg ((e,false,[],None,None),[]) in 328 | let f = emit_function None [] lambda None e1 in 329 | emit_function_expr f (mk $startpos $endpos) 330 | } 331 | 332 | expr_closed: 333 | | expr_metadata | expr_macro | expr_block | expr_throw | expr_if | expr_return | expr_return_value | expr_break | expr_continue 334 | | expr_do | expr_try | expr_switch | expr_for | expr_while | expr_untyped | expr_lambda { $1 } 335 | 336 | expr_open: 337 | | expr_object_declaration | expr_unsafe_cast | expr_safe_cast | expr_new 338 | | expr_is | expr_array_declaration | expr_function | expr_unary_prefix 339 | | expr_field | expr_call | expr_array_access | expr_binop | expr_unary_postfix 340 | | expr_ternary | expr_in | expr_dotint | expr_dollarident | expr_macro_escape 341 | | expr_const | expr_keyword_ident { $1 } 342 | | tc = expr_typechecks { 343 | match tc with 344 | | (e,false,_,None,None),[] -> emit_parenthesis_expr e (mk $startpos $endpos) 345 | | (e,false,_,Some ct,None),[] -> emit_typecheck_expr e ct (mk $startpos $endpos) 346 | | _ -> $syntaxerror 347 | } 348 | 349 | %inline expr_inline: 350 | | e = expr_closed | e = expr_open | e = expr_var { e } 351 | 352 | expr: 353 | | e = expr_closed | e = expr_open %prec LOWEST | e = expr_var { e } 354 | 355 | (* Type hints *) 356 | 357 | structural_extension: 358 | | GT; tp = type_path; COMMA { tp } 359 | 360 | anonymous_type_field: 361 | | opt = QUESTIONMARK?; name = pos(dollar_ident); ct = type_hint { 362 | emit_anonymous_type_field opt name ct (mk $startpos $endpos) 363 | } 364 | 365 | anonymous_type_fields_short_next: 366 | | { [] } 367 | | COMMA; fl = anonymous_type_fields_short { fl } 368 | 369 | anonymous_type_fields_short: 370 | | { [] } 371 | | f = anonymous_type_field; fl = anonymous_type_fields_short_next { f :: fl } 372 | 373 | anonymous_type_fields: 374 | | l = class_field+ { emit_anonymous_class_fields l } 375 | | l = anonymous_type_fields_short { emit_anonymous_type_fields l } 376 | 377 | complex_type_named: 378 | | n = pos(dollar_ident); COLON; ct = complex_type { emit_complex_type_named n ct (mk $startpos $endpos) } 379 | 380 | complex_type_maybe_named: 381 | | complex_type_named | complex_type { $1 } 382 | 383 | complex_type_parent: 384 | | POPEN; ct = complex_type; PCLOSE { 385 | emit_complex_type_parent ct (mk $startpos $endpos) 386 | } 387 | | POPEN; ct = complex_type; COMMA; ctl = separated_nonempty_list(COMMA, complex_type_maybe_named); PCLOSE; ARROW; ctr = complex_type { 388 | emit_complex_type_named_function (ct :: ctl) ctr (mk $startpos $endpos) 389 | } 390 | | POPEN; ct = complex_type_named; PCLOSE; ARROW; ctr = complex_type { 391 | emit_complex_type_named_function [ct] ctr (mk $startpos $endpos) 392 | } 393 | | POPEN; ct = complex_type_named; COMMA; ctl = separated_nonempty_list(COMMA, complex_type_maybe_named); PCLOSE; ARROW; ctr = complex_type { 394 | emit_complex_type_named_function (ct :: ctl) ctr (mk $startpos $endpos) 395 | } 396 | 397 | complex_type_extension: 398 | | BROPEN; l = structural_extension+; cffl = anonymous_type_fields; BRCLOSE { 399 | emit_complex_type_extension l cffl (mk $startpos $endpos) 400 | } 401 | 402 | complex_type_anonymous: 403 | | BROPEN; l = anonymous_type_fields; BRCLOSE { emit_complex_type_anonymous l (mk $startpos $endpos) } 404 | 405 | complex_type_optional: 406 | | QUESTIONMARK; ct = complex_type_maybe_named; { emit_complex_type_optional ct (mk $startpos $endpos) } 407 | 408 | complex_type_path: 409 | | tp = type_path { emit_complex_type_path tp (mk $startpos $endpos) } 410 | 411 | complex_type_function: 412 | | ct1 = complex_type; ARROW; ct2 = complex_type { 413 | emit_complex_type_function ct1 ct2 (mk $startpos $endpos) 414 | } 415 | 416 | complex_type: 417 | | complex_type_parent | complex_type_extension | complex_type_anonymous | complex_type_optional 418 | | complex_type_path | complex_type_function { $1 } 419 | 420 | type_path_parameter_bracket: 421 | | BKOPEN; el = array_elements; BKCLOSE { emit_type_path_parameter_bracket el (mk $startpos $endpos) } 422 | 423 | type_path_parameter_complex_type: 424 | | ct = complex_type { emit_type_path_parameter_complex_type ct } 425 | 426 | type_path_parameter_literal: 427 | | cst = literal { emit_type_path_parameter_literal cst (mk $startpos $endpos) } 428 | 429 | type_path_parameter_bool: 430 | | TRUE { emit_type_path_parameter_bool true (mk $startpos $endpos) } 431 | | FALSE { emit_type_path_parameter_bool false (mk $startpos $endpos) } 432 | 433 | %inline type_path_parameter: 434 | | type_path_parameter_bracket | type_path_parameter_complex_type | type_path_parameter_literal 435 | | type_path_parameter_bool { $1 } 436 | /*| e = expr { TPExpr e }*/ 437 | 438 | type_path_parameters: 439 | | LT; tl = separated_nonempty_list(COMMA,type_path_parameter); GT { tl } 440 | | %prec LOWEST { [] } 441 | 442 | type_path: 443 | | path = path; l = type_path_parameters { 444 | emit_type_path path l (mk $startpos $endpos) 445 | } 446 | 447 | type_hint: 448 | | COLON; ct = complex_type { ct } 449 | 450 | (* Field *) 451 | 452 | function_argument: 453 | | annotations = annotations; opt = QUESTIONMARK?; name = pos(dollar_ident); ct = type_hint?; eo = assignment? { 454 | emit_function_argument annotations opt name ct eo 455 | } 456 | 457 | function_arguments: 458 | | l = separated_list(COMMA,function_argument) { l } 459 | 460 | modifier: 461 | | STATIC { emit_static_modifier (mk $startpos $endpos) } 462 | | MACRO { emit_macro_modifier (mk $startpos $endpos) } 463 | | PUBLIC { emit_public_modifier (mk $startpos $endpos) } 464 | | PRIVATE { emit_private_modifier (mk $startpos $endpos) } 465 | | OVERRIDE { emit_override_modifier (mk $startpos $endpos) } 466 | | DYNAMIC { emit_dynamic_modifier (mk $startpos $endpos) } 467 | | INLINE { emit_inline_modifier (mk $startpos $endpos) } 468 | | EXTERN { emit_extern_modifier (mk $startpos $endpos) } 469 | 470 | function_name: 471 | | s = pos(dollar_ident) { s } 472 | | s = pos(NEW) { "new",snd s } 473 | 474 | property_ident: 475 | | s = pos(ident) { s } 476 | | s = pos(DYNAMIC) { "dynamic",snd s } 477 | | s = pos(DEFAULT) { "default",snd s } 478 | | s = pos(NULL) { "null",snd s } 479 | 480 | function_field: 481 | | annotations = annotations; ml = modifier*; FUNCTION; name = function_name; tl = type_decl_parameters; POPEN; args = function_arguments; PCLOSE; ct = type_hint? eo = field_expr { 482 | emit_function_field annotations ml name tl args ct eo (mk $startpos $endpos) 483 | } 484 | 485 | variable_field: 486 | | annotations = annotations; ml = modifier*; VAR; name = pos(dollar_ident); ct = type_hint?; eo = assignment?; SEMICOLON { 487 | emit_variable_field annotations ml name ct eo (mk $startpos $endpos) 488 | } 489 | 490 | property_field: 491 | | annotations = annotations; ml = modifier*; VAR; name = pos(dollar_ident); POPEN; get = property_ident; COMMA; set = property_ident; PCLOSE; ct = type_hint?; eo = assignment?; SEMICOLON { 492 | emit_property_field annotations ml name get set ct eo (mk $startpos $endpos) 493 | } 494 | 495 | final_field: 496 | | annotations = annotations; ml = modifier*; FINAL; name = pos(dollar_ident); ct = type_hint?; eo = assignment?; SEMICOLON { 497 | emit_variable_field annotations ml name ct eo (mk $startpos $endpos) 498 | } 499 | 500 | %inline class_field: 501 | | cff = function_field | cff = variable_field | cff = property_field | cff = final_field { cff } 502 | 503 | enum_field_arg: 504 | | opt = QUESTIONMARK?; name = dollar_ident; ct = type_hint; { 505 | emit_enum_field_arg opt name ct 506 | } 507 | 508 | enum_field_args: 509 | | { [] } 510 | | POPEN; l = separated_list(COMMA,enum_field_arg); PCLOSE { l } 511 | 512 | enum_field: 513 | | annotations = annotations; name = pos(dollar_ident); tl = type_decl_parameters; args = enum_field_args; ct = type_hint?; SEMICOLON { 514 | emit_enum_field annotations name tl args ct (mk $startpos $endpos) 515 | } 516 | 517 | (* Type declaration *) 518 | 519 | class_relations: 520 | | EXTENDS; path = type_path { emit_class_relation_extends path } 521 | | IMPLEMENTS; path = type_path { emit_class_relation_implements path } 522 | 523 | abstract_relations: 524 | | TO; ct = complex_type { emit_abstract_relation_to ct } 525 | | FROM; ct = complex_type { emit_abstract_relation_from ct } 526 | 527 | underlying_type: 528 | | POPEN; ct = complex_type; PCLOSE { ct } 529 | 530 | common_flags: 531 | | PRIVATE { emit_common_flag_private } 532 | | EXTERN { emit_common_flag_extern } 533 | 534 | constraints_multiple: 535 | | COLON; POPEN; ct = complex_type; COMMA; ctl = separated_nonempty_list(COMMA,complex_type); PCLOSE { 536 | emit_constraints_multiple (ct :: ctl) 537 | } 538 | 539 | constraints_single: 540 | | COLON; ct = complex_type { emit_constraints_single ct } 541 | 542 | constraints_none: 543 | | { emit_constraints_none } 544 | 545 | %inline constraints: 546 | | constraints_multiple | constraints_single | constraints_none { $1 } 547 | 548 | type_decl_parameter: 549 | | annotations = annotations; name = pos(dollar_ident); ctl = constraints { 550 | emit_type_decl_parameter annotations name ctl 551 | } 552 | 553 | type_decl_parameters: 554 | | LT; tl = separated_nonempty_list(COMMA,type_decl_parameter); GT { tl } 555 | | { [] } 556 | 557 | import_mode_alias: 558 | | IN; ident = ident { emit_import_mode_alias ident } 559 | | AS; ident = ident { emit_import_mode_alias ident } 560 | 561 | import_mode_all: 562 | | DOTSTAR { emit_import_mode_all } 563 | 564 | import_mode_normal: 565 | | { emit_import_mode_normal } 566 | 567 | %inline import_mode: 568 | | import_mode_alias | import_mode_all | import_mode_normal { $1 } 569 | 570 | class_or_interface: 571 | | CLASS { emit_class_flag_class } 572 | | INTERFACE { emit_class_flag_interface } 573 | 574 | %inline class_decl2: 575 | | flags = class_or_interface; name = pos(dollar_ident)?; tl = type_decl_parameters; rl = class_relations*; BROPEN; l = class_field*; BRCLOSE { 576 | emit_class flags name tl rl l 577 | } 578 | 579 | import_decl: 580 | | IMPORT; path = path_with_pos; mode = import_mode; SEMICOLON { emit_import path mode (mk $startpos $endpos) } 581 | 582 | using_decl: 583 | | USING; path = path_with_pos; SEMICOLON { emit_using path (mk $startpos $endpos) } 584 | 585 | class_decl: 586 | | annotations = annotations; flags = common_flags*; c = class_decl2 { 587 | emit_class_decl annotations flags c (mk $startpos $endpos) 588 | } 589 | 590 | enum_decl: 591 | | annotations = annotations; flags = common_flags*; ENUM; name = pos(dollar_ident); tl = type_decl_parameters; BROPEN; l = enum_field*; BRCLOSE { 592 | emit_enum_decl annotations flags name tl l (mk $startpos $endpos) 593 | } 594 | 595 | abstract_decl2: 596 | | ABSTRACT; name = pos(dollar_ident); tl = type_decl_parameters; st = underlying_type?; rl = abstract_relations*; BROPEN; l = class_field*; BRCLOSE { 597 | name,tl,st,rl,l 598 | } 599 | 600 | enum_abstract_decl: 601 | | annotations = annotations; flags = common_flags*; ENUM; a = abstract_decl2 { 602 | let name,tl,st,rl,l = a in 603 | (* TODO *) 604 | emit_abstract_decl annotations flags name tl st rl l (mk $startpos $endpos) 605 | } 606 | 607 | typedef_decl: 608 | | annotations = annotations; flags = common_flags*; TYPEDEF; name = pos(dollar_ident); tl = type_decl_parameters; ASSIGN; ct = complex_type; SEMICOLON? { 609 | emit_typedef_decl annotations flags name tl ct (mk $startpos $endpos) 610 | } 611 | 612 | abstract_decl: 613 | | annotations = annotations; flags = common_flags*; a = abstract_decl2 { 614 | let name,tl,st,rl,l = a in 615 | emit_abstract_decl annotations flags name tl st rl l (mk $startpos $endpos) 616 | } 617 | 618 | %inline decl: 619 | | import = import_decl { import } 620 | | using = using_decl { using } 621 | | c = class_decl { c } 622 | | en = enum_decl { en } 623 | | t = typedef_decl { t } 624 | | a = abstract_decl | a = enum_abstract_decl { a } 625 | 626 | (* File *) 627 | 628 | package: 629 | | PACKAGE; path = path?; SEMICOLON { emit_package path } 630 | 631 | file: 632 | | package = package?; decls = decl*; EOF { package,decls } 633 | 634 | (* Entry points *) 635 | 636 | expr_only: 637 | | expr = expr; EOF { expr } 638 | 639 | class_fields_only: 640 | | cff = class_field+; EOF { cff } 641 | 642 | class_decl_only: 643 | | c = class_decl2; EOF { 644 | emit_class_decl (emit_annotations None []) [] c (mk $startpos $endpos) 645 | } 646 | 647 | block_elements_only: 648 | | el = block_element+; EOF { el } 649 | 650 | unused: 651 | | WHITESPACE | COMMENTLINE | NEWLINE | NONSENSE | SHARPIF | SHARPELSE 652 | | SHARPELSEIF | SHARPEND | SHARPERROR | SHARPLINE | UNCLOSED { } -------------------------------------------------------------------------------- /src/context/meta.ml: -------------------------------------------------------------------------------- 1 | open Globals 2 | 3 | type strict_meta = 4 | | Abi 5 | | Abstract 6 | | Access 7 | | Accessor 8 | | Allow 9 | | Analyzer 10 | | Annotation 11 | | ArrayAccess 12 | | Ast 13 | | AstSource 14 | | AutoBuild 15 | | Bind 16 | | Bitmap 17 | | BridgeProperties 18 | | Build 19 | | BuildXml 20 | | Callable 21 | | Class 22 | | ClassCode 23 | | Commutative 24 | | CompilerGenerated 25 | | Const 26 | | CoreApi 27 | | CoreType 28 | | CppFileCode 29 | | CppInclude 30 | | CppNamespaceCode 31 | | CsNative 32 | | Dce 33 | | Debug 34 | | Decl 35 | | DefParam 36 | | Delegate 37 | | Depend 38 | | Deprecated 39 | | DirectlyUsed 40 | | DynamicObject 41 | | Eager 42 | | Enum 43 | | EnumConstructorParam 44 | | Event 45 | | Exhaustive 46 | | Expose 47 | | Extern 48 | | FakeEnum 49 | | File 50 | | FileXml 51 | | Final 52 | | Fixed 53 | | FlatEnum 54 | | Font 55 | | Forward 56 | | ForwardStatics 57 | | From 58 | | FunctionCode 59 | | FunctionTailCode 60 | | Generic 61 | | GenericBuild 62 | | GenericInstance 63 | | Getter 64 | | Hack 65 | | HasUntyped 66 | | HaxeGeneric 67 | | HeaderClassCode 68 | | HeaderCode 69 | | HeaderInclude 70 | | HeaderNamespaceCode 71 | | HxGen 72 | | IfFeature 73 | | Impl 74 | | PythonImport 75 | | ImplicitCast 76 | | Include 77 | | InitPackage 78 | | InlineConstructorVariable 79 | | Internal 80 | | IsVar 81 | | JavaCanonical 82 | | JavaNative 83 | | JsRequire 84 | | Keep 85 | | KeepInit 86 | | KeepSub 87 | | LibType 88 | | LuaRequire 89 | | Meta 90 | | Macro 91 | | MaybeUsed 92 | | MergeBlock 93 | | MultiReturn 94 | | MultiType 95 | | Native 96 | | NativeChildren 97 | | NativeGen 98 | | NativeGeneric 99 | | NativeProperty 100 | | NativeStaticExtension 101 | | NoCompletion 102 | | NoDebug 103 | | NoDoc 104 | | NoExpr 105 | | NoImportGlobal 106 | | NonVirtual 107 | | NoPackageRestrict 108 | | NoPrivateAccess 109 | | NoStack 110 | | NotNull 111 | | NoUsing 112 | | Ns 113 | | Objc 114 | | ObjcProtocol 115 | | Op 116 | | Optional 117 | | Overload 118 | | PhpConstants 119 | | PhpGlobal 120 | | PhpClassConst 121 | | PhpMagic 122 | | PhpNoConstructor 123 | | PrivateAccess 124 | | Property 125 | | Protected 126 | | Public 127 | | PublicFields 128 | | Pure 129 | | QuotedField 130 | | ReadOnly 131 | | RealPath 132 | | Remove 133 | | Require 134 | | RequiresAssign 135 | | Resolve 136 | | Rtti 137 | | Runtime 138 | | RuntimeValue 139 | | Scalar 140 | | SelfCall 141 | | Setter 142 | | SkipCtor 143 | | SkipReflection 144 | | Sound 145 | | SourceFile 146 | | StackOnly 147 | | StoredTypedExpr 148 | | Strict 149 | | Struct 150 | | StructAccess 151 | | StructInit 152 | | SuppressWarnings 153 | | This 154 | | Throws 155 | | To 156 | | ToString 157 | | Transient 158 | | TemplatedCall 159 | | ValueUsed 160 | | Volatile 161 | | Unbound 162 | | UnifyMinDynamic 163 | | Unreflective 164 | | Unsafe 165 | | Usage 166 | | Used 167 | | UserVariable 168 | | Value 169 | | Void 170 | | Last 171 | (* do not put any custom metadata after Last *) 172 | | Dollar of string 173 | | Custom of string 174 | 175 | let has m ml = List.exists (fun (m2,_,_) -> m = m2) ml 176 | let get m ml = List.find (fun (m2,_,_) -> m = m2) ml 177 | 178 | type meta_usage = 179 | | TClass 180 | | TClassField 181 | | TAbstract 182 | | TAbstractField 183 | | TEnum 184 | | TTypedef 185 | | TAnyField 186 | | TExpr 187 | | TTypeParameter 188 | 189 | type meta_parameter = 190 | | HasParam of string 191 | | Platform of platform 192 | | Platforms of platform list 193 | | UsedOn of meta_usage 194 | | UsedOnEither of meta_usage list 195 | | UsedInternally 196 | 197 | let get_info = function 198 | | Abi -> ":abi",("Function ABI/calling convention",[Platforms [Cpp]]) 199 | | Abstract -> ":abstract",("Sets the underlying class implementation as 'abstract'",[Platforms [Java;Cs]]) 200 | | Access -> ":access",("Forces private access to package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]]) 201 | | Accessor -> ":accessor",("Used internally by DCE to mark property accessors",[UsedOn TClassField;UsedInternally]) 202 | | Allow -> ":allow",("Allows private access from package, type or field",[HasParam "Target path";UsedOnEither [TClass;TClassField]]) 203 | | Analyzer -> ":analyzer",("Used to configure the static analyzer",[]) 204 | | Annotation -> ":annotation",("Annotation (@interface) definitions on -java-lib imports will be annotated with this metadata. Has no effect on types compiled by Haxe",[Platform Java; UsedOn TClass]) 205 | | ArrayAccess -> ":arrayAccess",("Allows [] access on an abstract",[UsedOnEither [TAbstract;TAbstractField]]) 206 | | Ast -> ":ast",("Internally used to pass the AST source into the typed AST",[UsedInternally]) 207 | | AstSource -> ":astSource",("Filled by the compiler with the parsed expression of the field",[UsedOn TClassField]) 208 | | AutoBuild -> ":autoBuild",("Extends @:build metadata to all extending and implementing classes",[HasParam "Build macro call";UsedOn TClass]) 209 | | Bind -> ":bind",("Override Swf class declaration",[Platform Flash;UsedOn TClass]) 210 | | Bitmap -> ":bitmap",("Embeds given bitmap data into the class (must extend flash.display.BitmapData)",[HasParam "Bitmap file path";UsedOn TClass;Platform Flash]) 211 | | BridgeProperties -> ":bridgeProperties",("Creates native property bridges for all Haxe properties in this class",[UsedOn TClass;Platform Cs]) 212 | | Build -> ":build",("Builds a class or enum from a macro",[HasParam "Build macro call";UsedOnEither [TClass;TEnum]]) 213 | | BuildXml -> ":buildXml",("Specify xml data to be injected into Build.xml",[Platform Cpp]) 214 | | Callable -> ":callable",("Abstract forwards call to its underlying type",[UsedOn TAbstract]) 215 | | Class -> ":class",("Used internally to annotate an enum that will be generated as a class",[Platforms [Java;Cs]; UsedOn TEnum; UsedInternally]) 216 | | ClassCode -> ":classCode",("Used to inject platform-native code into a class",[Platforms [Java;Cs]; UsedOn TClass]) 217 | | Commutative -> ":commutative",("Declares an abstract operator as commutative",[UsedOn TAbstractField]) 218 | | CompilerGenerated -> ":compilerGenerated",("Marks a field as generated by the compiler. Shouldn't be used by the end user",[Platforms [Java;Cs]]) 219 | | Const -> ":const",("Allows a type parameter to accept expression values",[UsedOn TTypeParameter]) 220 | | CoreApi -> ":coreApi",("Identifies this class as a core api class (forces Api check)",[UsedOnEither [TClass;TEnum;TTypedef;TAbstract]]) 221 | | CoreType -> ":coreType",("Identifies an abstract as core type so that it requires no implementation",[UsedOn TAbstract]) 222 | | CppFileCode -> ":cppFileCode",("Code to be injected into generated cpp file",[Platform Cpp]) 223 | | CppInclude -> ":cppInclude",("File to be included in generated cpp file",[Platform Cpp]) 224 | | CppNamespaceCode -> ":cppNamespaceCode",("",[Platform Cpp]) 225 | | CsNative -> ":csNative",("Automatically added by -net-lib on classes generated from .NET DLL files",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) 226 | | Dce -> ":dce",("Forces dead code elimination even when -dce full is not specified",[UsedOnEither [TClass;TEnum]]) 227 | | Debug -> ":debug",("Forces debug information to be generated into the Swf even without -debug",[UsedOnEither [TClass;TClassField]; Platform Flash]) 228 | | Decl -> ":decl",("",[Platform Cpp]) 229 | | DefParam -> ":defParam",("Default function argument value loaded from the SWF and used for documentation in Genxml",[Platform Flash;UsedInternally]) 230 | | Delegate -> ":delegate",("Automatically added by -net-lib on delegates",[Platform Cs; UsedOn TAbstract]) 231 | | Depend -> ":depend",("",[Platform Cpp]) 232 | | Deprecated -> ":deprecated",("Mark a type or field as deprecated",[]) 233 | | DirectlyUsed -> ":directlyUsed",("Marks types that are directly referenced by non-extern code",[UsedInternally]) 234 | | DynamicObject -> ":dynamicObject",("Used internally to identify the Dynamic Object implementation",[Platforms [Java;Cs]; UsedOn TClass; UsedInternally]) 235 | | Eager -> ":eager",("Forces typedefs to be followed early",[UsedOn TTypedef]) 236 | | Enum -> ":enum",("Defines finite value sets to abstract definitions",[UsedOn TAbstract]) 237 | | EnumConstructorParam -> ":enumConstructorParam",("Used internally to annotate GADT type parameters",[UsedOn TClass; UsedInternally]) 238 | | Event -> ":event",("Automatically added by -net-lib on events. Has no effect on types compiled by Haxe",[Platform Cs; UsedOn TClassField]) 239 | | Exhaustive -> ":exhaustive",("",[UsedInternally]) 240 | | Expose -> ":expose",("Makes the class available on the window object",[HasParam "?Name=Class path";UsedOn TClass;Platform Js]) 241 | | Extern -> ":extern",("Marks the field as extern so it is not generated",[UsedOn TClassField]) 242 | | FakeEnum -> ":fakeEnum",("Treat enum as collection of values of the specified type",[HasParam "Type name";UsedOn TEnum]) 243 | | File -> ":file",("Includes a given binary file into the target Swf and associates it with the class (must extend flash.utils.ByteArray)",[HasParam "File path";UsedOn TClass;Platform Flash]) 244 | | FileXml -> ":fileXml",("Include xml attribute snippet in Build.xml entry for file",[UsedOn TClass;Platform Cpp]) 245 | | Final -> ":final",("Prevents a class from being extended",[UsedOn TClass]) 246 | | Fixed -> ":fixed",("Delcares an anonymous object to have fixed fields",[ (*UsedOn TObjectDecl(_)*)]) 247 | | FlatEnum -> ":flatEnum",("Internally used to mark an enum as being flat, i.e. having no function constructors",[UsedOn TEnum; UsedInternally]) 248 | | Font -> ":font",("Embeds the given TrueType font into the class (must extend flash.text.Font)",[HasParam "TTF path";HasParam "Range String";UsedOn TClass]) 249 | | Forward -> ":forward",("Forwards field access to underlying type",[HasParam "List of field names";UsedOn TAbstract]) 250 | | ForwardStatics -> ":forwardStatics",("Forwards static field access to underlying type",[HasParam "List of field names";UsedOn TAbstract]) 251 | | From -> ":from",("Specifies that the field of the abstract is a cast operation from the type identified in the function",[UsedOn TAbstractField]) 252 | | FunctionCode -> ":functionCode",("Used to inject platform-native code into a function",[Platforms [Cpp;Java;Cs]]) 253 | | FunctionTailCode -> ":functionTailCode",("",[Platform Cpp]) 254 | | Generic -> ":generic",("Marks a class or class field as generic so each type parameter combination generates its own type/field",[UsedOnEither [TClass;TClassField]]) 255 | | GenericBuild -> ":genericBuild",("Builds instances of a type using the specified macro",[UsedOn TClass]) 256 | | GenericInstance -> ":genericInstance",("Internally used to mark instances of @:generic methods",[UsedOn TClassField;UsedInternally]) 257 | | Getter -> ":getter",("Generates a native getter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash]) 258 | | Hack -> ":hack",("Allows extending classes marked as @:final",[UsedOn TClass]) 259 | | HasUntyped -> (":has_untyped",("Used by the typer to mark fields that have untyped expressions",[UsedInternally])) 260 | | HaxeGeneric -> ":haxeGeneric",("Used internally to annotate non-native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) 261 | | HeaderClassCode -> ":headerClassCode",("Code to be injected into the generated class, in the header",[Platform Cpp]) 262 | | HeaderCode -> ":headerCode",("Code to be injected into the generated header file",[Platform Cpp]) 263 | | HeaderInclude -> ":headerInclude",("File to be included in generated header file",[Platform Cpp]) 264 | | HeaderNamespaceCode -> ":headerNamespaceCode",("",[Platform Cpp]) 265 | | HxGen -> ":hxGen",("Annotates that an extern class was generated by Haxe",[Platforms [Java;Cs]; UsedOnEither [TClass;TEnum]]) 266 | | IfFeature -> ":ifFeature",("Causes a field to be kept by DCE if the given feature is part of the compilation",[HasParam "Feature name";UsedOn TClassField]) 267 | | Impl -> ":impl",("Used internally to mark abstract implementation fields",[UsedOn TAbstractField; UsedInternally]) 268 | | PythonImport -> ":pythonImport",("Generates python import statement for extern classes",[Platforms [Python]; UsedOn TClass]) 269 | | ImplicitCast -> ":implicitCast",("Generated automatically on the AST when an implicit abstract cast happens",[UsedInternally; UsedOn TExpr]) 270 | | Include -> ":include",("",[Platform Cpp]) 271 | | InitPackage -> ":initPackage",("Some weird thing for Genjs we want to remove someday",[UsedInternally; Platform Js]) 272 | | InlineConstructorVariable -> ":inlineConstructorVariable",("Internally used to mark variables that come from inlined constructors",[UsedInternally]) 273 | | Internal -> ":internal",("Generates the annotated field/class with 'internal' access",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum;TClassField]]) 274 | | IsVar -> ":isVar",("Forces a physical field to be generated for properties that otherwise would not require one",[UsedOn TClassField]) 275 | | JavaCanonical -> ":javaCanonical",("Used by the Java target to annotate the canonical path of the type",[HasParam "Output type package";HasParam "Output type name";UsedOnEither [TClass;TEnum]; Platform Java]) 276 | | JavaNative -> ":javaNative",("Automatically added by -java-lib on classes generated from JAR/class files",[Platform Java; UsedOnEither[TClass;TEnum]; UsedInternally]) 277 | | JsRequire -> ":jsRequire",("Generate javascript module require expression for given extern",[Platform Js; UsedOn TClass]) 278 | | LuaRequire -> ":luaRequire",("Generate lua module require expression for given extern",[Platform Lua; UsedOn TClass]) 279 | | Keep -> ":keep",("Causes a field or type to be kept by DCE",[]) 280 | | KeepInit -> ":keepInit",("Causes a class to be kept by DCE even if all its field are removed",[UsedOn TClass]) 281 | | KeepSub -> ":keepSub",("Extends @:keep metadata to all implementing and extending classes",[UsedOn TClass]) 282 | | LibType -> ":libType",("Used by -net-lib and -java-lib to mark a class that shouldn't be checked (overrides, interfaces, etc) by the type loader",[UsedInternally; UsedOn TClass; Platforms [Java;Cs]]) 283 | | Meta -> ":meta",("Internally used to mark a class field as being the metadata field",[]) 284 | | Macro -> ":macro",("(deprecated)",[]) 285 | | MaybeUsed -> ":maybeUsed",("Internally used by DCE to mark fields that might be kept",[UsedInternally]) 286 | | MergeBlock -> ":mergeBlock",("Merge the annotated block into the current scope",[UsedOn TExpr]) 287 | | MultiReturn -> ":multiReturn",("Annotates an extern class as the result of multi-return function",[UsedOn TClass; Platform Lua]) 288 | | MultiType -> ":multiType",("Specifies that an abstract chooses its this-type from its @:to functions",[UsedOn TAbstract; HasParam "Relevant type parameters"]) 289 | | Native -> ":native",("Rewrites the path of a class or enum during generation",[HasParam "Output type path";UsedOnEither [TClass;TEnum]]) 290 | | NativeChildren -> ":nativeChildren",("Annotates that all children from a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs]; UsedOn TClass]) 291 | | NativeGen -> ":nativeGen",("Annotates that a type should be treated as if it were an extern definition - platform native",[Platforms [Java;Cs;Python]; UsedOnEither[TClass;TEnum]]) 292 | | NativeGeneric -> ":nativeGeneric",("Used internally to annotate native generic classes",[Platform Cs; UsedOnEither[TClass;TEnum]; UsedInternally]) 293 | | NativeProperty -> ":nativeProperty",("Use native properties which will execute even with dynamic usage",[Platform Cpp]) 294 | | NativeStaticExtension -> ":nativeStaticExtension",("Converts static function syntax into member call",[Platform Cpp]) 295 | | NoCompletion -> ":noCompletion",("Prevents the compiler from suggesting completion on this field",[UsedOn TClassField]) 296 | | NoDebug -> ":noDebug",("Does not generate debug information into the Swf even if -debug is set",[UsedOnEither [TClass;TClassField];Platform Flash]) 297 | | NoDoc -> ":noDoc",("Prevents a type from being included in documentation generation",[]) 298 | | NoExpr -> ":noExpr",("Internally used to mark abstract fields which have no expression by design",[UsedInternally]) 299 | | NoImportGlobal -> ":noImportGlobal",("Prevents a static field from being imported with import Class.*",[UsedOn TAnyField]) 300 | | NonVirtual -> ":nonVirtual",("Declares function to be non-virtual in cpp",[Platform Cpp]) 301 | | NoPackageRestrict -> ":noPackageRestrict",("Allows a module to be accessed across all targets if found on its first type",[UsedInternally]) 302 | | NoPrivateAccess -> ":noPrivateAccess",("Disallow private access to anything for the annotated expression",[UsedOn TExpr]) 303 | | NoStack -> ":noStack",("",[Platform Cpp]) 304 | | NotNull -> ":notNull",("Declares an abstract type as not accepting null values",[UsedOn TAbstract]) 305 | | NoUsing -> ":noUsing",("Prevents a field from being used with 'using'",[UsedOn TClassField]) 306 | | Ns -> ":ns",("Internally used by the Swf generator to handle namespaces",[Platform Flash]) 307 | | Objc -> ":objc",("Declares a class or interface that is used to interoperate with Objective-C code",[Platform Cpp;UsedOn TClass]) 308 | | ObjcProtocol -> ":objcProtocol",("Associates an interface with, or describes a function in, a native Objective-C protocol.",[Platform Cpp;UsedOnEither [TClass;TClassField] ]) 309 | | Op -> ":op",("Declares an abstract field as being an operator overload",[HasParam "The operation";UsedOn TAbstractField]) 310 | | Optional -> ":optional",("Marks the field of a structure as optional",[UsedOn TClassField]) 311 | | Overload -> ":overload",("Allows the field to be called with different argument types",[HasParam "Function specification (no expression)";UsedOn TClassField]) 312 | | PhpConstants -> ":phpConstants",("Marks the static fields of a class as PHP constants, without $",[Platform Php;UsedOn TClass]) 313 | | PhpGlobal -> ":phpGlobal",("(php7) Puts the static fields of a class in the global PHP namespace",[Platforms [Php;Php];UsedOn TClass]) 314 | | PhpClassConst -> ":phpClassConst",("(php7) Generate static var of an extern class as a PHP class constant",[Platform Php;UsedOn TClass]) 315 | | PhpMagic -> ":phpMagic",("(php7) Treat annotated field as special PHP magic field",[Platform Php;UsedOn TClassField]) 316 | | PhpNoConstructor -> ":phpNoConstructor",("(php7) Special meta for extern classes which does not have native constructor in PHP, but need a constructor in Haxe extern",[Platform Php;UsedOn TClass]) 317 | | Public -> ":public",("Marks a class field as being public",[UsedOn TClassField;UsedInternally]) 318 | | PublicFields -> ":publicFields",("Forces all class fields of inheriting classes to be public",[UsedOn TClass]) 319 | | QuotedField -> ":quotedField",("Used internally to mark structure fields which are quoted in syntax",[UsedInternally]) 320 | | PrivateAccess -> ":privateAccess",("Allow private access to anything for the annotated expression",[UsedOn TExpr]) 321 | | Protected -> ":protected",("Marks a class field as being protected",[UsedOn TClassField;Platforms [Cs;Java;Flash]]) 322 | | Property -> ":property",("Marks a property field to be compiled as a native C# property",[UsedOn TClassField;Platform Cs]) 323 | | Pure -> ":pure",("Marks a class field, class or expression as pure (side-effect free)",[UsedOnEither [TClass;TClassField;TExpr]]) 324 | | ReadOnly -> ":readOnly",("Generates a field with the 'readonly' native keyword",[Platform Cs; UsedOn TClassField]) 325 | | RealPath -> ":realPath",("Internally used on @:native types to retain original path information",[UsedInternally]) 326 | | Remove -> ":remove",("Causes an interface to be removed from all implementing classes before generation",[UsedOn TClass]) 327 | | Require -> ":require",("Allows access to a field only if the specified compiler flag is set",[HasParam "Compiler flag to check";UsedOn TClassField]) 328 | | RequiresAssign -> ":requiresAssign",("Used internally to mark certain abstract operator overloads",[UsedInternally]) 329 | | Resolve -> ":resolve",("Abstract fields marked with this metadata can be used to resolve unknown fields",[UsedOn TClassField]) 330 | | Rtti -> ":rtti",("Adds runtime type informations",[UsedOn TClass]) 331 | | Runtime -> ":runtime",("?",[]) 332 | | RuntimeValue -> ":runtimeValue",("Marks an abstract as being a runtime value",[UsedOn TAbstract]) 333 | | Scalar -> ":scalar",("Used by hxcpp to mark a custom coreType abstract",[UsedOn TAbstract; Platform Cpp]) 334 | | SelfCall -> ":selfCall",("Translates method calls into calling object directly",[UsedOn TClassField; Platform Js]) 335 | | Setter -> ":setter",("Generates a native setter function on the given field",[HasParam "Class field name";UsedOn TClassField;Platform Flash]) 336 | | StackOnly -> ":stackOnly",("Instances of this type can only appear on the stack",[Platform Cpp]) 337 | | StoredTypedExpr -> ":storedTypedExpr",("Used internally to reference a typed expression returned from a macro",[UsedInternally]) 338 | | SkipCtor -> ":skipCtor",("Used internally to generate a constructor as if it were a native type (no __hx_ctor)",[Platforms [Java;Cs]; UsedInternally]) 339 | | SkipReflection -> ":skipReflection",("Used internally to annotate a field that shouldn't have its reflection data generated",[Platforms [Java;Cs]; UsedOn TClassField; UsedInternally]) 340 | | Sound -> ":sound",( "Includes a given .wav or .mp3 file into the target Swf and associates it with the class (must extend flash.media.Sound)",[HasParam "File path";UsedOn TClass;Platform Flash]) 341 | | SourceFile -> ":sourceFile",("Source code filename for external class",[Platform Cpp]) 342 | | Strict -> ":strict",("Used to declare a native C# attribute or a native Java metadata. Is type checked",[Platforms [Java;Cs]]) 343 | | Struct -> ":struct",("Marks a class definition as a struct",[Platform Cs; UsedOn TClass]) 344 | | StructAccess -> ":structAccess",("Marks an extern class as using struct access('.') not pointer('->')",[Platform Cpp; UsedOn TClass]) 345 | | StructInit -> ":structInit",("Allows to initialize the class with a structure that matches constructor parameters",[UsedOn TClass]) 346 | | SuppressWarnings -> ":suppressWarnings",("Adds a SuppressWarnings annotation for the generated Java class",[Platform Java; UsedOn TClass]) 347 | | TemplatedCall -> ":templatedCall",("Indicates that the first parameter of static call should be treated as a template arguement",[Platform Cpp; UsedOn TClassField]) 348 | | Throws -> ":throws",("Adds a 'throws' declaration to the generated function",[HasParam "Type as String"; Platform Java; UsedOn TClassField]) 349 | | This -> ":this",("Internally used to pass a 'this' expression to macros",[UsedInternally; UsedOn TExpr]) 350 | | To -> ":to",("Specifies that the field of the abstract is a cast operation to the type identified in the function",[UsedOn TAbstractField]) 351 | | ToString -> ":toString",("Internally used",[UsedInternally]) 352 | | Transient -> ":transient",("Adds the 'transient' flag to the class field",[Platform Java; UsedOn TClassField]) 353 | | ValueUsed -> ":valueUsed",("Internally used by DCE to mark an abstract value as used",[UsedInternally]) 354 | | Volatile -> ":volatile",("",[Platforms [Java;Cs]]) 355 | | Unbound -> ":unbound", ("Compiler internal to denote unbounded global variable",[UsedInternally]) 356 | | UnifyMinDynamic -> ":unifyMinDynamic",("Allows a collection of types to unify to Dynamic",[UsedOn TClassField]) 357 | | Unreflective -> ":unreflective",("",[Platform Cpp]) 358 | | Unsafe -> ":unsafe",("Declares a class, or a method with the C#'s 'unsafe' flag",[Platform Cs; UsedOnEither [TClass;TClassField]]) 359 | | Usage -> ":usage",("Internal metadata used to mark a symbol for which usage request was invoked",[UsedInternally]) 360 | | Used -> ":used",("Internally used by DCE to mark a class or field as used",[UsedInternally]) 361 | | UserVariable -> ":userVariable",("Internally used to mark variables that come from user code",[UsedInternally]) 362 | | Value -> ":value",("Used to store default values for fields and function arguments",[UsedOn TClassField]) 363 | | Void -> ":void",("Use Cpp native 'void' return type",[Platform Cpp]) 364 | | Last -> assert false 365 | (* do not put any custom metadata after Last *) 366 | | Dollar s -> "$" ^ s,("",[]) 367 | | Custom s -> s,("",[]) 368 | 369 | let to_string m = fst (get_info m) 370 | 371 | let hmeta = 372 | let h = Hashtbl.create 0 in 373 | let rec loop i = 374 | let m = Obj.magic i in 375 | if m <> Last then begin 376 | Hashtbl.add h (fst (get_info m)) m; 377 | loop (i + 1); 378 | end; 379 | in 380 | loop 0; 381 | h 382 | 383 | let parse s = try Hashtbl.find hmeta (":" ^ s) with Not_found -> Custom (":" ^ s) 384 | 385 | let from_string s = 386 | if s = "" then Custom "" else match s.[0] with 387 | | ':' -> (try Hashtbl.find hmeta s with Not_found -> Custom s) 388 | | '$' -> Dollar (String.sub s 1 (String.length s - 1)) 389 | | _ -> Custom s 390 | 391 | let get_documentation d = 392 | let t, (doc,flags) = get_info d in 393 | if not (List.mem UsedInternally flags) then begin 394 | let params = ref [] and used = ref [] and pfs = ref [] in 395 | List.iter (function 396 | | HasParam s -> params := s :: !params 397 | | Platform f -> pfs := f :: !pfs 398 | | Platforms fl -> pfs := fl @ !pfs 399 | | UsedOn u -> used := u :: !used 400 | | UsedOnEither ul -> used := ul @ !used 401 | | UsedInternally -> assert false 402 | ) flags; 403 | let params = (match List.rev !params with 404 | | [] -> "" 405 | | l -> "(" ^ String.concat "," l ^ ")" 406 | ) in 407 | let pfs = (match List.rev !pfs with 408 | | [] -> "" 409 | | [p] -> " (" ^ platform_name p ^ " only)" 410 | | pl -> " (for " ^ String.concat "," (List.map platform_name pl) ^ ")" 411 | ) in 412 | let str = "@" ^ t in 413 | Some (str,params ^ doc ^ pfs) 414 | end else 415 | None 416 | 417 | let get_documentation_list () = 418 | let m = ref 0 in 419 | let rec loop i = 420 | let d = Obj.magic i in 421 | if d <> Last then begin match get_documentation d with 422 | | None -> loop (i + 1) 423 | | Some (str,desc) -> 424 | if String.length str > !m then m := String.length str; 425 | (str,desc) :: loop (i + 1) 426 | end else 427 | [] 428 | in 429 | let all = List.sort (fun (s1,_) (s2,_) -> String.compare s1 s2) (loop 0) in 430 | all,!m -------------------------------------------------------------------------------- /src/syntax/syntaxErrors.ml: -------------------------------------------------------------------------------- 1 | 2 | (* This file was auto-generated based on "haxe.messages". *) 3 | 4 | (* Please note that the function [message] can raise [Not_found]. *) 5 | 6 | let message = 7 | fun s -> 8 | match s with 9 | | 0 -> 10 | "\n" 11 | | 1 -> 12 | "\n" 13 | | 2 -> 14 | "\n" 15 | | 600 -> 16 | "\n" 17 | | 601 -> 18 | "\n" 19 | | 602 -> 20 | "\n" 21 | | 3 -> 22 | "\n" 23 | | 12 -> 24 | "\n" 25 | | 597 -> 26 | "\n" 27 | | 425 -> 28 | "\n" 29 | | 426 -> 30 | "\n" 31 | | 428 -> 32 | "\n" 33 | | 28 -> 34 | "\n" 35 | | 29 -> 36 | "\n" 37 | | 31 -> 38 | "\n" 39 | | 32 -> 40 | "\n" 41 | | 33 -> 42 | "\n" 43 | | 559 -> 44 | "\n" 45 | | 34 -> 46 | "\n" 47 | | 35 -> 48 | "\n" 49 | | 36 -> 50 | "\n" 51 | | 37 -> 52 | "\n" 53 | | 38 -> 54 | "\n" 55 | | 39 -> 56 | "\n" 57 | | 554 -> 58 | "\n" 59 | | 557 -> 60 | "\n" 61 | | 561 -> 62 | "\n" 63 | | 159 -> 64 | "\n" 65 | | 160 -> 66 | "\n" 67 | | 607 -> 68 | "\n" 69 | | 163 -> 70 | "\n" 71 | | 164 -> 72 | "\n" 73 | | 169 -> 74 | "\n" 75 | | 170 -> 76 | "\n" 77 | | 190 -> 78 | "\n" 79 | | 191 -> 80 | "\n" 81 | | 167 -> 82 | "\n" 83 | | 350 -> 84 | "\n" 85 | | 351 -> 86 | "\n" 87 | | 352 -> 88 | "\n" 89 | | 57 -> 90 | "\n" 91 | | 523 -> 92 | "\n" 93 | | 194 -> 94 | "\n" 95 | | 195 -> 96 | "\n" 97 | | 173 -> 98 | "\n" 99 | | 174 -> 100 | "\n" 101 | | 205 -> 102 | "\n" 103 | | 206 -> 104 | "\n" 105 | | 210 -> 106 | "\n" 107 | | 211 -> 108 | "\n" 109 | | 199 -> 110 | "\n" 111 | | 200 -> 112 | "\n" 113 | | 220 -> 114 | "\n" 115 | | 221 -> 116 | "\n" 117 | | 225 -> 118 | "\n" 119 | | 226 -> 120 | "\n" 121 | | 230 -> 122 | "\n" 123 | | 231 -> 124 | "\n" 125 | | 345 -> 126 | "\n" 127 | | 346 -> 128 | "\n" 129 | | 234 -> 130 | "\n" 131 | | 235 -> 132 | "\n" 133 | | 237 -> 134 | "\n" 135 | | 238 -> 136 | "\n" 137 | | 240 -> 138 | "\n" 139 | | 241 -> 140 | "\n" 141 | | 243 -> 142 | "\n" 143 | | 244 -> 144 | "\n" 145 | | 330 -> 146 | "\n" 147 | | 331 -> 148 | "\n" 149 | | 337 -> 150 | "\n" 151 | | 338 -> 152 | "\n" 153 | | 247 -> 154 | "\n" 155 | | 248 -> 156 | "\n" 157 | | 252 -> 158 | "\n" 159 | | 253 -> 160 | "\n" 161 | | 256 -> 162 | "\n" 163 | | 257 -> 164 | "\n" 165 | | 260 -> 166 | "\n" 167 | | 261 -> 168 | "\n" 169 | | 181 -> 170 | "\n" 171 | | 183 -> 172 | "\n" 173 | | 267 -> 174 | "\n" 175 | | 268 -> 176 | "\n" 177 | | 271 -> 178 | "\n" 179 | | 272 -> 180 | "\n" 181 | | 275 -> 182 | "\n" 183 | | 276 -> 184 | "\n" 185 | | 279 -> 186 | "\n" 187 | | 280 -> 188 | "\n" 189 | | 283 -> 190 | "\n" 191 | | 284 -> 192 | "\n" 193 | | 287 -> 194 | "\n" 195 | | 288 -> 196 | "\n" 197 | | 291 -> 198 | "\n" 199 | | 292 -> 200 | "\n" 201 | | 295 -> 202 | "\n" 203 | | 296 -> 204 | "\n" 205 | | 299 -> 206 | "\n" 207 | | 300 -> 208 | "\n" 209 | | 303 -> 210 | "\n" 211 | | 304 -> 212 | "\n" 213 | | 307 -> 214 | "\n" 215 | | 308 -> 216 | "\n" 217 | | 311 -> 218 | "\n" 219 | | 312 -> 220 | "\n" 221 | | 214 -> 222 | "\n" 223 | | 215 -> 224 | "\n" 225 | | 42 -> 226 | "\n" 227 | | 43 -> 228 | "\n" 229 | | 45 -> 230 | "\n" 231 | | 46 -> 232 | "\n" 233 | | 49 -> 234 | "\n" 235 | | 529 -> 236 | "\n" 237 | | 530 -> 238 | "\n" 239 | | 531 -> 240 | "\n" 241 | | 532 -> 242 | "\n" 243 | | 534 -> 244 | "\n" 245 | | 536 -> 246 | "\n" 247 | | 537 -> 248 | "\n" 249 | | 538 -> 250 | "\n" 251 | | 539 -> 252 | "\n" 253 | | 540 -> 254 | "\n" 255 | | 542 -> 256 | "\n" 257 | | 543 -> 258 | "\n" 259 | | 51 -> 260 | "\n" 261 | | 53 -> 262 | "\n" 263 | | 526 -> 264 | "\n" 265 | | 388 -> 266 | "\n" 267 | | 389 -> 268 | "\n" 269 | | 394 -> 270 | "\n" 271 | | 395 -> 272 | "\n" 273 | | 55 -> 274 | "\n" 275 | | 56 -> 276 | "\n" 277 | | 22 -> 278 | "\n" 279 | | 571 -> 280 | "\n" 281 | | 568 -> 282 | "\n" 283 | | 567 -> 284 | "\n" 285 | | 27 -> 286 | "\n" 287 | | 58 -> 288 | "\n" 289 | | 59 -> 290 | "\n" 291 | | 61 -> 292 | "\n" 293 | | 518 -> 294 | "\n" 295 | | 516 -> 296 | "\n" 297 | | 519 -> 298 | "\n" 299 | | 152 -> 300 | "\n" 301 | | 153 -> 302 | "\n" 303 | | 63 -> 304 | "\n" 305 | | 64 -> 306 | "\n" 307 | | 67 -> 308 | "\n" 309 | | 66 -> 310 | "\n" 311 | | 453 -> 312 | "\n" 313 | | 13 -> 314 | "\n" 315 | | 595 -> 316 | "\n" 317 | | 106 -> 318 | "\n" 319 | | 14 -> 320 | "\n" 321 | | 15 -> 322 | "\n" 323 | | 593 -> 324 | "\n" 325 | | 16 -> 326 | "\n" 327 | | 586 -> 328 | "\n" 329 | | 578 -> 330 | "\n" 331 | | 579 -> 332 | "\n" 333 | | 580 -> 334 | "\n" 335 | | 581 -> 336 | "\n" 337 | | 577 -> 338 | "\n" 339 | | 18 -> 340 | "\n" 341 | | 19 -> 342 | "\n" 343 | | 575 -> 344 | "\n" 345 | | 71 -> 346 | "\n" 347 | | 73 -> 348 | "\n" 349 | | 74 -> 350 | "\n" 351 | | 76 -> 352 | "\n" 353 | | 77 -> 354 | "\n" 355 | | 433 -> 356 | "\n" 357 | | 434 -> 358 | "\n" 359 | | 435 -> 360 | "\n" 361 | | 436 -> 362 | "\n" 363 | | 444 -> 364 | "\n" 365 | | 437 -> 366 | "\n" 367 | | 438 -> 368 | "\n" 369 | | 440 -> 370 | "\n" 371 | | 446 -> 372 | "\n" 373 | | 78 -> 374 | "\n" 375 | | 79 -> 376 | "\n" 377 | | 113 -> 378 | "\n" 379 | | 423 -> 380 | "\n" 381 | | 419 -> 382 | "\n" 383 | | 424 -> 384 | "\n" 385 | | 418 -> 386 | "\n" 387 | | 422 -> 388 | "\n" 389 | | 116 -> 390 | "\n" 391 | | 119 -> 392 | "\n" 393 | | 416 -> 394 | "\n" 395 | | 118 -> 396 | "\n" 397 | | 421 -> 398 | "\n" 399 | | 80 -> 400 | "\n" 401 | | 90 -> 402 | "\n" 403 | | 83 -> 404 | "\n" 405 | | 91 -> 406 | "\n" 407 | | 108 -> 408 | "\n" 409 | | 92 -> 410 | "\n" 411 | | 98 -> 412 | "\n" 413 | | 100 -> 414 | "\n" 415 | | 103 -> 416 | "\n" 417 | | 104 -> 418 | "\n" 419 | | 82 -> 420 | "\n" 421 | | 89 -> 422 | "\n" 423 | | 112 -> 424 | "\n" 425 | | 121 -> 426 | "\n" 427 | | 122 -> 428 | "\n" 429 | | 410 -> 430 | "\n" 431 | | 411 -> 432 | "\n" 433 | | 412 -> 434 | "\n" 435 | | 124 -> 436 | "\n" 437 | | 125 -> 438 | "\n" 439 | | 128 -> 440 | "\n" 441 | | 406 -> 442 | "\n" 443 | | 129 -> 444 | "\n" 445 | | 402 -> 446 | "\n" 447 | | 403 -> 448 | "\n" 449 | | 404 -> 450 | "\n" 451 | | 401 -> 452 | "\n" 453 | | 130 -> 454 | "\n" 455 | | 131 -> 456 | "\n" 457 | | 134 -> 458 | "\n" 459 | | 135 -> 460 | "\n" 461 | | 137 -> 462 | "\n" 463 | | 386 -> 464 | "\n" 465 | | 391 -> 466 | "\n" 467 | | 392 -> 468 | "\n" 469 | | 138 -> 470 | "\n" 471 | | 139 -> 472 | "\n" 473 | | 140 -> 474 | "\n" 475 | | 380 -> 476 | "\n" 477 | | 384 -> 478 | "\n" 479 | | 379 -> 480 | "\n" 481 | | 366 -> 482 | "\n" 483 | | 368 -> 484 | "\n" 485 | | 369 -> 486 | "\n" 487 | | 365 -> 488 | "\n" 489 | | 372 -> 490 | "\n" 491 | | 142 -> 492 | "\n" 493 | | 382 -> 494 | "\n" 495 | | 143 -> 496 | "\n" 497 | | 144 -> 498 | "\n" 499 | | 145 -> 500 | "\n" 501 | | 150 -> 502 | "\n" 503 | | 360 -> 504 | "\n" 505 | | 359 -> 506 | "\n" 507 | | 609 -> 508 | "\n" 509 | | 621 -> 510 | "\n" 511 | | 618 -> 512 | "\n" 513 | | 622 -> 514 | "\n" 515 | | 641 -> 516 | "\n" 517 | | 642 -> 518 | "\n" 519 | | 643 -> 520 | "\n" 521 | | 644 -> 522 | "\n" 523 | | 645 -> 524 | "\n" 525 | | 690 -> 526 | "\n" 527 | | 610 -> 528 | "\n" 529 | | 94 -> 530 | "\n" 531 | | 612 -> 532 | "\n" 533 | | 95 -> 534 | "\n" 535 | | 615 -> 536 | "\n" 537 | | 86 -> 538 | "\n" 539 | | 620 -> 540 | "\n" 541 | | 455 -> 542 | "\n" 543 | | 456 -> 544 | "\n" 545 | | 457 -> 546 | "\n" 547 | | 458 -> 548 | "\n" 549 | | 511 -> 550 | "\n" 551 | | 460 -> 552 | "\n" 553 | | 463 -> 554 | "\n" 555 | | 479 -> 556 | "\n" 557 | | 480 -> 558 | "\n" 559 | | 466 -> 560 | "\n" 561 | | 481 -> 562 | "\n" 563 | | 485 -> 564 | "\n" 565 | | 486 -> 566 | "\n" 567 | | 487 -> 568 | "\n" 569 | | 488 -> 570 | "\n" 571 | | 489 -> 572 | "\n" 573 | | 490 -> 574 | "\n" 575 | | 493 -> 576 | "\n" 577 | | 494 -> 578 | "\n" 579 | | 476 -> 580 | "\n" 581 | | 468 -> 582 | "\n" 583 | | 496 -> 584 | "\n" 585 | | 498 -> 586 | "\n" 587 | | 500 -> 588 | "\n" 589 | | 503 -> 590 | "\n" 591 | | 507 -> 592 | "\n" 593 | | 504 -> 594 | "\n" 595 | | 499 -> 596 | "\n" 597 | | 629 -> 598 | "\n" 599 | | 624 -> 600 | "\n" 601 | | 631 -> 602 | "\n" 603 | | 625 -> 604 | "\n" 605 | | 637 -> 606 | "\n" 607 | | 634 -> 608 | "\n" 609 | | 648 -> 610 | "\n" 611 | | 649 -> 612 | "\n" 613 | | 650 -> 614 | "\n" 615 | | 651 -> 616 | "\n" 617 | | 657 -> 618 | "\n" 619 | | 654 -> 620 | "\n" 621 | | 659 -> 622 | "\n" 623 | | 663 -> 624 | "\n" 625 | | 665 -> 626 | "\n" 627 | | 668 -> 628 | "\n" 629 | | 666 -> 630 | "\n" 631 | | 662 -> 632 | "\n" 633 | | 658 -> 634 | "\n" 635 | | 669 -> 636 | "\n" 637 | | 656 -> 638 | "\n" 639 | | 85 -> 640 | "\n" 641 | | 671 -> 642 | "\n" 643 | | 672 -> 644 | "\n" 645 | | 679 -> 646 | "\n" 647 | | 680 -> 648 | "\n" 649 | | 674 -> 650 | "\n" 651 | | 675 -> 652 | "\n" 653 | | 678 -> 654 | "\n" 655 | | 673 -> 656 | "\n" 657 | | 681 -> 658 | "\n" 659 | | 682 -> 660 | "\n" 661 | | 684 -> 662 | "\n" 663 | | 693 -> 664 | "\n" 665 | | 696 -> 666 | "\n" 667 | | 700 -> 668 | "\n" 669 | | 717 -> 670 | "\n" 671 | | 718 -> 672 | "\n" 673 | | 789 -> 674 | "\n" 675 | | 719 -> 676 | "\n" 677 | | 720 -> 678 | "\n" 679 | | 723 -> 680 | "\n" 681 | | 724 -> 682 | "\n" 683 | | 725 -> 684 | "\n" 685 | | 726 -> 686 | "\n" 687 | | 727 -> 688 | "\n" 689 | | 728 -> 690 | "\n" 691 | | 721 -> 692 | "\n" 693 | | 732 -> 694 | "\n" 695 | | 733 -> 696 | "\n" 697 | | 734 -> 698 | "\n" 699 | | 735 -> 700 | "\n" 701 | | 729 -> 702 | "\n" 703 | | 730 -> 704 | "\n" 705 | | 738 -> 706 | "\n" 707 | | 739 -> 708 | "\n" 709 | | 740 -> 710 | "\n" 711 | | 741 -> 712 | "\n" 713 | | 742 -> 714 | "\n" 715 | | 743 -> 716 | "\n" 717 | | 744 -> 718 | "\n" 719 | | 787 -> 720 | "\n" 721 | | 745 -> 722 | "\n" 723 | | 784 -> 724 | "\n" 725 | | 746 -> 726 | "\n" 727 | | 781 -> 728 | "\n" 729 | | 747 -> 730 | "\n" 731 | | 748 -> 732 | "\n" 733 | | 782 -> 734 | "\n" 735 | | 783 -> 736 | "\n" 737 | | 785 -> 738 | "\n" 739 | | 786 -> 740 | "\n" 741 | | 749 -> 742 | "\n" 743 | | 750 -> 744 | "\n" 745 | | 751 -> 746 | "\n" 747 | | 752 -> 748 | "\n" 749 | | 753 -> 750 | "\n" 751 | | 754 -> 752 | "\n" 753 | | 755 -> 754 | "\n" 755 | | 756 -> 756 | "\n" 757 | | 757 -> 758 | "\n" 759 | | 758 -> 760 | "\n" 761 | | 759 -> 762 | "\n" 763 | | 760 -> 764 | "\n" 765 | | 761 -> 766 | "\n" 767 | | 762 -> 768 | "\n" 769 | | 763 -> 770 | "\n" 771 | | 764 -> 772 | "\n" 773 | | 765 -> 774 | "\n" 775 | | 766 -> 776 | "\n" 777 | | 767 -> 778 | "\n" 779 | | 768 -> 780 | "\n" 781 | | 769 -> 782 | "\n" 783 | | 770 -> 784 | "\n" 785 | | 771 -> 786 | "\n" 787 | | 772 -> 788 | "\n" 789 | | 773 -> 790 | "\n" 791 | | 774 -> 792 | "\n" 793 | | 775 -> 794 | "\n" 795 | | 776 -> 796 | "\n" 797 | | 777 -> 798 | "\n" 799 | | 778 -> 800 | "\n" 801 | | 779 -> 802 | "\n" 803 | | 780 -> 804 | "\n" 805 | | 736 -> 806 | "\n" 807 | | 737 -> 808 | "\n" 809 | | 701 -> 810 | "\n" 811 | | 702 -> 812 | "\n" 813 | | 716 -> 814 | "\n" 815 | | 703 -> 816 | "\n" 817 | | 705 -> 818 | "\n" 819 | | 706 -> 820 | "\n" 821 | | 707 -> 822 | "\n" 823 | | 792 -> 824 | "\n" 825 | | 796 -> 826 | "\n" 827 | | 801 -> 828 | "\n" 829 | | 802 -> 830 | "\n" 831 | | 816 -> 832 | "\n" 833 | | _ -> 834 | raise Not_found 835 | --------------------------------------------------------------------------------