2
0
Nicolas Cannasse 20 жил өмнө
parent
commit
e3b0842b33
12 өөрчлөгдсөн 1565 нэмэгдсэн , 0 устгасан
  1. 305 0
      ast.ml
  2. 28 0
      doc/download.html
  3. 128 0
      doc/index.html
  4. 11 0
      doc/menu.js
  5. 289 0
      doc/ref.html
  6. 111 0
      doc/style.css
  7. 21 0
      haxe.sln
  8. 59 0
      haxe.vcproj
  9. 228 0
      lexer.mll
  10. 67 0
      main.ml
  11. 282 0
      parser.ml
  12. 36 0
      plugin.ml

+ 305 - 0
ast.ml

@@ -0,0 +1,305 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+
+type pos = {
+	pfile : string;
+	pmin : int;
+	pmax : int;
+}
+
+type keyword =
+	| Function
+	| Class
+	| Var
+	| If
+	| Else
+	| While
+	| Do
+	| For
+	| Break
+	| Continue
+	| Return
+	| Extends
+	| Implements
+	| Import
+	| Switch
+	| Case
+	| Default
+	| Static
+	| Public
+	| Private
+	| Try
+	| Catch
+	| New
+	| This
+	| Throw
+	| Native
+	| Enum
+	| In
+	
+type binop =
+	| OpAdd
+	| OpMult
+	| OpDiv
+	| OpSub
+	| OpAssign
+	| OpEq
+	| OpPhysEq
+	| OpNotEq
+	| OpPhysNotEq
+	| OpGt
+	| OpGte
+	| OpLt
+	| OpLte
+	| OpAnd
+	| OpOr
+	| OpXor
+	| OpBoolAnd
+	| OpBoolOr
+	| OpShl
+	| OpShr
+	| OpUShr
+	| OpMod
+	| OpAssignOp of binop
+
+type unop =
+	| Increment
+	| Decrement
+	| Not
+	| Neg
+	| NegBits
+
+type constant =
+	| Int of string
+	| Float of string
+	| String of string
+	| Ident of string
+	| Type of string
+
+type token =
+	| Eof
+	| Const of constant
+	| Kwd of keyword
+	| Comment of string
+	| CommentLine of string
+	| Binop of binop
+	| Unop of unop
+	| Semicolon
+	| Comma
+	| BrOpen
+	| BrClose
+	| BkOpen
+	| BkClose
+	| POpen
+	| PClose
+	| Dot
+	| DblDot
+
+type unop_flag =
+	| Prefix
+	| Postfix
+
+type while_flag =
+	| NormalWhile
+	| DoWhile
+
+type type_path = { 
+	tpackage : string list;
+	tname : string;
+	tparams : type_path list;
+}
+
+type func = {
+	f_args : (string * type_path option) list;
+	f_type : type_path option;
+	f_expr : expr;
+}
+
+and expr_def =
+	| EConst of constant
+	| EArray of expr * expr
+	| EBinop of binop * expr * expr
+	| EField of expr * string
+	| EType of expr * string
+	| EParenthesis of expr
+	| EObjectDecl of (string * expr) list
+	| EArrayDecl of expr list
+	| ECall of expr * expr list
+	| ENew of type_path * expr list
+	| EUnop of unop * unop_flag * expr
+	| EVars of (string * type_path option * expr option) list
+	| EFunction of func
+	| EBlock of expr list
+	| EFor of string * expr * expr
+	| EIf of expr * expr * expr option
+	| EWhile of expr * expr * while_flag
+	| ESwitch of expr * (expr * expr) list * expr option
+	| ETry of expr * (string * type_path * expr) list
+	| EReturn of expr option
+	| EBreak
+	| EContinue
+
+and expr = expr_def * pos
+
+type access =
+	| APublic
+	| APrivate
+	| AStatic
+
+type class_field =
+	| FVar of string * access list * type_path * expr option
+	| FFun of string * access list * func
+
+type class_flag =
+	| HNative
+	| HExtends of type_path
+	| HImplements of type_path
+
+type class_type = string * class_flag list
+
+type type_def =
+	| EClass of string * class_type list * class_flag list * class_field list
+	| EEnum of string * (string * (string * type_path) list) list
+	| EImport of type_path
+
+type type_decl = type_def * pos
+
+type package = string list * type_decl list
+
+let pos = snd
+
+let is_postfix (e,_) = function
+	| Increment | Decrement -> (match e with EConst _ | EField _ | EType _ | EArray _ -> true | _ -> false)
+	| Not | Neg | NegBits -> false
+
+let is_prefix = function
+	| Increment | Decrement -> true
+	| Not | Neg | NegBits -> true
+
+let base_class_name = snd
+
+let null_pos = { pfile = "<null>"; pmin = -1; pmax = -1 }
+
+let punion p p2 =
+	{
+		pfile = p.pfile;
+		pmin = min p.pmin p2.pmin;
+		pmax = max p.pmax p2.pmax;
+	}
+
+let s_type_path (p,s) = match p with [] -> s | _ -> String.concat "." p ^ "." ^ s
+
+let s_escape s =
+	let b = Buffer.create (String.length s) in
+	for i = 0 to (String.length s) - 1 do
+		match s.[i] with
+		| '\n' -> Buffer.add_string b "\\n"
+		| '\t' -> Buffer.add_string b "\\t"
+		| '\r' -> Buffer.add_string b "\\r"
+		| c -> Buffer.add_char b c
+	done;
+	Buffer.contents b
+
+let s_constant = function
+	| Int s -> s
+	| Float s -> s
+	| String s -> "\"" ^ s_escape s ^ "\""
+	| Ident s -> s
+	| Type s -> s
+	
+let s_keyword = function
+	| Function -> "function"
+	| Class -> "class"
+	| Static -> "static"
+	| Var -> "var"
+	| If -> "if"
+	| Else -> "else"
+	| While -> "while"
+	| Do -> "do"
+	| For -> "for"
+	| Break -> "break"
+	| Return -> "return"
+	| Continue -> "continue"
+	| Extends -> "extends"
+	| Implements -> "implements"
+	| Import -> "import"
+	| Switch -> "switch"
+	| Case -> "case"
+	| Default -> "default"
+	| Private -> "private"
+	| Public -> "public"
+	| Try -> "try"
+	| Catch -> "catch"
+	| New -> "new"
+	| This -> "this"
+	| Throw -> "throw"
+	| Native -> "native"
+	| Enum -> "enum"
+	| In -> "in"
+
+let rec s_binop = function
+	| OpAdd -> "+"
+	| OpMult -> "*"
+	| OpDiv -> "/"
+	| OpSub -> "-"
+	| OpAssign -> "="
+	| OpEq -> "=="
+	| OpPhysEq -> "==="
+	| OpNotEq -> "!="
+	| OpPhysNotEq -> "!=="
+	| OpGte -> ">="
+	| OpLte -> "<="
+	| OpGt -> ">"
+	| OpLt -> "<"
+	| OpAnd -> "&"
+	| OpOr -> "|"
+	| OpXor -> "^"
+	| OpBoolAnd -> "&&"
+	| OpBoolOr -> "||"
+	| OpShr -> ">>"
+	| OpUShr -> ">>>"
+	| OpShl -> "<<"
+	| OpMod -> "%"
+	| OpAssignOp op -> s_binop op ^ "="
+
+let s_unop = function
+	| Increment -> "++"
+	| Decrement -> "--"
+	| Not -> "!"
+	| Neg -> "-"
+	| NegBits -> "~"
+
+let s_token = function
+	| Eof -> "<end of file>"
+	| Const c -> s_constant c
+	| Kwd k -> s_keyword k
+	| Comment s -> "/*"^s^"*/"
+	| CommentLine s -> "//"^s
+	| Binop o -> s_binop o
+	| Unop o -> s_unop o
+	| Semicolon -> ";"
+	| Comma -> ","
+	| BkOpen -> "["
+	| BkClose -> "]"
+	| BrOpen -> "{"
+	| BrClose -> "}"
+	| POpen -> "("
+	| PClose -> ")"
+	| Dot -> "."
+	| DblDot -> ":"

+ 28 - 0
doc/download.html

@@ -0,0 +1,28 @@
+<html>
+<head>
+<title>The haXe Programming Language</title>
+<link rel="stylesheet" type="text/css" href="style.css"/>
+</head>
+
+<body>
+
+<div class="content">
+
+<h1>The haXe Programming Language</h1>
+
+<script type="text/javascript" src="menu.js"></script>
+
+<h2>Download</h2>
+
+<p>
+	TODO
+</p>
+
+<h2 class="end">Eof</h2>
+
+</div>
+
+<div id="scroll"></div>
+
+</body>
+</html>

+ 128 - 0
doc/index.html

@@ -0,0 +1,128 @@
+<html>
+<head>
+<title>The haXe Programming Language</title>
+<link rel="stylesheet" type="text/css" href="style.css"/>
+</head>
+
+<body>
+
+<div class="content">
+
+<h1>The haXe Programming Language</h1>
+
+<script type="text/javascript" src="menu.js"></script>
+
+<h2>Introduction</h2>
+
+<p>
+	The Web is evolving quickly, with different technologies needed at different places. For instance, if you want to create a website now you'll have to handle several languages :
+</p>
+
+<ul>
+	<li>on the <b>server</b> side : a <em>web</em> language such as PHP, Perl, Ruby or Python.</li>
+	<li>on the <b>client</b> side : HTML and CSS.</li>
+	<li>for <b>rich clients</b> : Flash (ActionScript 1, 2 and now 3) and Javascript / DHTML / AJAX.</li>
+</ul>
+
+<p>
+	The haXe programming language is trying to unite several of theses different <em>platforms</em> under one language. It brings features that are making it easy to deal with a dynamic world such as DHTML or Databases, while still bringing you a full-featured type system with a compiler that will detect errors early in the development phase.
+</p>
+
+<p>
+	Basicly, what haXe can do is :
+</p>
+
+<ul>
+	<li>create <b>Flash SWF</b> files using Flash APIs for Players 6,7,8 and soon 8.5.</li>
+	<li>generate <b>Javascript code</b> using Browser DHTML API, so you can create AJAX web applications.</li>
+	<li>generate <b>Neko sourcecode</b> that can be used on the Server side or in standalone executable.</li>
+</ul>
+
+<p>
+	Each of theses <em>platforms</em> have their own API, but they share the same programming language and the same standard library, so if your classes are <em>pure code</em> (using no specific API) then they can be compiled and used everywhere, depending on your needs.
+</p>
+
+<p>
+	Also, haXe make it easy to <b>interoperate</b> between theses different <em>platforms</em>, by providing common <em>protocol</em> libraries. Please note that it's still possible to use haXe on only one platform if you want for example keep your current working code.
+</p>
+
+<p>
+	We will now detail how haXe can be useful for each supported <em>platform</em>.
+</p>
+
+<h2>Flash SWF</h2>
+
+<p>
+	If you want to create really rich internet applications, such as Games, highly-interactive user interfaces, applications using sound or video streaming, then Flash is the platform of choice for you. However, there is several showstoppers if you want to use Flash.
+</p>
+
+<p>
+	On of them is that there is currenty <b>three</b> different programming languages for Flash (here's a little overview) :
+</p>
+
+<ul>
+	<li><em>ActionScript 1</em> : quite complete since Flash player 5, more mature in player 6. This is a Javascript variant (untyped , with no classes). Still widely used in order to make small quick scripts in Flash.</li>
+	<li><em>ActionScript 2</em> : since Flash MX 2004. Can be compiled to players 6 and more. Add a type-system with classes to JavaScript. Have several problems since Macromedia compiler is really slow, and the language itself is a little too permitive for easily developing serious applications.</li>
+	<li><em>ActionScript 3</em> : in alpha right now, supported by Flash Player 8.5 with a new virtual machine with JIT. Try to be Java, without the good features such as Generics.</li>
+</ul>
+
+<p>
+	Although you would like to use latest AS3 language, you still can't right now since the Player is still in alpha release, that means it's still one or two years early before the player get widely distributed on end-user computers. You have then the choice to keep using previous versions of ActionScript, but their futures are compromised by the existence of AS3.
+</p>
+
+<p>
+	<b>haXe</b> is solution to this problem. It brings one language, that is current compiling to Flash Player 6 and more, and will support in the future the new virtual machine in Flash Player 8.5 as well as new API when they will be available. It means that :
+</p>
+
+<ul>
+	<li>you can start using <b>haXe</b> right now for making SWF</li>
+	<li>porting your code for AS1/AS2 to haXe is not more difficult than porting it to AS3</li>
+</ul>
+
+
+<p>
+	The <b>haXe</b> compiler is <em>compiling</em> several haXe classes and files into a single <b>SWF</b> file that can be deployed on your webserver as usual.
+</p>
+
+<h2>Javascript</h2>
+
+<p>
+	Today another way of building Rich Internet Applications or simply adding some interactivity to a website is to use the Javascript language (also called DHTML or AJAX technologies). Javascript is a dynamicly typed programming language with no classes and is running on the client side with some differences between Browsers API.
+</p>
+
+<p>
+	Writing small Javascript applications takes time. Mainly because unless you are familiar with DHTML API and Browser differences, you need a lot of tests to make it work correctly. On another point, scaling medium and large Javascript applications is also difficult because of the lack of ways to structure your application (using classes for instance).
+</p>
+
+<p>
+	<b>haXe</b> is helpful here, because it brings you the whole DHTML API and give you a type system to check that you're using them correctly. Some features of the type system are especialy designed to play nice with the inheritent dynamic typing of DHTML. You can also use classes to structure your program, and easily interact with <b>haXe</b> code running in Flash and on the server side.
+</p>
+
+<p>
+	The <b>haXe</b> compiler is <em>generating</em> some valid Javascript source code from several haXe classes and files, so you only have to generate one time and then include the .js as usual in your webpage.
+</p>
+
+<h2>Neko and NekoVM</h2>
+
+<p>
+	A lot of different web languages are available right now, with some such as PHP that are very popular and widely used. Still, most of theses languages are either interpreted or running on slow virtual machines, resulting in low performances and need for powerful servers.
+</p>
+
+<p>
+	The <a href="http://nekovm.org">Neko Virtual Machine</a> is a very fast - still lightweight - VM that can easily be embeded into any application. It can run Neko bytecode and easily be extended using C DLLs. In particular, there is a <code>mod_neko</code> for the Apache webserver that can be used to write websites using the Neko programming language.
+</p>
+
+<p>
+	The Neko programming language is a medium-level dynamicly typed programming language that can be used as a target for different compilers. For example, the <b>haXe</b> compile have a Neko <em>generator</em> so you can actually run any haXe program on the NekoVM, but it also means that you can also interact with other high-level programming languages that have a Neko generator.
+</p>
+
+<p>
+	The <b>haXe</b> programming language can then be executed using the <b>NekoVM</b>, which is available on the <em>server side</em> using Apache, from the <em>commandline</em>, or can be <em>embedded</em> into your standalone binary application. This greatly increase the number of usages you can have with one single programming language.
+</p>
+
+<h2 class="end">Eof</h2>
+
+</div>
+
+</body>
+</html>

+ 11 - 0
doc/menu.js

@@ -0,0 +1,11 @@
+document.write(' \
+\
+<p class="menu"> \
+	<a href="index.html">Main</a> | <a href="ref.html">Reference</a> | <a href="download.html">Download</a> | <a href="mailto:[email protected]">Contact</a> \
+</p> \
+\
+<p> \
+	hAxe is an open source programming language for the web. \
+</p> \
+\
+');

+ 289 - 0
doc/ref.html

@@ -0,0 +1,289 @@
+<html>
+<head>
+<title>The haXe Programming Language Reference</title>
+<link rel="stylesheet" type="text/css" href="style.css"/>
+</head>
+
+<body>
+
+<div class="content">
+
+<h1>The haXe Programming Language Reference</h1>
+
+<script type="text/javascript" src="menu.js"></script>
+
+
+<h2>Introduction</h2>
+
+<p>
+	This Language Reference document will quickly introduce you the haXe programming language syntax and features.
+</p>
+
+<h2>My First Class</h2>
+
+<p>
+	The syntax is Java/ActionScript/C++ like.
+</p>
+
+<p>
+	A source code file is composed of a <em>package name</em> followed by several <em>type</em> declarations. In order to enforce the conventions, packages names are composed of several <em>identifiers</em> which are starting with a lowercase letter while <em>type identifiers</em> are always starting with an uppercase letter. The following <em>types</em> are available :
+</p>
+
+<ul>
+	<li>class</li>
+	<li>enumeration</li>
+	<li><em>(... more to come)</em></li>
+</ul>
+
+<p>
+	Here's one single sample mixing a class and an enumeration :
+</p>
+
+<pre>    <k>package</k> my.pack {
+
+        <k>enum</k> Color {
+            red;
+            green;
+            blue;
+        }
+
+        <k>class</k> Colors {
+            <k>static function</k> toInt( c : Color ) : Int {
+                <k>return if</k>( c == red ) 0xFF000
+                  <k>else if</k>( c == green ) 0x00FF00
+                  <k>else</k> 0x0000FF;
+            }
+        }
+    }
+</pre>
+
+<p>
+	We can notice several things here :
+</p>
+
+<ul>
+	<li>an enumeration define several <em>identifiers</em> which have the enumeration type.</li>
+	<li>a class can have methods (static or private/public). All class fields (methods and members) must be typed.</li>
+	<li>There is no <em>statement</em>. For exemple <c><k>if</k></c> block can be used on the right side of a return, or as function call parameter, or everywhere else an expression can be put.</li>
+</ul>
+
+<h2>The Type System</h2>
+
+<p>
+	The Type System is more rich that usual OO languages. There is several kind of types available :
+</p>
+
+<ul class="big">
+	<li><b>Objects</b> : objects are declared using classes. Each class can <em>extend</em> a single class (using inheritance) and can <em>implements</em> several classes (this is prototyping).</li>
+	<li><b>Anonymous Objects</b> : it's possible to define anonymous objects such as <c>{ x : Int; y : Int }</c>.</li>
+	<li><b>Dynamic Objects</b> : the <c>Dynamic</c> class have an infinite number of fields and methods, each having the <c>Dynamic</c> type. Classes can <em>extends</em> Dynamic in order to get dynamic behavior. <c>Dynamic</c> can have an optional type parameter (see below).</li>
+	<li><b>Abstract Types</b>
+: enumeration are abstract types. They define a finite number of
+instance of this type. The empty enumeration for exemple, although it
+has a name, can't be constructed.</li>
+	<li><b>Function Types</b> :
+when you want to define function types, you can define them by listing
+the arguments followed by the return type and separated with arrows.
+For exemple <c>Int -&gt; Void</c> is the type of a function taking an Int as argument and returning Void. And <c>Color -&gt; Color -&gt; Int</c> takes two Color arguments and returns an Int.</li>
+</ul>
+
+<p>
+	As we said before, all objects fields (members and methods) must be fully typed (although you can use the <c>Dynamic</c>
+type if you want to get dynamic behavior). That means that inside a
+method, we know all the types. You don't have then to declare local
+variable types since they will get inferred for you by the compiler.
+</p>
+
+<p>
+	Several common types are already defined in the language. Most of them are abstracts.
+</p>
+
+<ul>
+	<li><c>Dynamic</c> : special type</li>
+	<li><c>Void</c> : abstract</li>
+	<li><c>Int</c> : abstract</li>
+	<li><c>Float</c> : abstract</li>
+	<li><c>Bool</c> : enum { true; false; }</li>
+</ul>
+
+<h2>Class Parameters</h2>
+
+<p>
+	You can define class parameters in order to have one single class implementing different behavior. This is a way to get <em>polymorphism</em> :
+</p>
+
+<pre>    <k>native class</k> Array&lt;T&gt; {
+        <k>function new</k>() : Void;
+        <k>function</k> get( pos : Int ) : T;
+        <k>function</k> set( pos : Int, elt : T ) : Void;
+        ...
+    }
+</pre>
+
+<p>
+	Then you can use different kind of <c>Array</c>s by specifying the type parameter. For example <c>Array&lt;Int&gt;</c> is an array of integers and <c>Array&lt;Array&lt;Float&gt;&gt;</c>
+is a two dimentional array containing floats. You can of course define
+your own parametrized types. If you want them not to be fully abstract,
+you can specify some requirements in the type parameter :
+</p>
+
+<pre>    <k>class</k> MyClass&lt;T <k>extends</k> MyObject&gt; {
+        <k>var</k> o : T;
+        <k>function</k> foo() : Void {
+            o.myMethod();
+        }
+        ...
+    }
+</pre>
+
+<h2>Iterators</h2>
+
+<p> A nice feature of the language is to be able to define your own
+iterators and play with them. An iterator is a function of the form : <c>Void -&gt; X</c> where <c>X</c> is the iterated type. You can use the <c><k>for</k>...<k>in</k></c> syntax in order to execute iterators. The most simple iterator is the <c>Int</c> iterator which can easily be built using the operator <c>...</c> :
+</p>
+
+<pre>    <k>for</k> i <k>in</k> 1...10 {
+        <g>// ...</g>
+    }
+</pre>
+
+<p>
+	Or the usual <c><k>for</k></c> loop :
+</p>
+
+<pre>    <k>for</k> i <k>in</k> 0...arr.length {
+        foo(arr[i]);
+    }
+</pre>
+
+<p>
+	But you can also define you own iterators. You can simply implement the <c>iterator()</c> method in your class. This method must return another function that will return one object each call or the special value <k><c>done</c></k> when finished. Here's a simple integer enumerator sample. Please note that it is not really useful since there is already the <c>...</c>&lt;&gt; operator, but it's good sample to understand how it works <em>behind the scene</em> :
+</p>
+
+<pre>    <k>class</k> IntIter {
+        <k>var</k> min : Int;
+        <k>var</k> max : Int;
+
+        <k>function new</k>( min : Int, max : Int ) {
+            <k>this</k>.min = min;
+            <k>this</k>.max = max;
+        }
+
+        <k>function</k> iterator() {
+            <k>var</k> cur = min;
+            <k>return function</k>() {
+                <k>if</k>( cur == max )
+                    <k>return</k> done;
+                <k>return</k> cur++;
+            }
+        }
+    }
+</pre>
+
+<p>
+	As this class shows, you can call several times the <c>iterator()</c> method in order to have several parallel iterators. Once your iterator is implemented, you can simply use it with the <c><k>for</k>...<k>in</k></c> syntax, this way :
+</p>
+
+<pre>    <k>var</k> iter = <k>new</k> IntIter(0,10);
+    <k>for</k> i <k>in</k> iter {
+        <g>// ...</g>
+    }
+</pre>
+
+<p> The variable name in the iterator is automaticaly declared and its
+type is bound to the iterator type. If the iterator is a function, then
+it must be of the form <c>Void -&gt; X</c> as previously said. If it's an object like the sample here, then it's a shortcut for writing <c>iter.iterator()</c>.
+</p>
+
+<h2>Going Dynamic</h2>
+
+<p>
+	When you want to have dynamic behavior, you can either type some variables as <c>Dynamic</c> or have your classes <c><k>extends</k></c> or <c><k>implements</k></c> Dynamic. Dynamic can have an optional type parameter that determine the type of the object fields when accessed. For exemple :
+</p>
+
+<pre>    <k>class</k> XML {
+
+        <k>var</k> attributes : Dynamic&lt;String&gt;
+        ....
+
+    }
+</pre>
+
+<p>
+	In that case, all objects fields of attributes will have the type <c>String</c>. Dynamic classes are then Strongly typed Object-Hashes. You can write as well <c>Dynamic&lt;Dynamic&lt;String&gt;&gt;</c> which will give you a two-level objects access (if you find any use for it...). Actually , <c>Dynamic</c> without type parameter is a shortcut for the infinite declaration : <c>Dynamic&lt;Dynamic&lt;Dynamic&lt;....&gt;&gt;&gt;</c> which would otherwise takes too much time to write.
+</p>
+
+<p>
+	Another possibility to get dynamic behavior is to set your code into an <c>untyped { }</c> block :
+</p>
+
+<pre>    <k>function</k> iKnowWhatImDoing( o : SomeObject ) : SomethingElse {
+        <k>untyped</k> {
+            <k>return</k> o.someStrangeMethod();
+        }
+    }
+</pre>
+
+<h2>Syntax</h2>
+
+<p>
+	Here's the syntax grammar (still in the works) :
+</p>
+
+<pre>    ident := [a-z][a-zA-Z0-9]*
+    type-name := [A-Z][a-zA-Z0-9]*
+
+    package-name := (<em>ident</em> <t>.</t> )* <em>ident</em>
+
+    type-path := (<em>package-name</em> <t>.</t>)? <em>type-name</em> <em>type-params</em>
+
+    type-params :=
+        | &#949;
+        | <t>&lt;</t> <em>type-path</em>+ <t>&gt;</t>
+
+    type-option :=
+        | &#949;
+        | <t>:</t> <em>type-path</em>
+
+    program := <k>package</k> <em>package-name</em>? <t>{</t> (<em>type-declaration</em> | <em>import</em> | <t>;</t> )* <t>}</t>
+
+    type-declaration :=
+        | <k>class</k> <em>type-name</em> <t>{</t> <em>class-field</em>* <t>}</t>
+        | <k>enum</k> <em>type-name</em> <t>{</t> (<em>ident</em> | <t>;</t> )* <t>}</t>
+
+    import := <k>import</k> <em>type-path</em>
+
+    class-field :=
+        | <em>field-style</em>* <k>var</k> <em>ident</em> <em>type-option</em>
+        | <em>field-style</em>* <k>function</k> <em>ident</em> <t>(</t> <em>parameter-list</em>? <t>)</t> <em>type-option</em> <t>{</t> <em>expr</em>* <t>}</t>
+
+    field-style :=
+        | <k>public</k>
+        | <k>private</k>
+        | <k>static</k>
+        | <k>native</k>
+
+    parameter_list := <em>ident</em> <em>type-option</em> (<t>,</t> <em>parameter-list</em>)?
+
+    expr := TODO
+
+</pre>
+
+<h2>And now ?</h2>
+
+<p>
+	A lot more will come later :)
+</p>
+
+<h2>Author</h2>
+
+<p>
+	<a href="mailto:[email protected]">Nicolas Cannasse</a>
+</p>
+
+<h2 class="end">Eof</h2>
+
+</div>
+
+</body>
+</html>

+ 111 - 0
doc/style.css

@@ -0,0 +1,111 @@
+/* ----------- colors ------------ */
+
+body {
+	background-color : #705200;
+}
+
+.content {
+	background-color : white;
+}
+
+h1, h2 {
+	color : #fff;
+	background-color : #fb0;
+}
+
+a {
+	color : #fb0;	
+}
+
+a:hover {
+	color: #ea0;
+}
+
+b , strong {
+	color: #705200;
+}
+
+/* ----------- style ------------ */
+
+body {
+	text-align: center;
+	font-family: Trebuchet MS, sans-serif;
+	padding : 0;
+	margin : 0;
+}
+
+.content {
+	width : 800px;
+	position: relative;
+	margin : 10 auto 30 auto;
+	text-align: left;
+}
+
+.menu {
+	text-align: right;
+}
+
+h1 {
+	margin-top : 0px;
+	text-align: center;
+	padding: 4px 0px 4px 0px;
+}
+
+h2 {
+	padding: 2px 0px 2px 20px;
+	margin-top : 30px;
+}
+
+h2.end {
+	margin-bottom : 0px;
+}
+
+p, li {
+	margin-left : 20px;
+	margin-right : 15px;
+	text-align : justify;
+}
+
+ul.big li {
+	margin-bottom : 10px;
+}
+
+a {
+	font-weight: bold;
+}
+
+#scroll {
+	position : absolute;
+	top : 0;
+	bottom : -0.1px;
+	width : 1em;
+	z-index : -1;
+}
+
+/* ----------- code ------------ */
+
+pre {
+	margin : 0px 20px 0px 20px;
+	padding : 5px;
+	background-color: #eee;
+	border: solid 1px #ccc;
+}
+
+k {
+	color: blue;
+}
+
+t {
+	font-weight: bold;
+	color : #700;
+}
+
+g {
+	color : #070;
+}
+
+c {
+	color : #333;
+	font-family: monospace;
+}
+

+ 21 - 0
haxe.sln

@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "haxe", "haxe.vcproj", "{6194C08E-41F1-4013-9D50-58C89E401FA8}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{6194C08E-41F1-4013-9D50-58C89E401FA8}.Debug.ActiveCfg = Debug|Win32
+		{6194C08E-41F1-4013-9D50-58C89E401FA8}.Debug.Build.0 = Debug|Win32
+		{6194C08E-41F1-4013-9D50-58C89E401FA8}.Release.ActiveCfg = Release|Win32
+		{6194C08E-41F1-4013-9D50-58C89E401FA8}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal

+ 59 - 0
haxe.vcproj

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="haxe"
+	ProjectGUID="{6194C08E-41F1-4013-9D50-58C89E401FA8}"
+	Keyword="MakeFileProj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="0">
+			<Tool
+				Name="VCNMakeTool"
+				BuildCommandLine="ocamake -opt -pp camlp4o haxe.vcproj extc.cmxa"
+				ReBuildCommandLine="ocamake -all -opt -pp camlp4o haxe.vcproj extc.cmxa"
+				CleanCommandLine="ocamake -clean -opt -pp camlp4o haxe.vcproj extc.cmxa"
+				Output="haxe.exe"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="0">
+			<Tool
+				Name="VCNMakeTool"
+				BuildCommandLine="ocamake -opt -pp camlp4o haxe.vcproj"
+				ReBuildCommandLine="ocamake -all -opt -pp camlp4o haxe.vcproj"
+				CleanCommandLine="ocamake -clean -opt -pp camlp4o haxe.vcproj"
+				Output="haxe.exe"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath=".\ast.ml">
+		</File>
+		<File
+			RelativePath=".\lexer.mll">
+		</File>
+		<File
+			RelativePath=".\main.ml">
+		</File>
+		<File
+			RelativePath=".\parser.ml">
+		</File>
+		<File
+			RelativePath=".\plugin.ml">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 228 - 0
lexer.mll

@@ -0,0 +1,228 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+
+{
+open Lexing
+open Ast
+
+type error_msg =
+	| Invalid_character of char
+	| Unterminated_string
+	| Unclosed_comment
+
+exception Error of error_msg * pos
+
+let error_msg = function
+	| Invalid_character c when int_of_char c > 32 && int_of_char c < 128 -> Printf.sprintf "Invalid character '%c'" c
+	| Invalid_character c -> Printf.sprintf "Invalid character 0x%.2X" (int_of_char c)
+	| Unterminated_string -> "Unterminated string"
+	| Unclosed_comment -> "Unclosed comment"
+
+let cur_file = ref ""
+let all_lines = Hashtbl.create 0
+let lines = ref []
+let buf = Buffer.create 100
+
+let error e pos = 
+	raise (Error (e,{ pmin = pos; pmax = pos; pfile = !cur_file }))
+
+let keywords =
+	let h = Hashtbl.create 3 in
+	List.iter (fun k -> Hashtbl.add h (s_keyword k) k) 
+		[Function;Class;Static;Var;If;Else;While;Do;For;
+		Break;Return;Continue;Extends;Implements;Import;
+		Switch;Case;Default;Public;Private;Try;
+		Catch;New;This;Throw;Native;Enum;In];
+	h
+
+let init file =
+	cur_file := file;
+	lines := []
+
+let save_lines() =
+	Hashtbl.replace all_lines !cur_file !lines
+
+let save() =
+	save_lines();
+	!cur_file
+
+let restore file =
+	save_lines();
+	cur_file := file;
+	lines := Hashtbl.find all_lines file 
+
+let newline lexbuf =
+	lines :=  (lexeme_end lexbuf) :: !lines
+
+let find_line p lines =
+	let rec loop n delta = function
+		| [] -> n , p - delta
+		| lp :: l when lp > p -> n , p - delta
+		| lp :: l -> loop (n+1) lp l
+	in
+	loop 1 0 lines
+
+let get_error_line p =
+	let lines = List.rev (try Hashtbl.find all_lines p.pfile with Not_found -> []) in
+	let l, _ = find_line p.pmin lines in
+	l
+
+let get_error_pos printer p =
+	if p.pmin = -1 then
+		"(unknown)"
+	else
+		let lines = List.rev (try Hashtbl.find all_lines p.pfile with Not_found -> []) in
+		let l1, p1 = find_line p.pmin lines in
+		let l2, p2 = find_line p.pmax lines in
+		if l1 = l2 then begin
+			let s = (if p1 = p2 then Printf.sprintf " %d" p1 else Printf.sprintf "s %d-%d" p1 p2) in
+			Printf.sprintf "%s character%s" (printer p.pfile l1) s
+		end else
+			Printf.sprintf "%s lines %d-%d" (printer p.pfile l1) l1 l2
+
+let reset() = Buffer.reset buf
+let contents() = Buffer.contents buf
+let store lexbuf = Buffer.add_string buf (lexeme lexbuf)
+let add c = Buffer.add_string buf c
+
+let mk_tok t pmin pmax =
+	t , { pfile = !cur_file; pmin = pmin; pmax = pmax }
+
+let mk lexbuf t = 
+	mk_tok t (lexeme_start lexbuf) (lexeme_end lexbuf)
+
+let mk_ident lexbuf =
+	match lexeme lexbuf with
+	| s ->
+		mk lexbuf (try Kwd (Hashtbl.find keywords s) with Not_found -> Const (Ident s))
+
+}
+
+let ident = ['_' 'a'-'z'] ['_' 'a'-'z' 'A'-'Z' '0'-'9']*
+let idtype = ['A' - 'Z'] ['_' 'a'-'z' 'A'-'Z' '0'-'9']*
+
+rule token = parse
+	| eof { mk lexbuf Eof }
+	| "\239\187\191" { token lexbuf }
+	| [' ' '\t']+ { token lexbuf } 
+	| "\r\n" { newline lexbuf; token lexbuf }
+	| '\n' | '\r' { newline lexbuf; token lexbuf }
+	| "0x" ['0'-'9' 'a'-'f' 'A'-'F']+ { mk lexbuf (Const (Int (lexeme lexbuf))) }
+	| ['0'-'9']+ { mk lexbuf (Const (Int (lexeme lexbuf))) }
+	| ['0'-'9']+ '.' ['0'-'9']* { mk lexbuf (Const (Float (lexeme lexbuf))) }
+	| '.' ['0'-'9']+ { mk lexbuf (Const (Float (lexeme lexbuf))) }
+	| ['0'-'9']+ ['e' 'E'] ['+' '-']? ['0'-'9']+ { mk lexbuf (Const (Float (lexeme lexbuf))) }
+	| ['0'-'9']+ '.' ['0'-'9']* ['e' 'E'] ['+' '-']? ['0'-'9']+ { mk lexbuf (Const (Float (lexeme lexbuf))) }
+	| "//" [^'\n' '\r']*  {
+			let s = lexeme lexbuf in
+			mk lexbuf (CommentLine (String.sub s 2 ((String.length s)-2)))
+		}
+	| "++" { mk lexbuf (Unop Increment) }
+	| "--" { mk lexbuf (Unop Decrement) }
+	| "~"  { mk lexbuf (Unop NegBits) }
+	| "%=" { mk lexbuf (Binop (OpAssignOp OpMod)) }
+	| "&=" { mk lexbuf (Binop (OpAssignOp OpAnd)) }
+	| "|=" { mk lexbuf (Binop (OpAssignOp OpOr)) }
+	| "^=" { mk lexbuf (Binop (OpAssignOp OpXor)) }
+	| "+=" { mk lexbuf (Binop (OpAssignOp OpAdd)) }
+	| "-=" { mk lexbuf (Binop (OpAssignOp OpSub)) }
+	| "*=" { mk lexbuf (Binop (OpAssignOp OpMult)) }
+	| "/=" { mk lexbuf (Binop (OpAssignOp OpDiv)) }
+	| "<<=" { mk lexbuf (Binop (OpAssignOp OpShl)) }
+	| ">>=" { mk lexbuf (Binop (OpAssignOp OpShr)) }
+	| ">>>=" { mk lexbuf (Binop (OpAssignOp OpUShr)) }	
+	| "===" { mk lexbuf (Binop OpPhysEq) }
+	| "!==" { mk lexbuf (Binop OpPhysNotEq) }
+	| "==" { mk lexbuf (Binop OpEq) }
+	| "!=" { mk lexbuf (Binop OpNotEq) }
+	| "<=" { mk lexbuf (Binop OpLte) }
+	| ">=" { mk lexbuf (Binop OpGte) }
+	| "&&" { mk lexbuf (Binop OpBoolAnd) }
+	| "||" { mk lexbuf (Binop OpBoolOr) }
+	| "<<" { mk lexbuf (Binop OpShl) }
+(*//| ">>" { mk lexbuf (Binop OpShr) } *)
+(*//| ">>>" { mk lexbuf (Binop OpUShr) } *)
+	| "!" { mk lexbuf (Unop Not) }
+	| "<" { mk lexbuf (Binop OpLt) }
+	| ">" { mk lexbuf (Binop OpGt) }
+	| ";" { mk lexbuf Semicolon }
+	| ":" { mk lexbuf DblDot }
+	| "," { mk lexbuf Comma }
+	| "." { mk lexbuf Dot }
+	| "%" { mk lexbuf (Binop OpMod) }
+	| "&" { mk lexbuf (Binop OpAnd) }
+	| "|" { mk lexbuf (Binop OpOr) }
+	| "^" { mk lexbuf (Binop OpXor) }
+	| "+" { mk lexbuf (Binop OpAdd) }
+	| "*" { mk lexbuf (Binop OpMult) }
+	| "/" { mk lexbuf (Binop OpDiv) }
+	| "-" { mk lexbuf (Binop OpSub) }
+	| "=" { mk lexbuf (Binop OpAssign) }
+	| "[" { mk lexbuf BkOpen }
+	| "]" { mk lexbuf BkClose }
+	| "{" { mk lexbuf BrOpen }
+	| "}" { mk lexbuf BrClose }
+	| "(" { mk lexbuf POpen }
+	| ")" { mk lexbuf PClose }
+	| "/*" {
+			reset();
+			let pmin = lexeme_start lexbuf in
+			let pmax = (try comment lexbuf with Exit -> error Unclosed_comment pmin) in
+			mk_tok (Comment (contents())) pmin pmax;
+		}
+	| '"' {
+			reset();
+			let pmin = lexeme_start lexbuf in
+			let pmax = (try string lexbuf with Exit -> error Unterminated_string pmin) in
+			mk_tok (Const (String (contents()))) pmin pmax;
+		}
+	| "'" {
+			reset();
+			let pmin = lexeme_start lexbuf in
+			let pmax = (try string2 lexbuf with Exit -> error Unterminated_string pmin) in
+			mk_tok (Const (String (contents()))) pmin pmax;
+		}
+	| ident { mk_ident lexbuf }
+	| idtype { mk lexbuf (Const (Type (lexeme lexbuf))) }
+	| _ { error (Invalid_character (lexeme_char lexbuf 0)) (lexeme_start lexbuf) }
+
+and comment = parse
+	| eof { raise Exit }
+	| '\n' | '\r' | "\r\n" { newline lexbuf; store lexbuf; comment lexbuf }
+	| "*/" { lexeme_end lexbuf }
+	| '*' { store lexbuf; comment lexbuf }
+	| [^'*' '\n' '\r']+ { store lexbuf; comment lexbuf }
+
+and string = parse
+	| eof { raise Exit }
+	| '\n' | '\r' | "\r\n" { newline lexbuf; store lexbuf; string lexbuf }
+	| "\\\"" { store lexbuf; string lexbuf }
+	| "\\\\" { store lexbuf; string lexbuf }
+	| '\\' { store lexbuf; string lexbuf }
+	| '"' { lexeme_end lexbuf }
+	| [^'"' '\\' '\r' '\n']+ { store lexbuf; string lexbuf }
+
+and string2 = parse
+	| eof { raise Exit }
+	| '\n' | '\r' | "\r\n" { newline lexbuf; store lexbuf; string2 lexbuf }
+	| '\\' { store lexbuf; string2 lexbuf }
+	| "\\\\" { store lexbuf; string2 lexbuf }
+	| "\\'" { store lexbuf; string2 lexbuf }
+	| "'" { lexeme_end lexbuf }
+	| [^'\'' '\\' '\r' '\n']+ { store lexbuf; string2 lexbuf }

+ 67 - 0
main.ml

@@ -0,0 +1,67 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+open Printf
+
+let normalize_path p =
+	let l = String.length p in
+	if l = 0 then
+		"./"
+	else match p.[l-1] with 
+		| '\\' | '/' -> p
+		| _ -> p ^ "/"
+
+let report kind msg p =
+	let error_printer file line = sprintf "%s:%d:" file line in
+	let epos = Lexer.get_error_pos error_printer p in
+	prerr_endline (sprintf "%s : %s %s" epos kind msg);
+	exit 1
+
+let compile files =
+	List.iter (fun f ->
+		let file = (try Plugin.find_file f with Not_found -> failwith ("File not found " ^ f)) in
+		let ch = open_in file in
+		let ast = Parser.parse (Lexing.from_channel ch) file in
+		()
+	) files
+
+;;
+try	
+	let usage = "Haxe Compiler Alpha - (c)2005 Motion-Twin\n Usage : haxe.exe [options] <files...>\n Options :" in
+	let base_path = normalize_path (try Extc.executable_path() with _ -> ".") in
+	let files = ref [] in
+	let time = Sys.time() in
+	Plugin.class_path := [base_path;"";"/"];
+	let args_spec = [
+		("-cp",Arg.String (fun path -> Plugin.class_path := normalize_path path :: !Plugin.class_path),"<path> : add a directory to find source files");
+		("-v",Arg.Unit (fun () -> Plugin.verbose := true),": turn on verbose mode");
+	] @ !Plugin.options in
+	Arg.parse args_spec (fun file -> files := file :: !files) usage;
+	if !files = [] then begin
+		Arg.usage args_spec usage
+	end else begin
+		if !Plugin.verbose then print_endline ("Classpath : " ^ (String.concat ";" !Plugin.class_path));
+		compile (List.rev !files);
+		if !Plugin.verbose then print_endline ("Time spent : " ^ string_of_float (Sys.time() -. time));
+	end;
+with
+	| Lexer.Error (m,p) -> report "syntax error" (Lexer.error_msg m) p
+	| Parser.Error (m,p) -> report "parse error" (Parser.error_msg m) p
+	| Failure msg ->
+		prerr_endline msg;
+		exit 1;

+ 282 - 0
parser.ml

@@ -0,0 +1,282 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+open Ast
+
+type error_msg =
+	| Unexpected of token
+	| Duplicate_default
+	| Missing_semicolon
+
+exception Error of error_msg * pos
+
+let error_msg = function
+	| Unexpected t -> "Unexpected "^(s_token t)
+	| Duplicate_default -> "Duplicate default"
+	| Missing_semicolon -> "Missing ;"
+
+let error m p = raise (Error (m,p))
+
+let serror() = raise (Stream.Error "")
+
+let priority = function
+	| OpAssign | OpAssignOp _ -> -4
+	| OpBoolOr -> -3
+	| OpBoolAnd -> -2
+	| OpEq | OpNotEq | OpGt | OpLt | OpGte | OpLte | OpPhysEq | OpPhysNotEq -> -1
+	| OpOr | OpAnd | OpXor -> 0
+	| OpShl | OpShr | OpUShr -> 1
+	| OpAdd | OpSub -> 2
+	| OpMod -> 3
+	| OpMult | OpDiv -> 4
+
+let is_not_assign = function
+	| OpAssign | OpAssignOp _ -> false
+	| _ -> true
+
+let can_swap _op op =
+	let p1 = priority _op in
+	let p2 = priority op in
+	if p1 < p2 then
+		true
+	else if p1 = p2 && p1 >= 0 then (* numerical ops are left-assoc *)
+		true
+	else
+		false
+
+let rec make_binop op e ((v,p2) as e2) =
+	match v with
+	| EBinop (_op,_e,_e2) when can_swap _op op && (is_not_assign _op || is_not_assign op) ->
+		let _e = make_binop op e _e in
+		EBinop (_op,_e,_e2) , punion (pos _e) (pos _e2)
+	| _ ->
+		EBinop (op,e,e2) , punion (pos e) (pos e2)
+
+let rec make_unop op ((v,p2) as e) p1 = 
+	match v with
+	| EBinop (bop,e,e2) -> EBinop (bop, make_unop op e p1 , e2) , (punion p1 p2)
+	| _ ->
+		EUnop (op,Prefix,e), punion p1 p2
+
+let popt f = parser
+	| [< v = f >] -> Some v
+	| [< >] -> None
+
+let rec plist f = parser
+	| [< v = f; l = plist f >] -> v :: l
+	| [< >] -> []
+
+let rec psep sep f = parser
+	| [< v = f; s >] ->
+		match s with parser
+		| [< '(sep2,_) when sep2 = sep; l = psep sep f >] -> v :: l
+		| [< >] -> [v]
+
+let rec psep_opt sep f = parser
+	| [< v = f; s >] ->
+		(match s with parser
+		| [< '(sep2,_) when sep2 = sep; l = psep_opt sep f >] -> v :: l
+		| [< l = psep_opt sep f >] -> v :: l
+		| [< >] -> serror())
+	| [< >] -> []
+
+let ident = parser
+	| [< '(Const (Ident i),_) >] -> i
+
+let comma = parser
+	| [< '(Comma,_) >] -> ()
+
+let semicolon = parser
+	| [< '(Semicolon,p) >] -> p
+	| [< '(_,p) >] -> error Missing_semicolon p
+
+let rec	parse_file = parser
+	| [< '(Const (Ident "package"),_); p = parse_package; '(BrOpen,_); l = psep_opt Semicolon parse_type_decl; '(BrClose,_); '(Eof,_); >] -> p , l
+
+and parse_type_decl = parser
+	| [< '(Kwd Import,p); t = parse_type_path >] -> (EImport t, p)
+	| [< '(Kwd Enum,p1); '(Const (Type name),_); '(BrOpen,_); l = plist parse_enum; '(BrClose,p2) >] -> (EEnum (name,l), punion p1 p2)
+	| [< '(Kwd Class,p1); '(Const (Type name),_); tl = parse_class_types; hl = psep Comma parse_class_herit; '(BrOpen,_); fl = plist parse_class_field; '(BrClose,p2) >] -> (EClass (name,tl,hl,fl), punion p1 p2)
+
+and parse_package = parser
+	| [< p = psep Dot ident >] -> p 
+	| [< >] -> []
+
+and parse_type_opt = parser
+	| [< '(DblDot,_); t = parse_type_path >] -> Some t
+	| [< >] -> None
+
+and parse_type_path s = parse_type_path1 [] s
+
+and parse_type_path1 pack = parser
+	| [< '(Const (Ident name),_); '(Dot,_); t = parse_type_path1 (name :: pack) >] -> t
+	| [< '(Const (Type name),_); s >] ->
+		let params = (match s with parser
+			| [< '(Binop OpLt,_); l = psep Comma parse_type_path; '(Binop OpGt,_) >] -> l
+			| [< >] -> []
+		) in
+		{
+			tpackage = List.rev pack;
+			tname = name;
+			tparams = params
+		}
+
+and parse_enum = parser
+	| [< '(Const (Ident name),_); s >] ->
+		match s with parser
+		| [< '(POpen,_); l = psep Comma parse_enum_param; '(PClose,_); _ = semicolon; >] -> (name,l)
+		| [< '(Semicolon,_) >] -> (name,[])
+		| [< >] -> serror()
+
+and parse_enum_param = parser
+	| [< '(Const (Ident name),_); '(DblDot,_); t = parse_type_path >] -> (name,t)
+
+and parse_class_field = parser
+	| [< l = parse_cf_rights []; s >] ->
+		match s with parser
+		| [< '(Kwd Var,_); '(Const (Ident name),_); '(DblDot,_); t = parse_type_path; s >] -> 
+			let e = (match s with parser
+			| [< '(Binop OpAssign,_) when List.mem AStatic l; e = expr; _ = semicolon >] -> Some e
+			| [< '(Semicolon,_) >] -> None
+			| [< >] -> serror()
+			) in
+			FVar (name,l,t,e)
+		| [< '(Kwd Function,_); '(Const (Ident name),_); '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; e = expr >] ->
+			let f = {
+				f_args = al;
+				f_type = t;
+				f_expr = e;
+			} in
+			FFun (name,l,f)
+		| [< >] -> if l = [] then raise Stream.Failure else serror()
+
+and parse_cf_rights l = parser
+	| [< '(Kwd Static,_) when not(List.mem AStatic l); l = parse_cf_rights (AStatic :: l) >] -> l
+	| [< '(Kwd Public,_) when not(List.mem APublic l || List.mem APrivate l); l = parse_cf_rights (APublic :: l) >] -> l
+	| [< '(Kwd Private,_) when not(List.mem APublic l || List.mem APrivate l); l = parse_cf_rights (APrivate :: l) >] -> l
+	| [< >] -> l
+
+and parse_fun_param = parser
+	| [< '(Const (Ident name),_); t = parse_type_opt >] -> (name,t)
+
+and parse_class_types = parser
+	| [< '(Binop OpLt,_); l = psep Comma parse_class_type; '(Binop OpGt,_) >] -> l
+	| [< >] -> []
+
+and parse_class_type = parser
+	| [< '(Const (Type name),_); h = psep Comma parse_class_herit >] -> (name,h)
+
+and parse_class_herit = parser
+	| [< '(Kwd Extends,_); t = parse_type_path >] -> HExtends t
+	| [< '(Kwd Implements,_); t = parse_type_path >] -> HImplements t
+
+and block s = plist parse_block_elt s
+
+and parse_block_elt = parser
+	| [< '(Kwd Var,p1); vl = psep Comma parse_var_decl; p2 = semicolon >] -> (EVars vl,punion p1 p2)
+	| [< e = expr; _ = semicolon >] -> e
+
+and parse_var_decl = parser
+	| [< '(Const (Ident name),_); t = parse_type_opt; s >] ->
+		match s with parser
+		| [< '(Binop OpAssign,_); e = expr >] -> (name,t,Some e)
+		| [< >] -> (name,t,None)
+
+and expr = parser
+	| [< '(BrOpen,p1); l = block; '(BrClose,p2) >] -> (EBlock l,punion p1 p2)
+	| [< '(Const c,p); s >] -> expr_next (EConst c,p) s
+	| [< '(Kwd This,p); s >] -> expr_next (EConst (Ident "this"),p) s
+	| [< '(Kwd Throw,p); s >] -> expr_next (EConst (Ident "throw"),p) s
+	| [< '(Kwd New,p1); t = parse_type_path; '(POpen,_); al = psep Comma expr; '(PClose,p2); s >] -> expr_next (ENew (t,al),punion p1 p2) s
+	| [< '(POpen,p1); e = expr; '(PClose,p2); s >] -> expr_next (EParenthesis e, punion p1 p2) s
+	| [< '(BkOpen,p1); l = psep Comma expr; _ = popt comma; '(BkClose,p2); s >] -> expr_next (EArrayDecl l, punion p1 p2) s
+	| [< '(Kwd Function,p1); '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; e = expr; s >] -> 
+		let f = {
+			f_type = t;
+			f_args = al;
+			f_expr = e;
+		} in
+		expr_next (EFunction f, punion p1 (pos e)) s
+	| [< '(Unop op,p1) when is_prefix op; e = expr >] -> make_unop op e p1
+	| [< '(Binop OpSub,p1); e = expr >] -> make_unop Neg e p1
+	| [< '(Kwd For,p); '(Const (Ident name),_); '(Kwd In,_); it = expr; e = expr; s >] -> expr_next (EFor (name,it,e),punion p (pos e)) s
+	| [< '(Kwd If,p); cond = expr; e1 = expr; s >] ->
+		let e2 , s = (match s with parser
+			| [< '(Kwd Else,_); e2 = expr; s >] -> Some e2 , s
+			| [< >] -> None , s
+		) in
+		expr_next (EIf (cond,e1,e2), punion p (match e2 with None -> pos e1 | Some e -> pos e)) s
+	| [< '(Kwd Return,p); e = popt expr >] -> (EReturn e, match e with None -> p | Some e -> punion p (pos e))
+	| [< '(Kwd Break,p) >] -> (EBreak,p)
+	| [< '(Kwd Continue,p) >] -> (EContinue,p)
+	| [< '(Kwd While,p1); cond = expr; e = expr; s >] -> expr_next (EWhile (cond,e,NormalWhile),punion p1 (pos e)) s
+	| [< '(Kwd Do,p1); e = expr; '(Kwd While,_); cond = expr; s >] -> expr_next (EWhile (cond,e,DoWhile),punion p1 (pos e)) s
+	| [< '(Kwd Switch,p1); e = expr; '(BrOpen,_); cases , def = parse_switch_cases; '(BrClose,p2); s >] -> expr_next (ESwitch (e,List.rev cases,def),punion p1 p2) s
+	| [< '(Kwd Try,p1); e = expr; cl = plist parse_catch; s >] -> expr_next (ETry (e,cl),p1) s
+
+and expr_next e1 = parser
+	| [< '(Dot,_); s >] -> 
+		(match s with parser
+		| [< '(Const (Ident f),p); s >] -> expr_next (EField (e1,f) , punion (pos e1) p) s
+		| [< '(Const (Type t),p); s >] -> expr_next (EType (e1,t) , punion (pos e1) p) s
+		| [< >] -> serror())
+	| [< '(POpen,p1); params = psep Comma expr; '(PClose,p2); s >] ->
+		expr_next (ECall (e1,params) , punion (pos e1) p2) s
+	| [< '(BkOpen,_); e2 = expr; '(BkClose,p2); s >] ->
+		expr_next (EArray (e1,e2), punion (pos e1) p2) s
+	| [< '(Binop op,_); e2 = expr >] ->
+		make_binop op e1 e2
+	| [< '(Unop op,p) when is_postfix e1 op; s >] ->
+		expr_next (EUnop (op,Postfix,e1), punion (pos e1) p) s
+	| [< >] -> e1
+
+and parse_switch_cases = parser
+	| [< '(Kwd Default,p1); '(DblDot,_); el = block; l , def = parse_switch_cases >] -> 
+		(match def with None -> () | Some (e,p) -> error Duplicate_default p);
+		l , Some (EBlock el , p1)
+	| [< e = expr; '(DblDot,_); el = block; l , def = parse_switch_cases >] ->
+		(e,(EBlock el,pos e)) :: l , def
+
+and parse_catch = parser
+	| [< '(Kwd Catch,_); '(POpen,_); '(Const (Ident name),_); '(DblDot,_); t = parse_type_path; e = expr >] -> (name,t,e)
+
+let parse code file =
+	let old = Lexer.save() in
+	Lexer.init file;
+	let last = ref (Eof,null_pos) in
+	let rec next_token x =
+		let t, p = Lexer.token code in
+		match t with 
+		| Comment s | CommentLine s -> 
+			next_token x
+		| _ ->
+			last := (t , p);
+			Some (t , p)
+	in
+	try
+		let l = parse_file (Stream.from next_token) in
+		Lexer.restore old;
+		l
+	with
+		| Stream.Error _
+		| Stream.Failure -> 
+			Lexer.restore old;
+			error (Unexpected (fst !last)) (pos !last)
+		| e ->
+			Lexer.restore old;
+			raise e

+ 36 - 0
plugin.ml

@@ -0,0 +1,36 @@
+(*
+ *  Haxe Compiler
+ *  Copyright (c)2005 Nicolas Cannasse
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *)
+
+let verbose = ref false
+
+let options = ref ([] : (string * Arg.spec * string) list)
+
+let class_path = ref ([] : string list)
+
+let find_file f =
+	let rec loop = function
+		| [] -> raise Not_found
+		| p :: l ->
+			let file = p ^ f in
+			if Sys.file_exists file then
+				file
+			else
+				loop l
+	in
+	loop !class_path