Telecomms Refactor & CodeMirror

This commit does the following:
 - A lot of shit I am really too tired to fucking write about
 - Absolute pathed telecomms scripting
 - Browser Datum traffic control
  - Absolutely lovely replacement for the fucking skin TCS window, using
    codemirror
 - CodeMirror integration for nanoUI
  - Sorta, I didn't work on this as much as I wanted to, because IT TOOK
    11 FUCKING HOURS TO GET THE BROWSER DATUM TO WORK
This commit is contained in:
Tigercat2000
2015-10-28 17:23:22 -07:00
parent f76109ca5c
commit c244a0fe15
38 changed files with 13973 additions and 2155 deletions
+157 -119
View File
@@ -12,17 +12,17 @@ var/const/KW_WARN = 3 //Warning
var/const/Class: n_Keyword
var/const/Represents a special statement in the code triggered by a keyword.
*/
/n_Keyword
New(inline=0)
src.inline=inline
return ..()
/datum/n_Keyword
/*
Var: inline
1 if the keyword is in an expression (e.g. the new keyword in many languages), 0 otherwise (such as the if and else keywords).
*/
var/inline
/datum/n_Keyword/New(inline = 0)
src.inline = inline
return ..()
/*
Proc: Parse
Called when the parser finds a keyword in the code.
@@ -31,8 +31,8 @@ var/const/Represents a special statement in the code triggered by a keyword.
parser - The parser that created this object. You can use the parameter to manipulate the parser in order to add statements and blocks
to its AST.
*/
proc/Parse(n_Parser/parser)
/datum/n_Keyword/proc/Parse(var/datum/n_Parser/parser)
return
/*
Class: nS_Keyword
A keyword in n_Script. By default these include return, if, else, while, and def. To enable or disable a keyword, change the
@@ -42,125 +42,163 @@ var/const/Represents a special statement in the code triggered by a keyword.
When a parser is expecting a new statement, and a keyword listed in <nS_Options.keywords> is found, it will call the keyword's
<n_Keyword.Parse()> proc.
*/
//
nS_Keyword
New(inline=0)
if(inline)
del(src)
/datum/n_Keyword/nS_Keyword/New(var/inline = 0)
if(inline)
del src
kwReturn
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
parser.errors+=new/scriptError/BadReturn(parser.curToken)
. = KW_WARN
var/node/statement/ReturnStatement/stmt=new
parser.NextToken() //skip 'return' token
stmt.value=parser.ParseExpression()
parser.curBlock.statements+=stmt
/datum/n_Keyword/nS_Keyword/kwReturn/Parse(var/datum/n_Parser/nS_Parser/parser)
. = KW_PASS
if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock)) // Exit out of the program by setting the tokens list size to the same as index.
parser.tokens.len = parser.index
return
kwIf
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/node/statement/IfStatement/stmt=new
parser.NextToken() //skip 'if' token
stmt.cond=parser.ParseParenExpression()
if(!parser.CheckToken(")", /token/symbol))
return KW_FAIL
if(!parser.CheckToken("{", /token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0
return KW_ERR
parser.curBlock.statements+=stmt
stmt.block=new
parser.AddBlock(stmt.block)
var/datum/node/statement/ReturnStatement/stmt = new
parser.NextToken() //skip 'return' token
stmt.value = parser.ParseExpression()
parser.curBlock.statements += stmt
kwElse
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/list/L=parser.curBlock.statements
var/node/statement/IfStatement/stmt
if(L&&L.len) stmt=L[L.len] //Get the last statement in the current block
if(!stmt || !istype(stmt) || stmt.else_block) //Ensure that it is an if statement
parser.errors+=new/scriptError/ExpectedToken("if statement",parser.curToken)
return KW_FAIL
parser.NextToken() //skip 'else' token
if(!parser.CheckToken("{", /token/symbol, skip=0))
return KW_ERR
stmt.else_block=new()
parser.AddBlock(stmt.else_block)
/datum/n_Keyword/nS_Keyword/kwIf/Parse(var/datum/n_Parser/nS_Parser/parser)
. = KW_PASS
var/datum/node/statement/IfStatement/stmt = new
parser.NextToken() //skip 'if' token
stmt.cond = parser.ParseParenExpression()
if(!parser.CheckToken(")", /datum/token/symbol))
return KW_FAIL
kwWhile
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/node/statement/WhileLoop/stmt=new
parser.NextToken() //skip 'while' token
stmt.cond=parser.ParseParenExpression()
if(!parser.CheckToken(")", /token/symbol))
return KW_FAIL
if(!parser.CheckToken("{", /token/symbol, skip=0))
return KW_ERR
parser.curBlock.statements+=stmt
stmt.block=new
parser.AddBlock(stmt.block)
if(!parser.CheckToken("{", /datum/token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0
return KW_ERR
kwBreak
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
parser.errors+=new/scriptError/BadToken(parser.curToken)
. = KW_WARN
var/node/statement/BreakStatement/stmt=new
parser.NextToken() //skip 'break' token
parser.curBlock.statements+=stmt
parser.curBlock.statements += stmt
stmt.block = new
parser.AddBlock(stmt.block)
kwContinue
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
parser.errors+=new/scriptError/BadToken(parser.curToken)
. = KW_WARN
var/node/statement/ContinueStatement/stmt=new
parser.NextToken() //skip 'break' token
parser.curBlock.statements+=stmt
/datum/n_Keyword/nS_Keyword/kwElseIf/Parse(var/datum/n_Parser/nS_Parser/parser)
. = KW_PASS
var/list/L = parser.curBlock.statements
var/datum/node/statement/IfStatement/ifstmt
kwDef
Parse(n_Parser/nS_Parser/parser)
.=KW_PASS
var/node/statement/FunctionDefinition/def=new
parser.NextToken() //skip 'def' token
if(!parser.options.IsValidID(parser.curToken.value))
parser.errors+=new/scriptError/InvalidID(parser.curToken)
return KW_FAIL
def.func_name=parser.curToken.value
parser.NextToken()
if(!parser.CheckToken("(", /token/symbol))
return KW_FAIL
for() //for now parameters can be separated by whitespace - they don't need a comma in between
if(istype(parser.curToken, /token/symbol))
switch(parser.curToken.value)
if(",")
parser.NextToken()
if(")")
break
else
parser.errors+=new/scriptError/BadToken(parser.curToken)
return KW_ERR
if(L && L.len)
ifstmt = L[L.len] //Get the last statement in the current block
else if(istype(parser.curToken, /token/word))
def.parameters+=parser.curToken.value
parser.NextToken()
else
parser.errors+=new/scriptError/InvalidID(parser.curToken)
return KW_ERR
if(!parser.CheckToken(")", /token/symbol))
return KW_FAIL
if(!ifstmt || !istype(ifstmt) || ifstmt.else_if)
usr << "NTSL: ELSE IF FAILED: [!ifstmt], [!istype(ifstmt)], [!istype(ifstmt) || ifstmt.else_if]" // Usr is unsafe as SHIT but JUST incase I forget this debug line like the fucking asset cache...
parser.errors += new/datum/scriptError/ExpectedToken("if statement", parser.curToken)
return KW_FAIL
if(istype(parser.curToken, /token/end)) //Function prototype
parser.curBlock.statements+=def
else if(parser.curToken.value=="{" && istype(parser.curToken, /token/symbol))
def.block = new
parser.curBlock.statements+=def
parser.curBlock.functions[def.func_name]=def
parser.AddBlock(def.block)
var/datum/node/statement/IfStatement/ElseIf/stmt = new
parser.NextToken() //skip 'if' token
stmt.cond = parser.ParseParenExpression()
if(!parser.CheckToken(")", /datum/token/symbol))
return KW_FAIL
if(!parser.CheckToken("{", /datum/token/symbol, skip = 0)) //Token needs to be preserved for parse loop, so skip=0
return KW_ERR
parser.curBlock.statements += stmt
stmt.block = new
ifstmt.else_if = stmt
parser.AddBlock(stmt.block)
/datum/n_Keyword/nS_Keyword/kwElse/Parse(var/datum/n_Parser/nS_Parser/parser)
. = KW_PASS
var/list/L = parser.curBlock.statements
var/datum/node/statement/IfStatement/stmt
if(L && L.len)
stmt = L[L.len] //Get the last statement in the current block
if(!stmt || !istype(stmt) || stmt.else_block) //Ensure that it is an if statement
usr << "NTSL: ELSE IF FAILED: [!stmt], [!istype(stmt)], [!istype(stmt) || stmt.else_block]" // Usr is unsafe as SHIT but JUST incase I forget this debug line like the fucking asset cache...
parser.errors += new/datum/scriptError/ExpectedToken("if statement", parser.curToken)
return KW_FAIL
parser.NextToken() //skip 'else' token
if(!parser.CheckToken("{", /datum/token/symbol, skip = 0))
return KW_ERR
stmt.else_block = new()
parser.AddBlock(stmt.else_block)
/datum/n_Keyword/nS_Keyword/kwWhile/Parse(var/datum/n_Parser/nS_Parser/parser)
. = KW_PASS
var/datum/node/statement/WhileLoop/stmt = new
parser.NextToken() //skip 'while' token
stmt.cond = parser.ParseParenExpression()
if(!parser.CheckToken(")", /datum/token/symbol))
return KW_FAIL
if(!parser.CheckToken("{", /datum/token/symbol, skip=0))
return KW_ERR
parser.curBlock.statements += stmt
stmt.block = new
parser.AddBlock(stmt.block)
/datum/n_Keyword/nS_Keyword/kwBreak/Parse(var/datum/n_Parser/nS_Parser/parser)
. = KW_PASS
if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock))
parser.errors += new/datum/scriptError/BadToken(parser.curToken)
. = KW_WARN
var/datum/node/statement/BreakStatement/stmt = new
parser.NextToken() //skip 'break' token
parser.curBlock.statements += stmt
/datum/n_Keyword/nS_Keyword/kwContinue/Parse(var/datum/n_Parser/nS_Parser/parser)
. = KW_PASS
if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock))
parser.errors += new/datum/scriptError/BadToken(parser.curToken)
. = KW_WARN
var/datum/node/statement/ContinueStatement/stmt = new
parser.NextToken() //skip 'break' token
parser.curBlock.statements += stmt
/datum/n_Keyword/nS_Keyword/kwDef/Parse(var/datum/n_Parser/nS_Parser/parser)
. = KW_PASS
var/datum/node/statement/FunctionDefinition/def = new
parser.NextToken() //skip 'def' token
if(!parser.options.IsValidID(parser.curToken.value))
parser.errors += new/datum/scriptError/InvalidID(parser.curToken)
return KW_FAIL
def.func_name = parser.curToken.value
parser.NextToken()
if(!parser.CheckToken("(", /datum/token/symbol))
return KW_FAIL
for() //for now parameters can be separated by whitespace - they don't need a comma in between
if(istype(parser.curToken, /datum/token/symbol))
switch(parser.curToken.value)
if(",")
parser.NextToken()
if(")")
break
else
parser.errors+=new/scriptError/BadToken(parser.curToken)
return KW_FAIL
parser.errors += new/datum/scriptError/BadToken(parser.curToken)
return KW_ERR
else if(istype(parser.curToken, /datum/token/word))
def.parameters += parser.curToken.value
parser.NextToken()
else
parser.errors += new/datum/scriptError/InvalidID(parser.curToken)
return KW_ERR
if(!parser.CheckToken(")", /datum/token/symbol))
return KW_FAIL
if(istype(parser.curToken, /datum/token/end)) //Function prototype
parser.curBlock.statements += def
else if(parser.curToken.value == "{" && istype(parser.curToken, /datum/token/symbol))
def.block = new
parser.curBlock.statements += def
parser.curBlock.functions[def.func_name] = def
parser.AddBlock(def.block)
else
parser.errors += new/datum/scriptError/BadToken(parser.curToken)
return KW_FAIL