Created
May 4, 2019 14:22
-
-
Save somebody1234/88b8d71c3461c5a56aa72ca2cc9b86db to your computer and use it in GitHub Desktop.
vscode-snippet-parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* SnippetParser.re | |
* | |
* Module for parsing snippets??? | |
*/ | |
open CharCode; | |
module TokenType = { | |
let dollar = 0; | |
let colon = 1; | |
let comma = 2; | |
let curlyOpen = 4; | |
let curlyClose = 5; | |
let backslash = 6; | |
let forwardslash = 7; | |
let pipe = 8; | |
let int = 9; | |
let variableName = 10; | |
let format = 11; | |
let plus = 12; | |
let dash = 13; | |
let questionMark = 14; | |
let EOF = 15; | |
}; | |
module Token = { | |
type t = { | |
/* originally called `type` but that's a keyword */ | |
tokenType: int, | |
pos: int, | |
len: int | |
}; | |
}; | |
/* TODO: make this actually ok */ | |
module Scanner = { | |
/* private static */ | |
let _table = (ch: int) => { | |
if (ch < 255) { | |
switch (char_of_int(ch)) { | |
| '$' => Some(TokenType.dollar) | |
| ':' => Some(TokenType.colon) | |
| ',' => Some(TokenType.comma) | |
| '{' => Some(TokenType.curlyOpen) | |
| '}' => Some(TokenType.curlyClose) | |
| int_of_char('\\') => Some(TokenType.backslash) | |
| '/' => Some(TokenType.forwardslash) | |
| '|' => Some(TokenType.pipe) | |
| '+' => Some(TokenType.plus) | |
| '-' => Some(TokenType.dash) | |
| '?' => Some(TokenType.questionMark) | |
| _ => None | |
}; | |
} else { | |
None; | |
}; | |
}; | |
let isDigitCharacter = (ch: int) => { | |
ch >= int_of_char('0') && ch <= int_of_char('9') | |
}; | |
let isVariableCharacter = (ch: int) => { | |
ch === int_of_char('_') | |
|| (ch >= int_of_char('a') && ch <= int_of_char('z')) | |
|| (ch >= int_of_char('A') && ch <= int_of_char('Z')); | |
}; | |
type t = { | |
value: string, | |
mutable pos: int | |
}; | |
/* useless constructor? */ | |
let text = (value: string) => { | |
{value, pos: 0}; | |
}; | |
let tokenText = (v: t, token: Token.t) => { | |
/* TODO: return a view instead of a copy? */ | |
String.sub(v.value, token.pos, token.len) | |
}; | |
let next = (v: t) => { | |
if (v.pos > String.length(v.value)) { | |
{type: TokenType.EOF, pos: this.pos, len: 0}; | |
} else { | |
let pos = v.pos; | |
let len = v.len; | |
/* TODO: unicode */ | |
let ch = v[pos]; | |
let chlen = 1; | |
/* TODO: any way to declare type but not value? */ | |
let optionType = ref(Some(0)); | |
let type = ref(0); | |
/* static types */ | |
type := Scanner._table(ch); | |
switch (type^) { | |
| Some(n) => { | |
v.pos = v.pos + 1; | |
{type, pos, len: 1}; | |
} | |
| None => { | |
/* number */ | |
if (Scanner.isDigitCharacter(ch)) { | |
type := TokenType.int; | |
let newLen = ref(len); | |
let newCh = ref(ch); | |
while (Scanner.isDigitCharacter(newCh^)) { | |
newLen := newLen^ + 1; | |
/* TODO: unicode */ | |
newCh := v.value.[pos + newLen^]; | |
} | |
v.pos = v.pos + newLen^; | |
return {type: type^, pos, len: newLen^}; | |
} | |
/* variable name */ | |
if (Scanner.isVariableCharacter(ch)) { | |
type := TokenType.variableName; | |
let newLen = ref(len); | |
let newCh = ref(ch); | |
while (Scanner.isVariableCharacter(ch) || Scanner.isDigitCharacter(newCh^)) { | |
newLen := newLen^ + 1; | |
/* TODO: unicode */ | |
newCh := v.value.[pos + newLen^]; | |
} | |
v.pos = v.pos + newLen^; | |
return {type: type^, pos, len: newLen^}; | |
} | |
/* format */ | |
type := TokenType.format; | |
/* TODO is the first iteration also guaranteed to meet the conditions */ | |
let newLen = ref(len + 1); | |
/* TODO: unicode */ | |
let newCh = v.value.[pos + newLen^]; | |
/* TODO: isNaN */ | |
while ( | |
!isNaN(ch) | |
&& Scanner._table(ch) === None /* not static token */ | |
&& !Scanner.isDigitCharacter(ch) /* not number */ | |
&& !Scanner.isVariableCharacter(ch) /* not variable */ | |
) { | |
let newLen = ref(len + 1); | |
let newCh = v.value.[pos + newLen^]; | |
} | |
v.pos = v.pos + newLen^; | |
return {type: type^, pos, len: newLen^}; | |
} | |
} | |
}; | |
} | |
}; | |
module Marker = { | |
type t = { | |
_markerBrand: int, /* TODO: uhh it's never actually used */ | |
parent: marker, | |
_children: array(marker) | |
}; | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment