Skip to content

Instantly share code, notes, and snippets.

@vizanto
Last active September 18, 2017 18:51
Show Gist options
  • Save vizanto/b200479f43cd6f5568660225ff23a804 to your computer and use it in GitHub Desktop.
Save vizanto/b200479f43cd6f5568660225ff23a804 to your computer and use it in GitHub Desktop.
WIP: Clojure frontend for Haxe
package hxclj;
import hxclj.edn.Parser;
import byte.ByteData;
class Main {
static function main() {
var expr = "^:yo clojure.core// (.lol wut) .1 (+ 0N 0.1M 0xdeadbeef 1 2 ~a ~@aas)";
// trace("Parse ", expr);
var input = sys.io.File.getBytes("test.clj");
var parser = new Parser(@:privateAccess new ByteData(input), "test.clj");
parser.read();
}
}
package hxclj.edn;
import hxparse.Parser.parse as parse;
import haxe.io.Input;
private enum Token {
TBCurlyOpen; // {
TBCurlyClose; // }
TBRoundOpen; // (
TBRoundClose; // )
TBSquareOpen; // [
TBSquareClose; // ]
TCharacter(v:String); // \
TComment(v:String); // ;
TDispatch; // #
TMetadata; // ^
TInteger(v:String);
TRatio(v:String);
TFloat(v:String);
TNil;
TTrue;
TFalse;
TQuote; // '
TSyntaxQuote; // `
TUnQuote; // ~
TUnQuoteSplice; // ~@
TString(v:String); // "
TKeyword(v:String); // :TSymbol
TSymbol(v:String); // A-z 0-9, *, +, !, -, _, ', ?, /, and non-repeating :
TWhitespace(v:String); // , space etc
TEof;
}
/*
See: https://clojure.org/reference/reader
https://github.com/clojure/tools.reader/blob/master/src/main/clojure/clojure/tools/reader.clj
https://github.com/Simn/hxparse/blob/master/test/JSONParser.hx
*/
class CljLexer extends hxparse.Lexer implements hxparse.RuleBuilder
{
static var intPattern = ~/^([-+]?)(?:(0)|([1-9][0-9]*)|0[xX]([0-9A-Fa-f]+)|0([0-7]+)|([1-9][0-9]?)[rR]([0-9A-Za-z]+)|0[0-9]+)(N)?$/;
static var ratioPattern = ~/^([-+]?[0-9]+)\/([0-9]+)$/;
static var floatPattern = ~/^([-+]?[0-9]+(\.[0-9]*)?([eE][-+]?[0-9]+)?)M?$/;
public static var tok = @:rule [
"\\{" => TBCurlyOpen,
"\\}" => TBCurlyClose,
"\\(" => TBRoundOpen,
"\\)" => TBRoundClose,
"\\[" => TBSquareOpen,
"\\]" => TBSquareClose,
"\\\\([^ ,\r\n\t]+|[ \r\n])" => {
var v = lexer.current;
if (v.length == 2 || ~/^\\(newline|space|tab|formfeed|backspace|return|u[0-9A-Fa-f]+)$/.match(v))
TCharacter(v);
else throw 'Unsupported character: "${v}"';
},
";[^\r\n]*" => TComment(lexer.current),
"#" => TDispatch,
"^" => TMetadata,
"[-+]?[0-9]+[0-9xXA-Fa-feErRMN.]*" => {
var v = lexer.current;
if ( intPattern.match(v)) TInteger(v);
else if (ratioPattern.match(v)) TRatio(v);
else if (floatPattern.match(v)) TFloat(v);
else throw "Invalid number: " + v;
},
'nil' => TNil,
'true' => TTrue,
'false' => TFalse,
"'" => TQuote,
'`' => TSyntaxQuote,
'~' => TUnQuote,
'~@' => TUnQuoteSplice,
'"' => {
buf = new StringBuf();
lexer.token(string);
TString(buf.toString());
},
':[^ ,\r\n\t";@^`~()\\[\\]{}\\\\]+' => TKeyword(lexer.current), // ':[-a-zA-Z*+!_\'?/.][-0-9a-zA-Z*+!_\'?/.]*'
'[^ ,\r\n\t";@^`~()\\[\\]{}\\\\]+' => TSymbol(lexer.current), // '[-a-zA-Z*+!_\'?/.][-0-9a-zA-Z*+!_\'?/.]*'
"[ ,\r\n\t]+" => cast(lexer, CljLexer).handleWhitespace(),
"" => TEof
];
function handleWhitespace() {
return if (false) TWhitespace(current); else token(tok);
}
static var buf:StringBuf;
public static var string = @:rule [
'\\\\"' => {
buf.add(lexer.current);
lexer.token(string);
},
'\\\\' => {
buf.addChar('\\'.code);
lexer.token(string);
},
'"' => {
lexer.curPos().pmax;
},
'[^\\\\"]+' => {
buf.add(lexer.current);
lexer.token(string);
},
];
}
class Parser extends hxparse.Parser<hxparse.LexerTokenSource<Token>, Token>
{
public function new(input:byte.ByteData, sourceName:String) {
var lexer = new CljLexer(input, sourceName);
var ts = new hxparse.LexerTokenSource(lexer, CljLexer.tok);
super(ts);
}
public function read() {
var token = null;
while ((token = stream.token()) != TEof) trace(token);
// return parse(switch stream {
// case t: trace(t);
// });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment