Added REGEX!!!!!
Started working on automatic imports
This commit is contained in:
+1
-12
@@ -48,6 +48,7 @@ enum Error
|
||||
EUnexpected( s : String );
|
||||
EUnterminatedString;
|
||||
EUnterminatedComment;
|
||||
EUnterminatedRegex;
|
||||
EInvalidPreprocessor( msg : String );
|
||||
EUnknownVariable( v : String );
|
||||
EInvalidIterator( v : String );
|
||||
@@ -79,16 +80,4 @@ enum abstract ErrorMessage(Int) from Int to Int {
|
||||
case EXPECT_KEY_VALUE_SYNTAX: "Expected a => b";
|
||||
}
|
||||
}
|
||||
|
||||
public static function fromString(s:String):ErrorMessage {
|
||||
return switch(s) {
|
||||
case "INVALID_CHAR_CODE_MULTI": INVALID_CHAR_CODE_MULTI;
|
||||
case "FROM_CHAR_CODE_NON_INT": FROM_CHAR_CODE_NON_INT;
|
||||
case "EMPTY_INTERPOLATION": EMPTY_INTERPOLATION;
|
||||
case "UNKNOWN_MAP_TYPE": UNKNOWN_MAP_TYPE;
|
||||
case "UNKNOWN_MAP_TYPE_RUNTIME": UNKNOWN_MAP_TYPE_RUNTIME;
|
||||
case "EXPECT_KEY_VALUE_SYNTAX": EXPECT_KEY_VALUE_SYNTAX;
|
||||
default: throw "Unknown ErrorMessage";
|
||||
}
|
||||
}
|
||||
}
|
||||
+78
-1
@@ -46,6 +46,7 @@ enum Token {
|
||||
TEof;
|
||||
TConst( c : Const );
|
||||
TInterpString( tkl: Array<TokenList> ); // Stores the tokens that make up the interpolation string
|
||||
TRegex( r: String, opt: String );
|
||||
TId( s : String );
|
||||
TOp( s : String );
|
||||
TPOpen;
|
||||
@@ -103,7 +104,7 @@ class Parser {
|
||||
/**
|
||||
resume from parsing errors (when parsing incomplete code, during completion for example)
|
||||
**/
|
||||
public var resumeErrors : Bool;
|
||||
public var resumeErrors : Bool = false;
|
||||
|
||||
// implementation
|
||||
var input : String;
|
||||
@@ -479,6 +480,9 @@ class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
return parseExprNext(e);
|
||||
case TRegex(r, opt):
|
||||
var e = mk(EParent(mk(ENew("EReg", [mk(EConst(CString(r))), mk(EConst(CString(opt)))]), p1)), p1);
|
||||
return parseExprNext(e);
|
||||
case TPOpen:
|
||||
tk = token();
|
||||
@@ -2315,6 +2319,27 @@ class Parser {
|
||||
}
|
||||
invalidChar(char);
|
||||
default:
|
||||
if(char == '~'.code) {
|
||||
var char = readChar();
|
||||
if( char == "/".code ) {
|
||||
var regex = getRegexBody();
|
||||
var opt = "";
|
||||
while( true ) {
|
||||
char = readChar();
|
||||
if( char != 'g'.code && char != 'i'.code && char != 'm'.code && char != 's'.code && char != 'u'.code ) {
|
||||
if( char >= 'a'.code && char <= 'z'.code ) {
|
||||
error(ECustom('Invalid regex expression option "' + String.fromCharCode(char) + '"'), readPos, readPos);
|
||||
}
|
||||
this.char = char;
|
||||
return TRegex(regex, opt);
|
||||
}
|
||||
opt += String.fromCharCode(char);
|
||||
}
|
||||
}
|
||||
readPos--;
|
||||
//this.char = peekChar();
|
||||
}
|
||||
|
||||
if( ops[char] ) {
|
||||
var op = String.fromCharCode(char);
|
||||
while( true ) {
|
||||
@@ -2354,6 +2379,57 @@ class Parser {
|
||||
return null;
|
||||
}
|
||||
|
||||
function getRegexBody() {
|
||||
var regex = new StringBuf();
|
||||
var esc = false;
|
||||
var start = readPos-2;
|
||||
while( true ) {
|
||||
var char = readChar();
|
||||
if(StringTools.isEof(char))
|
||||
error(EUnterminatedRegex, start, start);
|
||||
if( char == "\n".code || char == "\r".code )
|
||||
error(EUnterminatedRegex, start, readPos-1);
|
||||
|
||||
if( esc ) {
|
||||
esc = false;
|
||||
switch( char ) {
|
||||
case '/'.code: regex.addChar("/".code);
|
||||
case 'n'.code: regex.addChar("\n".code);
|
||||
case 'r'.code: regex.addChar("\r".code);
|
||||
case 't'.code: regex.addChar("\t".code);
|
||||
case '\\'.code, '$'.code, '.'.code, '*'.code, '+'.code, '^'.code, '|'.code, '{'.code, '}'.code, '['.code, ']'.code, '('.code, ')'.code, '?'.code, '-'.code:
|
||||
regex.addChar(char);
|
||||
case '0'.code | '1'.code | '2'.code | '3'.code | '4'.code | '5'.code | '6'.code | '7'.code | '8'.code | '9'.code:
|
||||
regex.addChar("\\".code);
|
||||
regex.addChar(char);
|
||||
case 'w'.code, 'W'.code, 'b'.code, 'B'.code, 's'.code, 'S'.code, 'd'.code, 'D'.code, 'x'.code:
|
||||
regex.addChar("\\".code);
|
||||
regex.addChar(char);
|
||||
case 'u'.code, 'U'.code: // UNICODE
|
||||
regex.addChar("\\".code);
|
||||
for( i in 0...4 ) {
|
||||
var c = readChar();
|
||||
if( StringTools.isEof(c) )
|
||||
error(EUnterminatedRegex, start, readPos-1);
|
||||
var h = convertHex(c);
|
||||
if( h == -1 )
|
||||
invalidChar(c);
|
||||
regex.addChar(c);
|
||||
}
|
||||
|
||||
default: invalidChar(char);
|
||||
}
|
||||
} else if( char == "\\".code ) {
|
||||
esc = true;
|
||||
continue;
|
||||
} else if( char == "/".code )
|
||||
break;
|
||||
else
|
||||
regex.addChar(char);
|
||||
}
|
||||
return regex.toString();
|
||||
}
|
||||
|
||||
function preprocValue( id : String ) : Dynamic {
|
||||
return preprocesorValues.get(id);
|
||||
}
|
||||
@@ -2531,6 +2607,7 @@ class Parser {
|
||||
case TEof: "<eof>";
|
||||
case TConst(c): constString(c);
|
||||
case TInterpString(tg): constInterpString(tg);
|
||||
case TRegex(r, opt): '~/' + r + '/' + opt;
|
||||
case TId(s): s;
|
||||
case TOp(s): s;
|
||||
case TPOpen: "(";
|
||||
|
||||
+43
-2
@@ -9,19 +9,54 @@ import hscript.Parser;
|
||||
class Preprocessor {
|
||||
static inline function expr(e:Expr) return Tools.expr(e);
|
||||
|
||||
private static var importStack:Array<Array<String>> = [];
|
||||
private static function addImport(e:String, ?as:String) {
|
||||
for(i in importStack)
|
||||
if(i[0] == e)
|
||||
return;
|
||||
importStack.push([e, as]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Preprocesses the expression, like 'a'.code => 97
|
||||
* Also for transforming any abstracts into their implementations (TODO)
|
||||
* Also for transforming any static extensions into their real form (TODO)
|
||||
* Also to automatically add imports for stuff that is not imported
|
||||
**/
|
||||
public static function process(e:Expr, doBlock:Bool = true):Expr {
|
||||
public static function process(e:Expr, top:Bool = true):Expr {
|
||||
importStack = [];
|
||||
var e = _process(e, top);
|
||||
|
||||
// Automatically add imports for stuff
|
||||
switch(expr(e)) {
|
||||
case EBlock(exprs):
|
||||
while(importStack.length > 0) {
|
||||
var im = importStack.pop();
|
||||
exprs.unshift(mk(EImport(im[0], im[1]), e));
|
||||
}
|
||||
return mk(EBlock(exprs), e);
|
||||
default:
|
||||
if(importStack.length > 0) {
|
||||
var exprs = [];
|
||||
while(importStack.length > 0) {
|
||||
var im = importStack.pop();
|
||||
exprs.unshift(mk(EImport(im[0], im[1]), e));
|
||||
}
|
||||
exprs.push(e);
|
||||
return mk(EBlock(exprs), e);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
private static function _process(e:Expr, top:Bool = true):Expr {
|
||||
if(e == null)
|
||||
return null;
|
||||
|
||||
//trace(expr(e));
|
||||
|
||||
e = Tools.map(e, function(e) {
|
||||
return process(e);
|
||||
return _process(e, false);
|
||||
});
|
||||
|
||||
switch(expr(e)) {
|
||||
@@ -42,6 +77,12 @@ class Preprocessor {
|
||||
#else
|
||||
throw Parser.getBaseError(EPreset(FROM_CHAR_CODE_NON_INT));
|
||||
#end
|
||||
case ENew("String", _):
|
||||
addImport("String");
|
||||
case ENew("EReg", _):
|
||||
addImport("EReg");
|
||||
case EField(expr(_) => EIdent("EReg"), "escape", _):
|
||||
addImport("EReg");
|
||||
default:
|
||||
}
|
||||
|
||||
|
||||
@@ -534,6 +534,7 @@ class Printer {
|
||||
case EUnexpected(s): "Unexpected token: \""+s+"\"";
|
||||
case EUnterminatedString: "Unterminated string";
|
||||
case EUnterminatedComment: "Unterminated comment";
|
||||
case EUnterminatedRegex: "Unterminated regular expression";
|
||||
case EInvalidPreprocessor(str): "Invalid preprocessor (" + str + ")";
|
||||
case EUnknownVariable(v): "Unknown variable: "+v;
|
||||
case EInvalidIterator(v): "Invalid iterator: "+v;
|
||||
|
||||
Reference in New Issue
Block a user