mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-07-18 19:53:35 +01:00
[MIRROR] Staticpath [MDB ignore] (#12445)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
cc106f8032
commit
ba5224fbcb
@@ -30,88 +30,88 @@
|
||||
/*
|
||||
Class: node
|
||||
*/
|
||||
/node/proc/ToString()
|
||||
/datum/node/proc/ToString()
|
||||
return "[src.type]"
|
||||
/*
|
||||
Class: identifier
|
||||
*/
|
||||
/node/identifier
|
||||
/datum/node/identifier
|
||||
var/id_name
|
||||
|
||||
/node/identifier/New(id)
|
||||
/datum/node/identifier/New(id)
|
||||
.=..()
|
||||
src.id_name=id
|
||||
|
||||
/node/identifier/ToString()
|
||||
/datum/node/identifier/ToString()
|
||||
return id_name
|
||||
|
||||
/*
|
||||
Class: expression
|
||||
*/
|
||||
/node/expression
|
||||
/datum/node/expression
|
||||
/*
|
||||
Class: operator
|
||||
See <Binary Operators> and <Unary Operators> for subtypes.
|
||||
*/
|
||||
/node/expression/op
|
||||
var/node/expression/exp
|
||||
/datum/node/expression/op
|
||||
var/datum/node/expression/exp
|
||||
var/tmp/name
|
||||
var/tmp/precedence
|
||||
|
||||
/node/expression/op/New()
|
||||
/datum/node/expression/op/New()
|
||||
.=..()
|
||||
if(!src.name) src.name="[src.type]"
|
||||
|
||||
/node/expression/op/ToString()
|
||||
/datum/node/expression/op/ToString()
|
||||
return "operator: [name]"
|
||||
|
||||
/*
|
||||
Class: FunctionCall
|
||||
*/
|
||||
/node/expression/FunctionCall
|
||||
/datum/node/expression/FunctionCall
|
||||
//Function calls can also be expressions or statements.
|
||||
var/func_name
|
||||
var/node/identifier/object
|
||||
var/datum/node/identifier/object
|
||||
var/list/parameters = list()
|
||||
|
||||
/*
|
||||
Class: literal
|
||||
*/
|
||||
/node/expression/value/literal
|
||||
/datum/node/expression/value/literal
|
||||
var/value
|
||||
|
||||
/node/expression/value/literal/New(value)
|
||||
/datum/node/expression/value/literal/New(value)
|
||||
.=..()
|
||||
src.value=value
|
||||
|
||||
/node/expression/value/literal/ToString()
|
||||
/datum/node/expression/value/literal/ToString()
|
||||
return src.value
|
||||
|
||||
/*
|
||||
Class: variable
|
||||
*/
|
||||
/node/expression/value/variable
|
||||
var/node/object //Either a node/identifier or another node/expression/value/variable which points to the object
|
||||
var/node/identifier/id
|
||||
/datum/node/expression/value/variable
|
||||
var/datum/node/object //Either a node/identifier or another node/expression/value/variable which points to the object
|
||||
var/datum/node/identifier/id
|
||||
|
||||
|
||||
/node/expression/value/variable/New(ident)
|
||||
/datum/node/expression/value/variable/New(ident)
|
||||
.=..()
|
||||
id=ident
|
||||
if(istext(id))id=new(id)
|
||||
|
||||
/node/expression/value/variable/ToString()
|
||||
/datum/node/expression/value/variable/ToString()
|
||||
return src.id.ToString()
|
||||
|
||||
/*
|
||||
Class: reference
|
||||
*/
|
||||
/node/expression/value/reference
|
||||
/datum/node/expression/value/reference
|
||||
var/datum/value
|
||||
|
||||
/node/expression/value/reference/New(value)
|
||||
/datum/node/expression/value/reference/New(value)
|
||||
.=..()
|
||||
src.value=value
|
||||
|
||||
/node/expression/value/reference/ToString()
|
||||
/datum/node/expression/value/reference/ToString()
|
||||
return "ref: [src.value] ([src.value.type])"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
it is possible to have a function definition inside of any type of block (such as in an if statement or another function),
|
||||
and not just in the global scope as in many languages.
|
||||
*/
|
||||
/node/BlockDefinition
|
||||
/datum/node/BlockDefinition
|
||||
var/list/statements = list()
|
||||
var/list/functions = list()
|
||||
var/list/initial_variables = list()
|
||||
@@ -24,7 +24,7 @@
|
||||
See Also:
|
||||
- <n_Interpreter.SetVar()>
|
||||
*/
|
||||
/node/BlockDefinition/proc/SetVar(name, value)
|
||||
/datum/node/BlockDefinition/proc/SetVar(name, value)
|
||||
initial_variables[name]=value
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
A block object representing the global scope.
|
||||
*/
|
||||
//
|
||||
/node/BlockDefinition/GlobalBlock/New()
|
||||
/datum/node/BlockDefinition/GlobalBlock/New()
|
||||
initial_variables["null"]=null
|
||||
return ..()
|
||||
|
||||
@@ -42,4 +42,4 @@
|
||||
A block representing a function body.
|
||||
*/
|
||||
//
|
||||
/node/BlockDefinition/FunctionBlock
|
||||
/datum/node/BlockDefinition/FunctionBlock
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
Class: binary
|
||||
Represents a binary operator in the AST. A binary operator takes two operands (ie x and y) and returns a value.
|
||||
*/
|
||||
/node/expression/op/binary
|
||||
var/node/expression/exp2
|
||||
/datum/node/expression/op/binary
|
||||
var/datum/node/expression/exp2
|
||||
|
||||
////////// Comparison Operators //////////
|
||||
/*
|
||||
@@ -16,7 +16,7 @@
|
||||
Returns true if x = y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Equal
|
||||
/datum/node/expression/op/binary/Equal
|
||||
precedence=OOP_EQUAL
|
||||
|
||||
/*
|
||||
@@ -24,7 +24,7 @@
|
||||
Returns true if x and y aren't equal.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/NotEqual
|
||||
/datum/node/expression/op/binary/NotEqual
|
||||
precedence=OOP_EQUAL
|
||||
|
||||
/*
|
||||
@@ -32,7 +32,7 @@
|
||||
Returns true if x > y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Greater
|
||||
/datum/node/expression/op/binary/Greater
|
||||
precedence=OOP_COMPARE
|
||||
|
||||
/*
|
||||
@@ -40,7 +40,7 @@
|
||||
Returns true if x < y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Less
|
||||
/datum/node/expression/op/binary/Less
|
||||
precedence=OOP_COMPARE
|
||||
|
||||
/*
|
||||
@@ -48,7 +48,7 @@
|
||||
Returns true if x >= y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/GreaterOrEqual
|
||||
/datum/node/expression/op/binary/GreaterOrEqual
|
||||
precedence=OOP_COMPARE
|
||||
|
||||
/*
|
||||
@@ -56,7 +56,7 @@
|
||||
Returns true if x <= y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/LessOrEqual
|
||||
/datum/node/expression/op/binary/LessOrEqual
|
||||
precedence=OOP_COMPARE
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
Returns true if x and y are true.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/LogicalAnd
|
||||
/datum/node/expression/op/binary/LogicalAnd
|
||||
precedence=OOP_AND
|
||||
|
||||
/*
|
||||
@@ -75,7 +75,7 @@
|
||||
Returns true if x, y, or both are true.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/LogicalOr
|
||||
/datum/node/expression/op/binary/LogicalOr
|
||||
precedence=OOP_OR
|
||||
|
||||
/*
|
||||
@@ -83,7 +83,7 @@
|
||||
Returns true if either x or y but not both are true.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/LogicalXor //Not implemented in nS
|
||||
/datum/node/expression/op/binary/LogicalXor //Not implemented in nS
|
||||
precedence=OOP_OR
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
011 & 110 = 010
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/BitwiseAnd
|
||||
/datum/node/expression/op/binary/BitwiseAnd
|
||||
precedence=OOP_BIT
|
||||
|
||||
/*
|
||||
@@ -108,7 +108,7 @@
|
||||
011 | 110 = 111
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/BitwiseOr
|
||||
/datum/node/expression/op/binary/BitwiseOr
|
||||
precedence=OOP_BIT
|
||||
|
||||
/*
|
||||
@@ -119,7 +119,7 @@
|
||||
011 xor 110 = 101
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/BitwiseXor
|
||||
/datum/node/expression/op/binary/BitwiseXor
|
||||
precedence=OOP_BIT
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
Returns the sum of x and y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Add
|
||||
/datum/node/expression/op/binary/Add
|
||||
precedence=OOP_ADD
|
||||
|
||||
/*
|
||||
@@ -138,7 +138,7 @@
|
||||
Returns the difference of x and y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Subtract
|
||||
/datum/node/expression/op/binary/Subtract
|
||||
precedence=OOP_ADD
|
||||
|
||||
/*
|
||||
@@ -146,7 +146,7 @@
|
||||
Returns the product of x and y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Multiply
|
||||
/datum/node/expression/op/binary/Multiply
|
||||
precedence=OOP_MULTIPLY
|
||||
|
||||
/*
|
||||
@@ -154,7 +154,7 @@
|
||||
Returns the quotient of x and y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Divide
|
||||
/datum/node/expression/op/binary/Divide
|
||||
precedence=OOP_MULTIPLY
|
||||
|
||||
/*
|
||||
@@ -162,7 +162,7 @@
|
||||
Returns x raised to the power of y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Power
|
||||
/datum/node/expression/op/binary/Power
|
||||
precedence=OOP_POW
|
||||
|
||||
/*
|
||||
@@ -170,5 +170,5 @@
|
||||
Returns the remainder of x / y.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/binary/Modulo
|
||||
/datum/node/expression/op/binary/Modulo
|
||||
precedence=OOP_MULTIPLY
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Class: unary
|
||||
Represents a unary operator in the AST. Unary operators take a single operand (referred to as x below) and return a value.
|
||||
*/
|
||||
/node/expression/op/unary
|
||||
/datum/node/expression/op/unary
|
||||
precedence=OOP_UNARY
|
||||
|
||||
/*
|
||||
@@ -16,7 +16,7 @@
|
||||
!true = false and !false = true
|
||||
*/
|
||||
//
|
||||
/node/expression/op/unary/LogicalNot
|
||||
/datum/node/expression/op/unary/LogicalNot
|
||||
name="logical not"
|
||||
|
||||
/*
|
||||
@@ -27,7 +27,7 @@
|
||||
~10 (decimal 2) = 01 (decimal 1).
|
||||
*/
|
||||
//
|
||||
/node/expression/op/unary/BitwiseNot
|
||||
/datum/node/expression/op/unary/BitwiseNot
|
||||
name="bitwise not"
|
||||
|
||||
/*
|
||||
@@ -35,7 +35,7 @@
|
||||
Returns -x.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/unary/Minus
|
||||
/datum/node/expression/op/unary/Minus
|
||||
name="minus"
|
||||
|
||||
/*
|
||||
@@ -43,9 +43,9 @@
|
||||
A special unary operator representing a value in parentheses.
|
||||
*/
|
||||
//
|
||||
/node/expression/op/unary/group
|
||||
/datum/node/expression/op/unary/group
|
||||
precedence=OOP_GROUP
|
||||
|
||||
/node/expression/op/unary/New(node/expression/exp)
|
||||
/datum/node/expression/op/unary/New(datum/node/expression/exp)
|
||||
src.exp=exp
|
||||
return ..()
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
Class: statement
|
||||
An object representing a single instruction run by an interpreter.
|
||||
*/
|
||||
/node/statement
|
||||
/datum/node/statement
|
||||
/*
|
||||
Class: FunctionCall
|
||||
Represents a call to a function.
|
||||
*/
|
||||
//
|
||||
/node/statement/FunctionCall
|
||||
/datum/node/statement/FunctionCall
|
||||
var/func_name
|
||||
var/node/identifier/object
|
||||
var/datum/node/identifier/object
|
||||
var/list/parameters=list()
|
||||
|
||||
/*
|
||||
@@ -21,10 +21,10 @@
|
||||
Defines a function.
|
||||
*/
|
||||
//
|
||||
/node/statement/FunctionDefinition
|
||||
/datum/node/statement/FunctionDefinition
|
||||
var/func_name
|
||||
var/list/parameters=list()
|
||||
var/node/BlockDefinition/FunctionBlock/block
|
||||
var/datum/node/BlockDefinition/FunctionBlock/block
|
||||
|
||||
/*
|
||||
Class: VariableAssignment
|
||||
@@ -38,10 +38,10 @@
|
||||
- <VariableDeclaration>
|
||||
*/
|
||||
//
|
||||
/node/statement/VariableAssignment
|
||||
var/node/identifier/object
|
||||
var/node/identifier/var_name
|
||||
var/node/expression/value
|
||||
/datum/node/statement/VariableAssignment
|
||||
var/datum/node/identifier/object
|
||||
var/datum/node/identifier/var_name
|
||||
var/datum/node/expression/value
|
||||
|
||||
/*
|
||||
Class: VariableDeclaration
|
||||
@@ -51,56 +51,56 @@
|
||||
- <VariableAssignment>
|
||||
*/
|
||||
//
|
||||
/node/statement/VariableDeclaration
|
||||
var/node/identifier/object
|
||||
var/node/identifier/var_name
|
||||
/datum/node/statement/VariableDeclaration
|
||||
var/datum/node/identifier/object
|
||||
var/datum/node/identifier/var_name
|
||||
|
||||
/*
|
||||
Class: IfStatement
|
||||
*/
|
||||
//
|
||||
/node/statement/IfStatement
|
||||
var/node/BlockDefinition/block
|
||||
var/node/BlockDefinition/else_block // may be null
|
||||
var/node/expression/cond
|
||||
/datum/node/statement/IfStatement
|
||||
var/datum/node/BlockDefinition/block
|
||||
var/datum/node/BlockDefinition/else_block // may be null
|
||||
var/datum/node/expression/cond
|
||||
|
||||
/*
|
||||
Class: WhileLoop
|
||||
Loops while a given condition is true.
|
||||
*/
|
||||
//
|
||||
/node/statement/WhileLoop
|
||||
var/node/BlockDefinition/block
|
||||
var/node/expression/cond
|
||||
/datum/node/statement/WhileLoop
|
||||
var/datum/node/BlockDefinition/block
|
||||
var/datum/node/expression/cond
|
||||
|
||||
/*
|
||||
Class: ForLoop
|
||||
Loops while test is true, initializing a variable, increasing the variable
|
||||
*/
|
||||
/node/statement/ForLoop
|
||||
var/node/BlockDefinition/block
|
||||
var/node/expression/test
|
||||
var/node/expression/init
|
||||
var/node/expression/increment
|
||||
/datum/node/statement/ForLoop
|
||||
var/datum/node/BlockDefinition/block
|
||||
var/datum/node/expression/test
|
||||
var/datum/node/expression/init
|
||||
var/datum/node/expression/increment
|
||||
|
||||
/*
|
||||
Class: BreakStatement
|
||||
Ends a loop.
|
||||
*/
|
||||
//
|
||||
/node/statement/BreakStatement
|
||||
/datum/node/statement/BreakStatement
|
||||
|
||||
/*
|
||||
Class: ContinueStatement
|
||||
Skips to the next iteration of a loop.
|
||||
*/
|
||||
//
|
||||
/node/statement/ContinueStatement
|
||||
/datum/node/statement/ContinueStatement
|
||||
|
||||
/*
|
||||
Class: ReturnStatement
|
||||
Ends the function and returns a value.
|
||||
*/
|
||||
//
|
||||
/node/statement/ReturnStatement
|
||||
var/node/expression/value
|
||||
/datum/node/statement/ReturnStatement
|
||||
var/datum/node/expression/value
|
||||
|
||||
@@ -5,118 +5,118 @@
|
||||
Class: scriptError
|
||||
An error scanning or parsing the source code.
|
||||
*/
|
||||
/scriptError
|
||||
/datum/scriptError
|
||||
var/message /// A message describing the problem.
|
||||
/scriptError/New(msg=null)
|
||||
/datum/scriptError/New(msg=null)
|
||||
if(msg)message=msg
|
||||
|
||||
/scriptError/BadToken
|
||||
/datum/scriptError/BadToken
|
||||
message="Unexpected token: "
|
||||
var/token/token
|
||||
/scriptError/BadToken/New(token/t)
|
||||
var/datum/token/token
|
||||
/datum/scriptError/BadToken/New(datum/token/t)
|
||||
token=t
|
||||
if(t&&t.line) message="[t.line]: [message]"
|
||||
if(istype(t))message+="[t.value]"
|
||||
else message+="[t]"
|
||||
|
||||
/scriptError/InvalidID
|
||||
parent_type=/scriptError/BadToken
|
||||
/datum/scriptError/InvalidID
|
||||
parent_type=/datum/scriptError/BadToken
|
||||
message="Invalid identifier name: "
|
||||
|
||||
/scriptError/ReservedWord
|
||||
parent_type=/scriptError/BadToken
|
||||
/datum/scriptError/ReservedWord
|
||||
parent_type=/datum/scriptError/BadToken
|
||||
message="Identifer using reserved word: "
|
||||
|
||||
/scriptError/BadNumber
|
||||
parent_type=/scriptError/BadToken
|
||||
/datum/scriptError/BadNumber
|
||||
parent_type=/datum/scriptError/BadToken
|
||||
message = "Bad number: "
|
||||
|
||||
/scriptError/BadReturn
|
||||
var/token/token
|
||||
/datum/scriptError/BadReturn
|
||||
var/datum/token/token
|
||||
message = "Unexpected return statement outside of a function."
|
||||
/scriptError/BadReturn/New(token/t)
|
||||
/datum/scriptError/BadReturn/New(datum/token/t)
|
||||
src.token=t
|
||||
|
||||
/scriptError/EndOfFile
|
||||
/datum/scriptError/EndOfFile
|
||||
message = "Unexpected end of file."
|
||||
|
||||
/scriptError/ExpectedToken
|
||||
/datum/scriptError/ExpectedToken
|
||||
message="Expected: '"
|
||||
/scriptError/ExpectedToken/New(id, token/T)
|
||||
/datum/scriptError/ExpectedToken/New(id, datum/token/T)
|
||||
if(T && T.line) message="[T.line]: [message]"
|
||||
message+="[id]'. "
|
||||
if(T)message+="Found '[T.value]'."
|
||||
|
||||
|
||||
/scriptError/UnterminatedComment
|
||||
/datum/scriptError/UnterminatedComment
|
||||
message="Unterminated multi-line comment statement: expected */"
|
||||
|
||||
/scriptError/DuplicateFunction
|
||||
/datum/scriptError/DuplicateFunction
|
||||
message="Function defined twice."
|
||||
/scriptError/DuplicateFunction/New(name, token/t)
|
||||
/datum/scriptError/DuplicateFunction/New(name, datum/token/t)
|
||||
message="Function '[name]' defined twice."
|
||||
|
||||
/*
|
||||
Class: runtimeError
|
||||
An error thrown by the interpreter in running the script.
|
||||
*/
|
||||
/runtimeError
|
||||
/datum/runtimeError
|
||||
var/name
|
||||
var/message /// A basic description as to what went wrong.
|
||||
var/stack/stack
|
||||
var/datum/stack/stack
|
||||
|
||||
/**
|
||||
* Proc: ToString
|
||||
* Returns a description of the error suitable for showing to the user.
|
||||
*/
|
||||
/runtimeError/proc/ToString()
|
||||
/datum/runtimeError/proc/ToString()
|
||||
. = "[name]: [message]"
|
||||
if(!stack.Top()) return
|
||||
.+="\nStack:"
|
||||
while(stack.Top())
|
||||
var/node/statement/FunctionCall/stmt=stack.Pop()
|
||||
var/datum/node/statement/FunctionCall/stmt=stack.Pop()
|
||||
. += "\n\t [stmt.func_name]()"
|
||||
|
||||
/runtimeError/TypeMismatch
|
||||
/datum/runtimeError/TypeMismatch
|
||||
name="TypeMismatchError"
|
||||
/runtimeError/TypeMismatch/New(op, a, b)
|
||||
/datum/runtimeError/TypeMismatch/New(op, a, b)
|
||||
message="Type mismatch: '[a]' [op] '[b]'"
|
||||
|
||||
/runtimeError/UnexpectedReturn
|
||||
/datum/runtimeError/UnexpectedReturn
|
||||
name="UnexpectedReturnError"
|
||||
message="Unexpected return statement."
|
||||
|
||||
/runtimeError/UnknownInstruction
|
||||
/datum/runtimeError/UnknownInstruction
|
||||
name="UnknownInstructionError"
|
||||
message="Unknown instruction type. This may be due to incompatible compiler and interpreter versions or a lack of implementation."
|
||||
|
||||
/runtimeError/UndefinedVariable
|
||||
/datum/runtimeError/UndefinedVariable
|
||||
name="UndefinedVariableError"
|
||||
/runtimeError/UndefinedVariable/New(variable)
|
||||
/datum/runtimeError/UndefinedVariable/New(variable)
|
||||
message="Variable '[variable]' has not been declared."
|
||||
|
||||
/runtimeError/UndefinedFunction
|
||||
/datum/runtimeError/UndefinedFunction
|
||||
name="UndefinedFunctionError"
|
||||
/runtimeError/UndefinedFunction/New(function)
|
||||
/datum/runtimeError/UndefinedFunction/New(function)
|
||||
message="Function '[function]()' has not been defined."
|
||||
|
||||
/runtimeError/DuplicateVariableDeclaration
|
||||
/datum/runtimeError/DuplicateVariableDeclaration
|
||||
name="DuplicateVariableError"
|
||||
/runtimeError/DuplicateVariableDeclaration/New(variable)
|
||||
/datum/runtimeError/DuplicateVariableDeclaration/New(variable)
|
||||
message="Variable '[variable]' was already declared."
|
||||
|
||||
/runtimeError/IterationLimitReached
|
||||
/datum/runtimeError/IterationLimitReached
|
||||
name="MaxIterationError"
|
||||
message="A loop has reached its maximum number of iterations."
|
||||
|
||||
/runtimeError/RecursionLimitReached
|
||||
/datum/runtimeError/RecursionLimitReached
|
||||
name="MaxRecursionError"
|
||||
message="The maximum amount of recursion has been reached."
|
||||
|
||||
/runtimeError/DivisionByZero
|
||||
/datum/runtimeError/DivisionByZero
|
||||
name="DivideByZeroError"
|
||||
message="Division by zero attempted."
|
||||
|
||||
/runtimeError/MaxCPU
|
||||
/datum/runtimeError/MaxCPU
|
||||
name="MaxComputationalUse"
|
||||
message="Maximum amount of computational cycles reached (>= 1000)."
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
if(compileerrors.len)
|
||||
src << output(span_bold("Compile Errors"), "tcserror")
|
||||
for(var/scriptError/e in compileerrors)
|
||||
for(var/datum/scriptError/e in compileerrors)
|
||||
src << output(span_red("\t>[e.message]"), "tcserror")
|
||||
src << output("([compileerrors.len] errors)", "tcserror")
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
if(M.client)
|
||||
M << output(null, "tcserror")
|
||||
M << output(span_bold("Compile Errors"), "tcserror")
|
||||
for(var/scriptError/e in compileerrors)
|
||||
for(var/datum/scriptError/e in compileerrors)
|
||||
M << output(span_red("\t>[e.message]"), "tcserror")
|
||||
M << output("([compileerrors.len] errors)", "tcserror")
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
if(compileerrors.len)
|
||||
src << output(span_bold("Compile Errors"), "tcserror")
|
||||
for(var/scriptError/e in compileerrors)
|
||||
for(var/datum/scriptError/e in compileerrors)
|
||||
src << output(span_red("\t>[e.message]"), "tcserror")
|
||||
src << output("([compileerrors.len] errors)", "tcserror")
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
if(M.client)
|
||||
M << output(null, "tcserror")
|
||||
M << output(span_bold("Compile Errors"), "tcserror")
|
||||
for(var/scriptError/e in compileerrors)
|
||||
for(var/datum/scriptError/e in compileerrors)
|
||||
M << output(span_red("\t>[e.message]"), "tcserror")
|
||||
M << output("([compileerrors.len] errors)", "tcserror")
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
/* --- Traffic Control Scripting Language --- */
|
||||
// NanoTrasen TCS Language - Made by Doohl
|
||||
|
||||
/n_Interpreter/TCS_Interpreter
|
||||
/datum/n_Interpreter/TCS_Interpreter
|
||||
var/datum/TCS_Compiler/Compiler
|
||||
|
||||
/n_Interpreter/TCS_Interpreter/HandleError(runtimeError/e)
|
||||
/datum/n_Interpreter/TCS_Interpreter/HandleError(datum/runtimeError/e)
|
||||
Compiler.Holder.add_entry(e.ToString(), "Execution Error")
|
||||
|
||||
/datum/TCS_Compiler
|
||||
var/n_Interpreter/TCS_Interpreter/interpreter
|
||||
var/datum/n_Interpreter/TCS_Interpreter/interpreter
|
||||
var/obj/machinery/telecomms/server/Holder // the server that is running the code
|
||||
var/ready = 1 // 1 if ready to run code
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
*/
|
||||
|
||||
/datum/TCS_Compiler/proc/Compile(code as message)
|
||||
var/n_scriptOptions/nS_Options/options = new()
|
||||
var/n_Scanner/nS_Scanner/scanner = new(code, options)
|
||||
var/datum/n_scriptOptions/nS_Options/options = new()
|
||||
var/datum/n_Scanner/nS_Scanner/scanner = new(code, options)
|
||||
var/list/tokens = scanner.Scan()
|
||||
var/n_Parser/nS_Parser/parser = new(tokens, options)
|
||||
var/node/BlockDefinition/GlobalBlock/program = parser.Parse()
|
||||
var/datum/n_Parser/nS_Parser/parser = new(tokens, options)
|
||||
var/datum/node/BlockDefinition/GlobalBlock/program = parser.Parse()
|
||||
|
||||
var/list/returnerrors = list()
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
/proc/isobject(x)
|
||||
return !(isnum(x) || istext(x))
|
||||
|
||||
/n_Interpreter/proc/Eval(node/expression/exp)
|
||||
if(istype(exp, /node/expression/FunctionCall))
|
||||
/datum/n_Interpreter/proc/Eval(datum/node/expression/exp)
|
||||
if(istype(exp, /datum/node/expression/FunctionCall))
|
||||
return RunFunction(exp)
|
||||
else if(istype(exp, /node/expression/op))
|
||||
else if(istype(exp, /datum/node/expression/op))
|
||||
return EvalOperator(exp)
|
||||
else if(istype(exp, /node/expression/value/literal))
|
||||
var/node/expression/value/literal/lit=exp
|
||||
else if(istype(exp, /datum/node/expression/value/literal))
|
||||
var/datum/node/expression/value/literal/lit=exp
|
||||
return lit.value
|
||||
else if(istype(exp, /node/expression/value/reference))
|
||||
var/node/expression/value/reference/ref=exp
|
||||
else if(istype(exp, /datum/node/expression/value/reference))
|
||||
var/datum/node/expression/value/reference/ref=exp
|
||||
return ref.value
|
||||
else if(istype(exp, /node/expression/value/variable))
|
||||
var/node/expression/value/variable/v=exp
|
||||
else if(istype(exp, /datum/node/expression/value/variable))
|
||||
var/datum/node/expression/value/variable/v=exp
|
||||
if(!v.object)
|
||||
return Eval(GetVariable(v.id.id_name))
|
||||
else
|
||||
var/datum/D
|
||||
if(istype(v.object, /node/identifier))
|
||||
if(istype(v.object, /datum/node/identifier))
|
||||
D=GetVariable(v.object:id_name)
|
||||
else
|
||||
D=v.object
|
||||
@@ -26,142 +26,142 @@
|
||||
if(!isobject(D))
|
||||
return null
|
||||
if(!D.vars.Find(v.id.id_name))
|
||||
RaiseError(new/runtimeError/UndefinedVariable("[v.object.ToString()].[v.id.id_name]"))
|
||||
RaiseError(new/datum/runtimeError/UndefinedVariable("[v.object.ToString()].[v.id.id_name]"))
|
||||
return null
|
||||
return Eval(D.vars[v.id.id_name])
|
||||
else if(istype(exp, /node/expression))
|
||||
RaiseError(new/runtimeError/UnknownInstruction())
|
||||
else if(istype(exp, /datum/node/expression))
|
||||
RaiseError(new/datum/runtimeError/UnknownInstruction())
|
||||
else
|
||||
return exp
|
||||
|
||||
/n_Interpreter/proc/EvalOperator(node/expression/op/exp)
|
||||
if(istype(exp, /node/expression/op/binary))
|
||||
var/node/expression/op/binary/bin=exp
|
||||
/datum/n_Interpreter/proc/EvalOperator(datum/node/expression/op/exp)
|
||||
if(istype(exp, /datum/node/expression/op/binary))
|
||||
var/datum/node/expression/op/binary/bin=exp
|
||||
switch(bin.type)
|
||||
if(/node/expression/op/binary/Equal)
|
||||
if(/datum/node/expression/op/binary/Equal)
|
||||
return Equal(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/NotEqual)
|
||||
if(/datum/node/expression/op/binary/NotEqual)
|
||||
return NotEqual(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/Greater)
|
||||
if(/datum/node/expression/op/binary/Greater)
|
||||
return Greater(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/Less)
|
||||
if(/datum/node/expression/op/binary/Less)
|
||||
return Less(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/GreaterOrEqual)
|
||||
if(/datum/node/expression/op/binary/GreaterOrEqual)
|
||||
return GreaterOrEqual(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/LessOrEqual)
|
||||
if(/datum/node/expression/op/binary/LessOrEqual)
|
||||
return LessOrEqual(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/LogicalAnd)
|
||||
if(/datum/node/expression/op/binary/LogicalAnd)
|
||||
return LogicalAnd(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/LogicalOr)
|
||||
if(/datum/node/expression/op/binary/LogicalOr)
|
||||
return LogicalOr(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/LogicalXor)
|
||||
if(/datum/node/expression/op/binary/LogicalXor)
|
||||
return LogicalXor(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/BitwiseAnd)
|
||||
if(/datum/node/expression/op/binary/BitwiseAnd)
|
||||
return BitwiseAnd(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/BitwiseOr)
|
||||
if(/datum/node/expression/op/binary/BitwiseOr)
|
||||
return BitwiseOr(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/BitwiseXor)
|
||||
if(/datum/node/expression/op/binary/BitwiseXor)
|
||||
return BitwiseXor(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/Add)
|
||||
if(/datum/node/expression/op/binary/Add)
|
||||
return Add(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/Subtract)
|
||||
if(/datum/node/expression/op/binary/Subtract)
|
||||
return Subtract(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/Multiply)
|
||||
if(/datum/node/expression/op/binary/Multiply)
|
||||
return Multiply(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/Divide)
|
||||
if(/datum/node/expression/op/binary/Divide)
|
||||
return Divide(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/Power)
|
||||
if(/datum/node/expression/op/binary/Power)
|
||||
return Power(Eval(bin.exp), Eval(bin.exp2))
|
||||
if(/node/expression/op/binary/Modulo)
|
||||
if(/datum/node/expression/op/binary/Modulo)
|
||||
return Modulo(Eval(bin.exp), Eval(bin.exp2))
|
||||
else
|
||||
RaiseError(new/runtimeError/UnknownInstruction())
|
||||
RaiseError(new/datum/runtimeError/UnknownInstruction())
|
||||
return
|
||||
switch(exp.type)
|
||||
if(/node/expression/op/unary/Minus)
|
||||
if(/datum/node/expression/op/unary/Minus)
|
||||
return Minus(Eval(exp.exp))
|
||||
if(/node/expression/op/unary/LogicalNot)
|
||||
if(/datum/node/expression/op/unary/LogicalNot)
|
||||
return LogicalNot(Eval(exp.exp))
|
||||
if(/node/expression/op/unary/BitwiseNot)
|
||||
if(/datum/node/expression/op/unary/BitwiseNot)
|
||||
return BitwiseNot(Eval(exp.exp))
|
||||
if(/node/expression/op/unary/group)
|
||||
if(/datum/node/expression/op/unary/group)
|
||||
return Eval(exp.exp)
|
||||
else
|
||||
RaiseError(new/runtimeError/UnknownInstruction())
|
||||
RaiseError(new/datum/runtimeError/UnknownInstruction())
|
||||
|
||||
|
||||
//Binary//
|
||||
//Comparison operators
|
||||
/n_Interpreter/proc/Equal(a, b) return a==b
|
||||
/n_Interpreter/proc/NotEqual(a, b) return a!=b //LogicalNot(Equal(a, b))
|
||||
/n_Interpreter/proc/Greater(a, b) return a>b
|
||||
/n_Interpreter/proc/Less(a, b) return a<b
|
||||
/n_Interpreter/proc/GreaterOrEqual(a, b) return a>=b
|
||||
/n_Interpreter/proc/LessOrEqual(a, b) return a<=b
|
||||
/datum/n_Interpreter/proc/Equal(a, b) return a==b
|
||||
/datum/n_Interpreter/proc/NotEqual(a, b) return a!=b //LogicalNot(Equal(a, b))
|
||||
/datum/n_Interpreter/proc/Greater(a, b) return a>b
|
||||
/datum/n_Interpreter/proc/Less(a, b) return a<b
|
||||
/datum/n_Interpreter/proc/GreaterOrEqual(a, b) return a>=b
|
||||
/datum/n_Interpreter/proc/LessOrEqual(a, b) return a<=b
|
||||
//Logical Operators
|
||||
/n_Interpreter/proc/LogicalAnd(a, b) return a&&b
|
||||
/n_Interpreter/proc/LogicalOr(a, b) return a||b
|
||||
/n_Interpreter/proc/LogicalXor(a, b) return (a||b) && !(a&&b)
|
||||
/datum/n_Interpreter/proc/LogicalAnd(a, b) return a&&b
|
||||
/datum/n_Interpreter/proc/LogicalOr(a, b) return a||b
|
||||
/datum/n_Interpreter/proc/LogicalXor(a, b) return (a||b) && !(a&&b)
|
||||
//Bitwise Operators
|
||||
/n_Interpreter/proc/BitwiseAnd(a, b) return a&b
|
||||
/n_Interpreter/proc/BitwiseOr(a, b) return a|b
|
||||
/n_Interpreter/proc/BitwiseXor(a, b) return a^b
|
||||
/datum/n_Interpreter/proc/BitwiseAnd(a, b) return a&b
|
||||
/datum/n_Interpreter/proc/BitwiseOr(a, b) return a|b
|
||||
/datum/n_Interpreter/proc/BitwiseXor(a, b) return a^b
|
||||
//Arithmetic Operators
|
||||
/n_Interpreter/proc/Add(a, b)
|
||||
/datum/n_Interpreter/proc/Add(a, b)
|
||||
if(istext(a)&&!istext(b)) b="[b]"
|
||||
else if(istext(b)&&!istext(a)) a="[a]"
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("+", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("+", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("+", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("+", a, b))
|
||||
return null
|
||||
return a+b
|
||||
/n_Interpreter/proc/Subtract(a, b)
|
||||
/datum/n_Interpreter/proc/Subtract(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("-", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("-", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("-", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("-", a, b))
|
||||
return null
|
||||
return a-b
|
||||
/n_Interpreter/proc/Divide(a, b)
|
||||
/datum/n_Interpreter/proc/Divide(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("/", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("/", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("/", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("/", a, b))
|
||||
return null
|
||||
if(b==0)
|
||||
RaiseError(new/runtimeError/DivisionByZero())
|
||||
RaiseError(new/datum/runtimeError/DivisionByZero())
|
||||
return null
|
||||
return a/b
|
||||
/n_Interpreter/proc/Multiply(a, b)
|
||||
/datum/n_Interpreter/proc/Multiply(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("*", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("*", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("*", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("*", a, b))
|
||||
return null
|
||||
return a*b
|
||||
/n_Interpreter/proc/Modulo(a, b)
|
||||
/datum/n_Interpreter/proc/Modulo(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("%", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("%", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("%", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("%", a, b))
|
||||
return null
|
||||
return a%b
|
||||
/n_Interpreter/proc/Power(a, b)
|
||||
/datum/n_Interpreter/proc/Power(a, b)
|
||||
if(isobject(a) && !isobject(b))
|
||||
RaiseError(new/runtimeError/TypeMismatch("**", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("**", a, b))
|
||||
return null
|
||||
else if(isobject(b) && !isobject(a))
|
||||
RaiseError(new/runtimeError/TypeMismatch("**", a, b))
|
||||
RaiseError(new/datum/runtimeError/TypeMismatch("**", a, b))
|
||||
return null
|
||||
return a**b
|
||||
|
||||
//Unary//
|
||||
/n_Interpreter/proc/Minus(a) return -a
|
||||
/n_Interpreter/proc/LogicalNot(a) return !a
|
||||
/n_Interpreter/proc/BitwiseNot(a) return ~a
|
||||
/datum/n_Interpreter/proc/Minus(a) return -a
|
||||
/datum/n_Interpreter/proc/LogicalNot(a) return !a
|
||||
/datum/n_Interpreter/proc/BitwiseNot(a) return ~a
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
Class: n_Interpreter
|
||||
Procedures allowing for interaction with the script that is being run by the interpreter object.
|
||||
*/
|
||||
/n_Interpreter
|
||||
/datum/n_Interpreter
|
||||
|
||||
/*
|
||||
Proc: Load
|
||||
@@ -15,7 +15,7 @@
|
||||
Parameters:
|
||||
program - A <GlobalBlock> object which represents the script's global scope.
|
||||
*/
|
||||
/n_Interpreter/proc/Load(node/BlockDefinition/GlobalBlock/program)
|
||||
/datum/n_Interpreter/proc/Load(datum/node/BlockDefinition/GlobalBlock/program)
|
||||
ASSERT(program)
|
||||
src.program = program
|
||||
CreateGlobalScope()
|
||||
@@ -24,7 +24,7 @@
|
||||
Proc: Run
|
||||
Runs the script.
|
||||
*/
|
||||
/n_Interpreter/proc/Run()
|
||||
/datum/n_Interpreter/proc/Run()
|
||||
cur_recursion = 0 // reset recursion
|
||||
cur_statements = 0 // reset CPU tracking
|
||||
alertadmins = 0
|
||||
@@ -43,7 +43,7 @@
|
||||
See Also:
|
||||
- <Block.SetVar()>
|
||||
*/
|
||||
/n_Interpreter/proc/SetVar(name, value)
|
||||
/datum/n_Interpreter/proc/SetVar(name, value)
|
||||
if(!istext(name))
|
||||
//CRASH("Invalid variable name")
|
||||
return
|
||||
@@ -59,24 +59,24 @@
|
||||
object - (Optional) An object which will the be target of a function call.
|
||||
params - Only required if object is not null, a list of the names of parameters the proc takes.
|
||||
*/
|
||||
/n_Interpreter/proc/SetProc(name, path, object=null, list/params=null)
|
||||
/datum/n_Interpreter/proc/SetProc(name, path, object=null, list/params=null)
|
||||
if(!istext(name))
|
||||
//CRASH("Invalid function name")
|
||||
return
|
||||
if(!object)
|
||||
globalScope.functions[name] = path
|
||||
return
|
||||
var/node/statement/FunctionDefinition/S = new()
|
||||
var/datum/node/statement/FunctionDefinition/S = new()
|
||||
S.func_name = name
|
||||
S.parameters = params
|
||||
S.block = new()
|
||||
S.block.SetVar("src", object)
|
||||
var/node/expression/FunctionCall/C = new()
|
||||
var/datum/node/expression/FunctionCall/C = new()
|
||||
C.func_name = path
|
||||
C.object = new("src")
|
||||
for(var/p in params)
|
||||
C.parameters += new/node/expression/value/variable(p)
|
||||
var/node/statement/ReturnStatement/R=new()
|
||||
C.parameters += new/datum/node/expression/value/variable(p)
|
||||
var/datum/node/statement/ReturnStatement/R=new()
|
||||
R.value=C
|
||||
S.block.statements += R
|
||||
globalScope.functions[name] = S
|
||||
@@ -84,14 +84,14 @@
|
||||
Proc: VarExists
|
||||
Checks whether a global variable with the specified name exists.
|
||||
*/
|
||||
/n_Interpreter/proc/VarExists(name)
|
||||
/datum/n_Interpreter/proc/VarExists(name)
|
||||
return globalScope.variables.Find(name) //convert to 1/0 first?
|
||||
|
||||
/*
|
||||
Proc: ProcExists
|
||||
Checks whether a global function with the specified name exists.
|
||||
*/
|
||||
/n_Interpreter/proc/ProcExists(name)
|
||||
/datum/n_Interpreter/proc/ProcExists(name)
|
||||
return globalScope.functions.Find(name)
|
||||
|
||||
/*
|
||||
@@ -101,7 +101,7 @@
|
||||
See Also:
|
||||
- <VarExists()>
|
||||
*/
|
||||
/n_Interpreter/proc/GetVar(name)
|
||||
/datum/n_Interpreter/proc/GetVar(name)
|
||||
if(!VarExists(name))
|
||||
//CRASH("No variable named '[name]'.")
|
||||
return
|
||||
@@ -116,13 +116,13 @@
|
||||
See Also:
|
||||
- <ProcExists()>
|
||||
*/
|
||||
/n_Interpreter/proc/CallProc(name, params[]=null)
|
||||
/datum/n_Interpreter/proc/CallProc(name, params[]=null)
|
||||
if(!ProcExists(name))
|
||||
//CRASH("No function named '[name]'.")
|
||||
return
|
||||
var/node/statement/FunctionDefinition/func = globalScope.functions[name]
|
||||
var/datum/node/statement/FunctionDefinition/func = globalScope.functions[name]
|
||||
if(istype(func))
|
||||
var/node/statement/FunctionCall/stmt = new
|
||||
var/datum/node/statement/FunctionCall/stmt = new
|
||||
stmt.func_name = func.func_name
|
||||
stmt.parameters = params
|
||||
return RunFunction(stmt)
|
||||
@@ -137,4 +137,4 @@
|
||||
See Also:
|
||||
- <runtimeError>
|
||||
*/
|
||||
/n_Interpreter/proc/HandleError(runtimeError/e)
|
||||
/datum/n_Interpreter/proc/HandleError(datum/runtimeError/e)
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
#define RETURNING 1
|
||||
#define BREAKING 2
|
||||
#define CONTINUING 4
|
||||
/n_Interpreter
|
||||
var/scope/curScope
|
||||
var/scope/globalScope
|
||||
var/node/BlockDefinition/program
|
||||
var/node/statement/FunctionDefinition/curFunction
|
||||
var/stack/scopes = new()
|
||||
var/stack/functions = new()
|
||||
/datum/n_Interpreter
|
||||
var/datum/scope/curScope
|
||||
var/datum/scope/globalScope
|
||||
var/datum/node/BlockDefinition/program
|
||||
var/datum/node/statement/FunctionDefinition/curFunction
|
||||
var/datum/stack/scopes = new()
|
||||
var/datum/stack/functions = new()
|
||||
|
||||
var/datum/container // associated container for interpeter
|
||||
/*
|
||||
@@ -46,7 +46,7 @@
|
||||
Constructor: New
|
||||
Calls <Load()> with the given parameters.
|
||||
*/
|
||||
/n_Interpreter/New(node/BlockDefinition/GlobalBlock/program=null)
|
||||
/datum/n_Interpreter/New(datum/node/BlockDefinition/GlobalBlock/program=null)
|
||||
.=..()
|
||||
if(program)Load(program)
|
||||
|
||||
@@ -54,20 +54,20 @@
|
||||
Proc: RaiseError
|
||||
Raises a runtime error.
|
||||
*/
|
||||
/n_Interpreter/proc/RaiseError(runtimeError/e)
|
||||
/datum/n_Interpreter/proc/RaiseError(datum/runtimeError/e)
|
||||
e.stack=functions.Copy()
|
||||
e.stack.Push(curFunction)
|
||||
src.HandleError(e)
|
||||
|
||||
/n_Interpreter/proc/CreateScope(node/BlockDefinition/B)
|
||||
var/scope/S = new(B, curScope)
|
||||
/datum/n_Interpreter/proc/CreateScope(datum/node/BlockDefinition/B)
|
||||
var/datum/scope/S = new(B, curScope)
|
||||
scopes.Push(curScope)
|
||||
curScope = S
|
||||
return S
|
||||
|
||||
/n_Interpreter/proc/CreateGlobalScope()
|
||||
/datum/n_Interpreter/proc/CreateGlobalScope()
|
||||
scopes.Clear()
|
||||
var/scope/S = new(program, null)
|
||||
var/datum/scope/S = new(program, null)
|
||||
globalScope = S
|
||||
return S
|
||||
|
||||
@@ -75,8 +75,8 @@
|
||||
Proc: RunBlock
|
||||
Runs each statement in a block of code.
|
||||
*/
|
||||
/n_Interpreter/proc/RunBlock(node/BlockDefinition/Block, scope/scope = null)
|
||||
var/is_global = istype(Block, /node/BlockDefinition/GlobalBlock)
|
||||
/datum/n_Interpreter/proc/RunBlock(datum/node/BlockDefinition/Block, datum/scope/scope = null)
|
||||
var/is_global = istype(Block, /datum/node/BlockDefinition/GlobalBlock)
|
||||
if(!is_global)
|
||||
if(scope)
|
||||
curScope = scope
|
||||
@@ -89,12 +89,12 @@ Runs each statement in a block of code.
|
||||
|
||||
if(cur_statements < max_statements)
|
||||
|
||||
for(var/node/statement/S in Block.statements)
|
||||
for(var/datum/node/statement/S in Block.statements)
|
||||
while(paused) sleep(10)
|
||||
|
||||
cur_statements++
|
||||
if(cur_statements >= max_statements)
|
||||
RaiseError(new/runtimeError/MaxCPU())
|
||||
RaiseError(new/datum/runtimeError/MaxCPU())
|
||||
|
||||
if(container && !alertadmins)
|
||||
if(istype(container, /datum/TCS_Compiler))
|
||||
@@ -106,8 +106,8 @@ Runs each statement in a block of code.
|
||||
message_admins(message, 1)
|
||||
break
|
||||
|
||||
if(istype(S, /node/statement/VariableAssignment))
|
||||
var/node/statement/VariableAssignment/stmt = S
|
||||
if(istype(S, /datum/node/statement/VariableAssignment))
|
||||
var/datum/node/statement/VariableAssignment/stmt = S
|
||||
var/name = stmt.var_name.id_name
|
||||
if(!stmt.object)
|
||||
// Below we assign the variable first to null if it doesn't already exist.
|
||||
@@ -120,38 +120,38 @@ Runs each statement in a block of code.
|
||||
var/datum/D = Eval(GetVariable(stmt.object.id_name))
|
||||
if(!D) return
|
||||
D.vars[stmt.var_name.id_name] = Eval(stmt.value)
|
||||
else if(istype(S, /node/statement/VariableDeclaration))
|
||||
else if(istype(S, /datum/node/statement/VariableDeclaration))
|
||||
//VariableDeclaration nodes are used to forcibly declare a local variable so that one in a higher scope isn't used by default.
|
||||
var/node/statement/VariableDeclaration/dec=S
|
||||
var/datum/node/statement/VariableDeclaration/dec=S
|
||||
if(!dec.object)
|
||||
AssignVariable(dec.var_name.id_name, null, curScope)
|
||||
else
|
||||
var/datum/D = Eval(GetVariable(dec.object.id_name))
|
||||
if(!D) return
|
||||
D.vars[dec.var_name.id_name] = null
|
||||
else if(istype(S, /node/statement/FunctionCall))
|
||||
else if(istype(S, /datum/node/statement/FunctionCall))
|
||||
RunFunction(S)
|
||||
else if(istype(S, /node/statement/FunctionDefinition))
|
||||
else if(istype(S, /datum/node/statement/FunctionDefinition))
|
||||
pass() //do nothing
|
||||
else if(istype(S, /node/statement/WhileLoop))
|
||||
else if(istype(S, /datum/node/statement/WhileLoop))
|
||||
RunWhile(S)
|
||||
else if(istype(S, /node/statement/IfStatement))
|
||||
else if(istype(S, /datum/node/statement/IfStatement))
|
||||
RunIf(S)
|
||||
else if(istype(S, /node/statement/ReturnStatement))
|
||||
else if(istype(S, /datum/node/statement/ReturnStatement))
|
||||
if(!curFunction)
|
||||
RaiseError(new/runtimeError/UnexpectedReturn())
|
||||
RaiseError(new/datum/runtimeError/UnexpectedReturn())
|
||||
continue
|
||||
status |= RETURNING
|
||||
returnVal=Eval(S:value)
|
||||
break
|
||||
else if(istype(S, /node/statement/BreakStatement))
|
||||
else if(istype(S, /datum/node/statement/BreakStatement))
|
||||
status |= BREAKING
|
||||
break
|
||||
else if(istype(S, /node/statement/ContinueStatement))
|
||||
else if(istype(S, /datum/node/statement/ContinueStatement))
|
||||
status |= CONTINUING
|
||||
break
|
||||
else
|
||||
RaiseError(new/runtimeError/UnknownInstruction())
|
||||
RaiseError(new/datum/runtimeError/UnknownInstruction())
|
||||
if(status)
|
||||
break
|
||||
|
||||
@@ -161,15 +161,15 @@ Runs each statement in a block of code.
|
||||
Proc: RunFunction
|
||||
Runs a function block or a proc with the arguments specified in the script.
|
||||
*/
|
||||
/n_Interpreter/proc/RunFunction(node/statement/FunctionCall/stmt)
|
||||
/datum/n_Interpreter/proc/RunFunction(datum/node/statement/FunctionCall/stmt)
|
||||
//Note that anywhere /node/statement/FunctionCall/stmt is used so may /node/expression/FunctionCall
|
||||
|
||||
// If recursion gets too high (max 50 nested functions) throw an error
|
||||
if(cur_recursion >= max_recursion)
|
||||
RaiseError(new/runtimeError/RecursionLimitReached())
|
||||
RaiseError(new/datum/runtimeError/RecursionLimitReached())
|
||||
return 0
|
||||
|
||||
var/node/statement/FunctionDefinition/def
|
||||
var/datum/node/statement/FunctionDefinition/def
|
||||
if(!stmt.object) //A scope's function is being called, stmt.object is null
|
||||
def = GetFunction(stmt.func_name)
|
||||
else if(istype(stmt.object)) //A method of an object exposed as a variable is being called, stmt.object is a /node/identifier
|
||||
@@ -182,14 +182,14 @@ Runs a function block or a proc with the arguments specified in the script.
|
||||
cur_recursion++ // add recursion
|
||||
if(istype(def))
|
||||
if(curFunction) functions.Push(curFunction)
|
||||
var/scope/S = CreateScope(def.block)
|
||||
var/datum/scope/S = CreateScope(def.block)
|
||||
for(var/i=1 to def.parameters.len)
|
||||
var/val
|
||||
if(stmt.parameters.len>=i)
|
||||
val = stmt.parameters[i]
|
||||
//else
|
||||
// unspecified param
|
||||
AssignVariable(def.parameters[i], new/node/expression/value/literal(Eval(val)), S)
|
||||
AssignVariable(def.parameters[i], new/datum/node/expression/value/literal(Eval(val)), S)
|
||||
curFunction=stmt
|
||||
RunBlock(def.block, S)
|
||||
//Handle return value
|
||||
@@ -201,11 +201,11 @@ Runs a function block or a proc with the arguments specified in the script.
|
||||
else
|
||||
cur_recursion--
|
||||
var/list/params=new
|
||||
for(var/node/expression/P in stmt.parameters)
|
||||
for(var/datum/node/expression/P in stmt.parameters)
|
||||
params+=list(Eval(P))
|
||||
if(isobject(def)) //def is an object which is the target of a function call
|
||||
if( !hascall(def, stmt.func_name) )
|
||||
RaiseError(new/runtimeError/UndefinedFunction("[stmt.object.id_name].[stmt.func_name]"))
|
||||
RaiseError(new/datum/runtimeError/UndefinedFunction("[stmt.object.id_name].[stmt.func_name]"))
|
||||
return
|
||||
return call(def, stmt.func_name)(arglist(params))
|
||||
else //def is a path to a global proc
|
||||
@@ -217,7 +217,7 @@ Runs a function block or a proc with the arguments specified in the script.
|
||||
Proc: RunIf
|
||||
Checks a condition and runs either the if block or else block.
|
||||
*/
|
||||
/n_Interpreter/proc/RunIf(node/statement/IfStatement/stmt)
|
||||
/datum/n_Interpreter/proc/RunIf(datum/node/statement/IfStatement/stmt)
|
||||
if(Eval(stmt.cond))
|
||||
RunBlock(stmt.block)
|
||||
else if(stmt.else_block)
|
||||
@@ -227,7 +227,7 @@ Checks a condition and runs either the if block or else block.
|
||||
Proc: RunWhile
|
||||
Runs a while loop.
|
||||
*/
|
||||
/n_Interpreter/proc/RunWhile(node/statement/WhileLoop/stmt)
|
||||
/datum/n_Interpreter/proc/RunWhile(datum/node/statement/WhileLoop/stmt)
|
||||
var/i=1
|
||||
while(Eval(stmt.cond) && Iterate(stmt.block, i++))
|
||||
continue
|
||||
@@ -237,10 +237,10 @@ Runs a while loop.
|
||||
Proc:Iterate
|
||||
Runs a single iteration of a loop. Returns a value indicating whether or not to continue looping.
|
||||
*/
|
||||
/n_Interpreter/proc/Iterate(node/BlockDefinition/block, count)
|
||||
/datum/n_Interpreter/proc/Iterate(datum/node/BlockDefinition/block, count)
|
||||
RunBlock(block)
|
||||
if(max_iterations > 0 && count >= max_iterations)
|
||||
RaiseError(new/runtimeError/IterationLimitReached())
|
||||
RaiseError(new/datum/runtimeError/IterationLimitReached())
|
||||
return 0
|
||||
if(status & (BREAKING|RETURNING))
|
||||
return 0
|
||||
@@ -251,36 +251,36 @@ Runs a single iteration of a loop. Returns a value indicating whether or not to
|
||||
Proc: GetFunction
|
||||
Finds a function in an accessible scope with the given name. Returns a <FunctionDefinition>.
|
||||
*/
|
||||
/n_Interpreter/proc/GetFunction(name)
|
||||
var/scope/S = curScope
|
||||
/datum/n_Interpreter/proc/GetFunction(name)
|
||||
var/datum/scope/S = curScope
|
||||
while(S)
|
||||
if(S.functions.Find(name))
|
||||
return S.functions[name]
|
||||
S = S.parent
|
||||
RaiseError(new/runtimeError/UndefinedFunction(name))
|
||||
RaiseError(new/datum/runtimeError/UndefinedFunction(name))
|
||||
|
||||
/*
|
||||
Proc: GetVariable
|
||||
Finds a variable in an accessible scope and returns its value.
|
||||
*/
|
||||
/n_Interpreter/proc/GetVariable(name)
|
||||
var/scope/S = curScope
|
||||
/datum/n_Interpreter/proc/GetVariable(name)
|
||||
var/datum/scope/S = curScope
|
||||
while(S)
|
||||
if(S.variables.Find(name))
|
||||
return S.variables[name]
|
||||
S = S.parent
|
||||
RaiseError(new/runtimeError/UndefinedVariable(name))
|
||||
RaiseError(new/datum/runtimeError/UndefinedVariable(name))
|
||||
|
||||
/n_Interpreter/proc/GetVariableScope(name) //needed for when you reassign a variable in a higher scope
|
||||
var/scope/S = curScope
|
||||
/datum/n_Interpreter/proc/GetVariableScope(name) //needed for when you reassign a variable in a higher scope
|
||||
var/datum/scope/S = curScope
|
||||
while(S)
|
||||
if(S.variables.Find(name))
|
||||
return S
|
||||
S = S.parent
|
||||
|
||||
|
||||
/n_Interpreter/proc/IsVariableAccessible(name)
|
||||
var/scope/S = curScope
|
||||
/datum/n_Interpreter/proc/IsVariableAccessible(name)
|
||||
var/datum/scope/S = curScope
|
||||
while(S)
|
||||
if(S.variables.Find(name))
|
||||
return TRUE
|
||||
@@ -297,13 +297,13 @@ name - The name of the variable to assign.
|
||||
value - The value to assign to it.
|
||||
S - The scope the variable resides in. If it is null, a scope with the variable already existing is found. If no scopes have a variable of the given name, the current scope is used.
|
||||
*/
|
||||
/n_Interpreter/proc/AssignVariable(name, node/expression/value, scope/S=null)
|
||||
/datum/n_Interpreter/proc/AssignVariable(name, datum/node/expression/value, datum/scope/S=null)
|
||||
if(!S) S = GetVariableScope(name)
|
||||
if(!S) S = curScope
|
||||
if(!S) S = globalScope
|
||||
ASSERT(istype(S))
|
||||
if(istext(value) || isnum(value) || isnull(value)) value = new/node/expression/value/literal(value)
|
||||
else if(!istype(value) && isobject(value)) value = new/node/expression/value/reference(value)
|
||||
if(istext(value) || isnum(value) || isnull(value)) value = new/datum/node/expression/value/literal(value)
|
||||
else if(!istype(value) && isobject(value)) value = new/datum/node/expression/value/reference(value)
|
||||
//TODO: check for invalid name
|
||||
S.variables["[name]"] = value
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
Class: scope
|
||||
A runtime instance of a block. Used internally by the interpreter.
|
||||
*/
|
||||
/scope/
|
||||
var/scope/parent = null
|
||||
var/node/BlockDefinition/block
|
||||
/datum/scope
|
||||
var/datum/scope/parent = null
|
||||
var/datum/node/BlockDefinition/block
|
||||
var/list/functions
|
||||
var/list/variables
|
||||
|
||||
/scope/New(node/BlockDefinition/B, scope/parent)
|
||||
/datum/scope/New(datum/node/BlockDefinition/B, datum/scope/parent)
|
||||
src.block = B
|
||||
src.parent = parent
|
||||
src.variables = B.initial_variables.Copy()
|
||||
|
||||
@@ -14,19 +14,19 @@ File: Options
|
||||
/*
|
||||
Class: n_scriptOptions
|
||||
*/
|
||||
/n_scriptOptions/proc/CanStartID(char) //returns true if the character can start a variable, function, or keyword name (by default letters or an underscore)
|
||||
/datum/n_scriptOptions/proc/CanStartID(char) //returns true if the character can start a variable, function, or keyword name (by default letters or an underscore)
|
||||
if(!isnum(char))char=text2ascii(char)
|
||||
return (char in ASCII_A to ASCII_Z) || (char in ASCII_LOWER_A to ASCII_LOWER_Z) || char==ASCII_UNDERSCORE || char==ASCII_DOLLAR
|
||||
|
||||
/n_scriptOptions/proc/IsValidIDChar(char) //returns true if the character can be in the body of a variable, function, or keyword name (by default letters, numbers, and underscore)
|
||||
/datum/n_scriptOptions/proc/IsValidIDChar(char) //returns true if the character can be in the body of a variable, function, or keyword name (by default letters, numbers, and underscore)
|
||||
if(!isnum(char))char=text2ascii(char)
|
||||
return CanStartID(char) || IsDigit(char)
|
||||
|
||||
/n_scriptOptions/proc/IsDigit(char)
|
||||
/datum/n_scriptOptions/proc/IsDigit(char)
|
||||
if(!isnum(char))char=text2ascii(char)
|
||||
return char in ASCII_ZERO to ASCII_NINE
|
||||
|
||||
/n_scriptOptions/proc/IsValidID(id) //returns true if all the characters in the string are okay to be in an identifier name
|
||||
/datum/n_scriptOptions/proc/IsValidID(id) //returns true if all the characters in the string are okay to be in an identifier name
|
||||
if(!CanStartID(id)) //don't need to grab first char in id, since text2ascii does it automatically
|
||||
return 0
|
||||
if(length(id)==1) return 1
|
||||
@@ -39,7 +39,7 @@ File: Options
|
||||
Class: nS_Options
|
||||
An implementation of <n_scriptOptions> for the n_Script language.
|
||||
*/
|
||||
/n_scriptOptions/nS_Options
|
||||
/datum/n_scriptOptions/nS_Options
|
||||
var/list/symbols = list("(", ")", "\[", "]", ";", ",", "{", "}") //scanner - Characters that can be in symbols
|
||||
/*
|
||||
Var: keywords
|
||||
@@ -47,13 +47,13 @@ An associative list used by the parser to parse keywords. Indices are strings wh
|
||||
associated values are <nS_Keyword> types of which the <n_Keyword.Parse()> proc will be called.
|
||||
*/
|
||||
var/list/keywords = list(
|
||||
"if" = /n_Keyword/nS_Keyword/kwIf,
|
||||
"else" = /n_Keyword/nS_Keyword/kwElse,
|
||||
"while" = /n_Keyword/nS_Keyword/kwWhile,
|
||||
"break" = /n_Keyword/nS_Keyword/kwBreak,
|
||||
"continue" = /n_Keyword/nS_Keyword/kwContinue,
|
||||
"return" = /n_Keyword/nS_Keyword/kwReturn,
|
||||
"def" = /n_Keyword/nS_Keyword/kwDef
|
||||
"if" = /datum/n_Keyword/nS_Keyword/kwIf,
|
||||
"else" = /datum/n_Keyword/nS_Keyword/kwElse,
|
||||
"while" = /datum/n_Keyword/nS_Keyword/kwWhile,
|
||||
"break" = /datum/n_Keyword/nS_Keyword/kwBreak,
|
||||
"continue" = /datum/n_Keyword/nS_Keyword/kwContinue,
|
||||
"return" = /datum/n_Keyword/nS_Keyword/kwReturn,
|
||||
"def" = /datum/n_Keyword/nS_Keyword/kwDef
|
||||
)
|
||||
|
||||
var/list/assign_operators = list(
|
||||
@@ -70,31 +70,31 @@ associated values are <nS_Keyword> types of which the <n_Keyword.Parse()> proc w
|
||||
)
|
||||
|
||||
var/list/unary_operators =list(
|
||||
"!" = /node/expression/op/unary/LogicalNot,
|
||||
"~" = /node/expression/op/unary/BitwiseNot,
|
||||
"-" = /node/expression/op/unary/Minus
|
||||
"!" = /datum/node/expression/op/unary/LogicalNot,
|
||||
"~" = /datum/node/expression/op/unary/BitwiseNot,
|
||||
"-" = /datum/node/expression/op/unary/Minus
|
||||
)
|
||||
|
||||
var/list/binary_operators=list(
|
||||
"==" = /node/expression/op/binary/Equal,
|
||||
"!=" = /node/expression/op/binary/NotEqual,
|
||||
">" = /node/expression/op/binary/Greater,
|
||||
"<" = /node/expression/op/binary/Less,
|
||||
">=" = /node/expression/op/binary/GreaterOrEqual,
|
||||
"<=" = /node/expression/op/binary/LessOrEqual,
|
||||
"&&" = /node/expression/op/binary/LogicalAnd,
|
||||
"||" = /node/expression/op/binary/LogicalOr,
|
||||
"&" = /node/expression/op/binary/BitwiseAnd,
|
||||
"|" = /node/expression/op/binary/BitwiseOr,
|
||||
"`" = /node/expression/op/binary/BitwiseXor,
|
||||
"+" = /node/expression/op/binary/Add,
|
||||
"-" = /node/expression/op/binary/Subtract,
|
||||
"*" = /node/expression/op/binary/Multiply,
|
||||
"/" = /node/expression/op/binary/Divide,
|
||||
"^" = /node/expression/op/binary/Power,
|
||||
"%" = /node/expression/op/binary/Modulo)
|
||||
"==" = /datum/node/expression/op/binary/Equal,
|
||||
"!=" = /datum/node/expression/op/binary/NotEqual,
|
||||
">" = /datum/node/expression/op/binary/Greater,
|
||||
"<" = /datum/node/expression/op/binary/Less,
|
||||
">=" = /datum/node/expression/op/binary/GreaterOrEqual,
|
||||
"<=" = /datum/node/expression/op/binary/LessOrEqual,
|
||||
"&&" = /datum/node/expression/op/binary/LogicalAnd,
|
||||
"||" = /datum/node/expression/op/binary/LogicalOr,
|
||||
"&" = /datum/node/expression/op/binary/BitwiseAnd,
|
||||
"|" = /datum/node/expression/op/binary/BitwiseOr,
|
||||
"`" = /datum/node/expression/op/binary/BitwiseXor,
|
||||
"+" = /datum/node/expression/op/binary/Add,
|
||||
"-" = /datum/node/expression/op/binary/Subtract,
|
||||
"*" = /datum/node/expression/op/binary/Multiply,
|
||||
"/" = /datum/node/expression/op/binary/Divide,
|
||||
"^" = /datum/node/expression/op/binary/Power,
|
||||
"%" = /datum/node/expression/op/binary/Modulo)
|
||||
|
||||
/n_scriptOptions/nS_Options/New()
|
||||
/datum/n_scriptOptions/nS_Options/New()
|
||||
.=..()
|
||||
for(var/O in assign_operators+binary_operators+unary_operators)
|
||||
if(!symbols.Find(O)) symbols+=O
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
/*
|
||||
Class: nS_Parser
|
||||
*/
|
||||
/n_Parser/nS_Parser
|
||||
/datum/n_Parser/nS_Parser
|
||||
/*
|
||||
Var: expecting
|
||||
A variable which keeps track of whether an operator or value is expected. It should be either <OPERATOR> or <VALUE>. See <ParseExpression()>
|
||||
@@ -30,7 +30,7 @@
|
||||
Proc: Precedence
|
||||
Compares two operators, decides which is higher in the order of operations, and returns <SHIFT> or <REDUCE>.
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/Precedence(node/expression/op/top, node/expression/op/input)
|
||||
/datum/n_Parser/nS_Parser/proc/Precedence(datum/node/expression/op/top, datum/node/expression/op/input)
|
||||
if(istype(top))
|
||||
top=top.precedence
|
||||
if(istype(input))
|
||||
@@ -43,35 +43,35 @@
|
||||
Proc: GetExpression
|
||||
Takes a token expected to represent a value and returns an <expression> node.
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/GetExpression(token/T)
|
||||
/datum/n_Parser/nS_Parser/proc/GetExpression(datum/token/T)
|
||||
if(!T) return
|
||||
if(istype(T, /node/expression))
|
||||
if(istype(T, /datum/node/expression))
|
||||
return T
|
||||
switch(T.type)
|
||||
if(/token/word)
|
||||
return new/node/expression/value/variable(T.value)
|
||||
if(/token/accessor)
|
||||
var/token/accessor/A=T
|
||||
var/node/expression/value/variable/E//=new(A.member)
|
||||
var/stack/S=new()
|
||||
while(istype(A.object, /token/accessor))
|
||||
if(/datum/token/word)
|
||||
return new/datum/node/expression/value/variable(T.value)
|
||||
if(/datum/token/accessor)
|
||||
var/datum/token/accessor/A=T
|
||||
var/datum/node/expression/value/variable/E//=new(A.member)
|
||||
var/datum/stack/S=new()
|
||||
while(istype(A.object, /datum/token/accessor))
|
||||
S.Push(A)
|
||||
A=A.object
|
||||
ASSERT(istext(A.object))
|
||||
|
||||
while(A)
|
||||
var/node/expression/value/variable/V=new()
|
||||
var/datum/node/expression/value/variable/V=new()
|
||||
V.id=new(A.member)
|
||||
if(E)
|
||||
V.object=E
|
||||
else
|
||||
V.object=new/node/identifier(A.object)
|
||||
V.object=new/datum/node/identifier(A.object)
|
||||
E=V
|
||||
A=S.Pop()
|
||||
return E
|
||||
|
||||
if(/token/number, /token/string)
|
||||
return new/node/expression/value/literal(T.value)
|
||||
if(/datum/token/number, /datum/token/string)
|
||||
return new/datum/node/expression/value/literal(T.value)
|
||||
|
||||
/*
|
||||
Proc: GetOperator
|
||||
@@ -88,9 +88,9 @@ See Also:
|
||||
- <GetBinaryOperator()>
|
||||
- <GetUnaryOperator()>
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/GetOperator(O, type=/node/expression/op, L[])
|
||||
/datum/n_Parser/nS_Parser/proc/GetOperator(O, type=/datum/node/expression/op, L[])
|
||||
if(istype(O, type)) return O //O is already the desired type
|
||||
if(istype(O, /token)) O=O:value //sets O to text
|
||||
if(istype(O, /datum/token)) O=O:value //sets O to text
|
||||
if(istext(O)) //sets O to path
|
||||
if(L.Find(O)) O=L[O]
|
||||
else return null
|
||||
@@ -107,8 +107,8 @@ See Also:
|
||||
- <GetOperator()>
|
||||
- <GetUnaryOperator()>
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/GetBinaryOperator(O)
|
||||
return GetOperator(O, /node/expression/op/binary, options.binary_operators)
|
||||
/datum/n_Parser/nS_Parser/proc/GetBinaryOperator(O)
|
||||
return GetOperator(O, /datum/node/expression/op/binary, options.binary_operators)
|
||||
|
||||
/*
|
||||
Proc: GetUnaryOperator
|
||||
@@ -119,24 +119,24 @@ See Also:
|
||||
- <GetOperator()>
|
||||
- <GetBinaryOperator()>
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/GetUnaryOperator(O)
|
||||
return GetOperator(O, /node/expression/op/unary, options.unary_operators)
|
||||
/datum/n_Parser/nS_Parser/proc/GetUnaryOperator(O)
|
||||
return GetOperator(O, /datum/node/expression/op/unary, options.unary_operators)
|
||||
|
||||
/*
|
||||
Proc: Reduce
|
||||
Takes the operator on top of the opr stack and assigns its operand(s). Then this proc pushes the value of that operation to the top
|
||||
of the val stack.
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/Reduce(stack/opr, stack/val)
|
||||
var/node/expression/op/O=opr.Pop()
|
||||
/datum/n_Parser/nS_Parser/proc/Reduce(datum/stack/opr, datum/stack/val)
|
||||
var/datum/node/expression/op/O=opr.Pop()
|
||||
if(!O) return
|
||||
if(!istype(O))
|
||||
errors+=new/scriptError("Error reducing expression - invalid operator.")
|
||||
errors+=new/datum/scriptError("Error reducing expression - invalid operator.")
|
||||
return
|
||||
//Take O and assign its operands, popping one or two values from the val stack
|
||||
//depending on whether O is a binary or unary operator.
|
||||
if(istype(O, /node/expression/op/binary))
|
||||
var/node/expression/op/binary/B=O
|
||||
if(istype(O, /datum/node/expression/op/binary))
|
||||
var/datum/node/expression/op/binary/B=O
|
||||
B.exp2=val.Pop()
|
||||
B.exp =val.Pop()
|
||||
val.Push(B)
|
||||
@@ -151,12 +151,12 @@ Returns true if the current token represents the end of an expression.
|
||||
Parameters:
|
||||
end - A list of values to compare the current token to.
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/EndOfExpression(end[])
|
||||
/datum/n_Parser/nS_Parser/proc/EndOfExpression(end[])
|
||||
if(!curToken)
|
||||
return 1
|
||||
if(istype(curToken, /token/symbol) && end.Find(curToken.value))
|
||||
if(istype(curToken, /datum/token/symbol) && end.Find(curToken.value))
|
||||
return 1
|
||||
if(istype(curToken, /token/end) && end.Find(/token/end))
|
||||
if(istype(curToken, /datum/token/end) && end.Find(/datum/token/end))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -177,43 +177,43 @@ See Also:
|
||||
- <ParseParenExpression()>
|
||||
- <ParseParamExpression()>
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/ParseExpression(list/end=list(/token/end), list/ErrChars=list("{", "}"))
|
||||
var/stack/opr=new
|
||||
var/stack/val=new
|
||||
/datum/n_Parser/nS_Parser/proc/ParseExpression(list/end=list(/datum/token/end), list/ErrChars=list("{", "}"))
|
||||
var/datum/stack/opr=new
|
||||
var/datum/stack/val=new
|
||||
src.expecting=VALUE
|
||||
while(TRUE)
|
||||
if(EndOfExpression(end))
|
||||
break
|
||||
if(istype(curToken, /token/symbol) && ErrChars.Find(curToken.value))
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
if(istype(curToken, /datum/token/symbol) && ErrChars.Find(curToken.value))
|
||||
errors+=new/datum/scriptError/BadToken(curToken)
|
||||
break
|
||||
|
||||
|
||||
if(index>tokens.len) //End of File
|
||||
errors+=new/scriptError/EndOfFile()
|
||||
errors+=new/datum/scriptError/EndOfFile()
|
||||
break
|
||||
var/token/ntok
|
||||
var/datum/token/ntok
|
||||
if(index+1<=tokens.len)
|
||||
ntok=tokens[index+1]
|
||||
|
||||
if(istype(curToken, /token/symbol) && curToken.value=="(") //Parse parentheses expression
|
||||
if(istype(curToken, /datum/token/symbol) && curToken.value=="(") //Parse parentheses expression
|
||||
if(expecting!=VALUE)
|
||||
errors+=new/scriptError/ExpectedToken("operator", curToken)
|
||||
errors+=new/datum/scriptError/ExpectedToken("operator", curToken)
|
||||
NextToken()
|
||||
continue
|
||||
val.Push(ParseParenExpression())
|
||||
else if(istype(curToken, /token/symbol)) //Operator found.
|
||||
var/node/expression/op/curOperator //Figure out whether it is unary or binary and get a new instance.
|
||||
else if(istype(curToken, /datum/token/symbol)) //Operator found.
|
||||
var/datum/node/expression/op/curOperator //Figure out whether it is unary or binary and get a new instance.
|
||||
if(src.expecting==OPERATOR)
|
||||
curOperator=GetBinaryOperator(curToken)
|
||||
if(!curOperator)
|
||||
errors+=new/scriptError/ExpectedToken("operator", curToken)
|
||||
errors+=new/datum/scriptError/ExpectedToken("operator", curToken)
|
||||
NextToken()
|
||||
continue
|
||||
else
|
||||
curOperator=GetUnaryOperator(curToken)
|
||||
if(!curOperator) //given symbol isn't a unary operator
|
||||
errors+=new/scriptError/ExpectedToken("expression", curToken)
|
||||
errors+=new/datum/scriptError/ExpectedToken("expression", curToken)
|
||||
NextToken()
|
||||
continue
|
||||
|
||||
@@ -222,31 +222,31 @@ See Also:
|
||||
continue
|
||||
opr.Push(curOperator)
|
||||
src.expecting=VALUE
|
||||
else if(ntok && ntok.value=="(" && istype(ntok, /token/symbol)\
|
||||
&& istype(curToken, /token/word)) //Parse function call
|
||||
var/token/preToken=curToken
|
||||
else if(ntok && ntok.value=="(" && istype(ntok, /datum/token/symbol)\
|
||||
&& istype(curToken, /datum/token/word)) //Parse function call
|
||||
var/datum/token/preToken=curToken
|
||||
var/old_expect=src.expecting
|
||||
var/fex=ParseFunctionExpression()
|
||||
if(old_expect!=VALUE)
|
||||
errors+=new/scriptError/ExpectedToken("operator", preToken)
|
||||
errors+=new/datum/scriptError/ExpectedToken("operator", preToken)
|
||||
NextToken()
|
||||
continue
|
||||
val.Push(fex)
|
||||
else if(istype(curToken, /token/keyword)) //inline keywords
|
||||
var/n_Keyword/kw=options.keywords[curToken.value]
|
||||
else if(istype(curToken, /datum/token/keyword)) //inline keywords
|
||||
var/datum/n_Keyword/kw=options.keywords[curToken.value]
|
||||
kw=new kw(inline=1)
|
||||
if(kw)
|
||||
if(!kw.Parse(src))
|
||||
return
|
||||
else
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
else if(istype(curToken, /token/end)) //semicolon found where it wasn't expected
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
errors+=new/datum/scriptError/BadToken(curToken)
|
||||
else if(istype(curToken, /datum/token/end)) //semicolon found where it wasn't expected
|
||||
errors+=new/datum/scriptError/BadToken(curToken)
|
||||
NextToken()
|
||||
continue
|
||||
else
|
||||
if(expecting!=VALUE)
|
||||
errors+=new/scriptError/ExpectedToken("operator", curToken)
|
||||
errors+=new/datum/scriptError/ExpectedToken("operator", curToken)
|
||||
NextToken()
|
||||
continue
|
||||
val.Push(GetExpression(curToken))
|
||||
@@ -256,8 +256,8 @@ See Also:
|
||||
while(opr.Top()) Reduce(opr, val) //Reduce the value stack completely
|
||||
.=val.Pop() //Return what should be the last value on the stack
|
||||
if(val.Top()) //
|
||||
var/node/N=val.Pop()
|
||||
errors+=new/scriptError("Error parsing expression. Unexpected value left on stack: [N.ToString()].")
|
||||
var/datum/node/N=val.Pop()
|
||||
errors+=new/datum/scriptError("Error parsing expression. Unexpected value left on stack: [N.ToString()].")
|
||||
return null
|
||||
|
||||
/*
|
||||
@@ -267,8 +267,8 @@ Parses a function call inside of an expression.
|
||||
See Also:
|
||||
- <ParseExpression()>
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/ParseFunctionExpression()
|
||||
var/node/expression/FunctionCall/exp=new
|
||||
/datum/n_Parser/nS_Parser/proc/ParseFunctionExpression()
|
||||
var/datum/node/expression/FunctionCall/exp=new
|
||||
exp.func_name=curToken.value
|
||||
NextToken() //skip function name
|
||||
NextToken() //skip open parenthesis, already found
|
||||
@@ -279,12 +279,12 @@ See Also:
|
||||
if(loops>=1000)
|
||||
CRASH("Something TERRIBLE has gone wrong in ParseFunctionExpression ;__;")
|
||||
|
||||
if(istype(curToken, /token/symbol) && curToken.value==")")
|
||||
if(istype(curToken, /datum/token/symbol) && curToken.value==")")
|
||||
return exp
|
||||
exp.parameters+=ParseParamExpression()
|
||||
if(curToken.value==","&&istype(curToken, /token/symbol))NextToken() //skip comma
|
||||
if(istype(curToken, /token/end)) //Prevents infinite loop...
|
||||
errors+=new/scriptError/ExpectedToken(")")
|
||||
if(curToken.value==","&&istype(curToken, /datum/token/symbol))NextToken() //skip comma
|
||||
if(istype(curToken, /datum/token/end)) //Prevents infinite loop...
|
||||
errors+=new/datum/scriptError/ExpectedToken(")")
|
||||
return exp
|
||||
|
||||
/*
|
||||
@@ -294,10 +294,10 @@ Parses an expression that ends with a close parenthesis. This is used for parsin
|
||||
See Also:
|
||||
- <ParseExpression()>
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/ParseParenExpression()
|
||||
if(!CheckToken("(", /token/symbol))
|
||||
/datum/n_Parser/nS_Parser/proc/ParseParenExpression()
|
||||
if(!CheckToken("(", /datum/token/symbol))
|
||||
return
|
||||
return new/node/expression/op/unary/group(ParseExpression(list(")")))
|
||||
return new/datum/node/expression/op/unary/group(ParseExpression(list(")")))
|
||||
|
||||
/*
|
||||
Proc: ParseParamExpression
|
||||
@@ -306,7 +306,7 @@ Parses an expression that ends with either a comma or close parenthesis. This is
|
||||
See Also:
|
||||
- <ParseExpression()>
|
||||
*/
|
||||
/n_Parser/nS_Parser/proc/ParseParamExpression()
|
||||
/datum/n_Parser/nS_Parser/proc/ParseParamExpression()
|
||||
return ParseExpression(list(",", ")"))
|
||||
|
||||
#undef OPERATOR
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
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).
|
||||
*/
|
||||
/n_Keyword
|
||||
/datum/n_Keyword
|
||||
var/inline
|
||||
/n_Keyword/New(inline=FALSE)
|
||||
/datum/n_Keyword/New(inline=FALSE)
|
||||
src.inline=inline
|
||||
return ..()
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
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.
|
||||
*/
|
||||
/n_Keyword/proc/Parse(n_Parser/parser)
|
||||
/datum/n_Keyword/proc/Parse(datum/n_Parser/parser)
|
||||
|
||||
/*
|
||||
Class: nS_Keyword
|
||||
@@ -38,118 +38,118 @@
|
||||
<n_Keyword.Parse()> proc.
|
||||
*/
|
||||
//
|
||||
/n_Keyword/nS_Keyword/New(inline=0)
|
||||
/datum/n_Keyword/nS_Keyword/New(inline=0)
|
||||
if(inline)
|
||||
qdel(src)
|
||||
|
||||
/n_Keyword/nS_Keyword/kwReturn/Parse(n_Parser/nS_Parser/parser)
|
||||
/datum/n_Keyword/nS_Keyword/kwReturn/Parse(datum/n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/scriptError/BadReturn(parser.curToken)
|
||||
if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/datum/scriptError/BadReturn(parser.curToken)
|
||||
. = KW_WARN
|
||||
var/node/statement/ReturnStatement/stmt=new
|
||||
var/datum/node/statement/ReturnStatement/stmt=new
|
||||
parser.NextToken() //skip 'return' token
|
||||
stmt.value=parser.ParseExpression()
|
||||
parser.curBlock.statements+=stmt
|
||||
|
||||
/n_Keyword/nS_Keyword/kwIf/Parse(n_Parser/nS_Parser/parser)
|
||||
/datum/n_Keyword/nS_Keyword/kwIf/Parse(datum/n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
var/node/statement/IfStatement/stmt=new
|
||||
var/datum/node/statement/IfStatement/stmt=new
|
||||
parser.NextToken() //skip 'if' token
|
||||
stmt.cond=parser.ParseParenExpression()
|
||||
if(!parser.CheckToken(")", /token/symbol))
|
||||
if(!parser.CheckToken(")", /datum/token/symbol))
|
||||
return KW_FAIL
|
||||
if(!parser.CheckToken("{", /token/symbol, skip=0)) //Token needs to be preserved for parse loop, so skip=0
|
||||
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
|
||||
parser.AddBlock(stmt.block)
|
||||
|
||||
/n_Keyword/nS_Keyword/kwElse/Parse(n_Parser/nS_Parser/parser)
|
||||
/datum/n_Keyword/nS_Keyword/kwElse/Parse(datum/n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
var/list/L=parser.curBlock.statements
|
||||
var/node/statement/IfStatement/stmt
|
||||
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
|
||||
parser.errors+=new/scriptError/ExpectedToken("if statement",parser.curToken)
|
||||
parser.errors+=new/datum/scriptError/ExpectedToken("if statement",parser.curToken)
|
||||
return KW_FAIL
|
||||
parser.NextToken() //skip 'else' token
|
||||
if(!parser.CheckToken("{", /token/symbol, skip=0))
|
||||
if(!parser.CheckToken("{", /datum/token/symbol, skip=0))
|
||||
return KW_ERR
|
||||
stmt.else_block=new()
|
||||
parser.AddBlock(stmt.else_block)
|
||||
|
||||
/n_Keyword/nS_Keyword/kwWhile/Parse(n_Parser/nS_Parser/parser)
|
||||
/datum/n_Keyword/nS_Keyword/kwWhile/Parse(datum/n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
var/node/statement/WhileLoop/stmt=new
|
||||
var/datum/node/statement/WhileLoop/stmt=new
|
||||
parser.NextToken() //skip 'while' token
|
||||
stmt.cond=parser.ParseParenExpression()
|
||||
if(!parser.CheckToken(")", /token/symbol))
|
||||
if(!parser.CheckToken(")", /datum/token/symbol))
|
||||
return KW_FAIL
|
||||
if(!parser.CheckToken("{", /token/symbol, skip=0))
|
||||
if(!parser.CheckToken("{", /datum/token/symbol, skip=0))
|
||||
return KW_ERR
|
||||
parser.curBlock.statements+=stmt
|
||||
stmt.block=new
|
||||
parser.AddBlock(stmt.block)
|
||||
|
||||
/n_Keyword/nS_Keyword/kwBreak/Parse(n_Parser/nS_Parser/parser)
|
||||
/datum/n_Keyword/nS_Keyword/kwBreak/Parse(datum/n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/scriptError/BadToken(parser.curToken)
|
||||
if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/datum/scriptError/BadToken(parser.curToken)
|
||||
. = KW_WARN
|
||||
var/node/statement/BreakStatement/stmt=new
|
||||
var/datum/node/statement/BreakStatement/stmt=new
|
||||
parser.NextToken() //skip 'break' token
|
||||
parser.curBlock.statements+=stmt
|
||||
|
||||
/n_Keyword/nS_Keyword/kwContinue/Parse(n_Parser/nS_Parser/parser)
|
||||
/datum/n_Keyword/nS_Keyword/kwContinue/Parse(datum/n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
if(istype(parser.curBlock, /node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/scriptError/BadToken(parser.curToken)
|
||||
if(istype(parser.curBlock, /datum/node/BlockDefinition/GlobalBlock))
|
||||
parser.errors+=new/datum/scriptError/BadToken(parser.curToken)
|
||||
. = KW_WARN
|
||||
var/node/statement/ContinueStatement/stmt=new
|
||||
var/datum/node/statement/ContinueStatement/stmt=new
|
||||
parser.NextToken() //skip 'break' token
|
||||
parser.curBlock.statements+=stmt
|
||||
|
||||
/n_Keyword/nS_Keyword/kwDef/Parse(n_Parser/nS_Parser/parser)
|
||||
/datum/n_Keyword/nS_Keyword/kwDef/Parse(datum/n_Parser/nS_Parser/parser)
|
||||
.=KW_PASS
|
||||
var/node/statement/FunctionDefinition/def=new
|
||||
var/datum/node/statement/FunctionDefinition/def=new
|
||||
parser.NextToken() //skip 'def' token
|
||||
if(!parser.options.IsValidID(parser.curToken.value))
|
||||
parser.errors+=new/scriptError/InvalidID(parser.curToken)
|
||||
parser.errors+=new/datum/scriptError/InvalidID(parser.curToken)
|
||||
return KW_FAIL
|
||||
def.func_name=parser.curToken.value
|
||||
parser.NextToken()
|
||||
if(!parser.CheckToken("(", /token/symbol))
|
||||
if(!parser.CheckToken("(", /datum/token/symbol))
|
||||
return KW_FAIL
|
||||
while(TRUE) //for now parameters can be separated by whitespace - they don't need a comma in between
|
||||
if(istype(parser.curToken, /token/symbol))
|
||||
if(istype(parser.curToken, /datum/token/symbol))
|
||||
switch(parser.curToken.value)
|
||||
if(",")
|
||||
parser.NextToken()
|
||||
if(")")
|
||||
break
|
||||
else
|
||||
parser.errors+=new/scriptError/BadToken(parser.curToken)
|
||||
parser.errors+=new/datum/scriptError/BadToken(parser.curToken)
|
||||
return KW_ERR
|
||||
|
||||
else if(istype(parser.curToken, /token/word))
|
||||
else if(istype(parser.curToken, /datum/token/word))
|
||||
def.parameters+=parser.curToken.value
|
||||
parser.NextToken()
|
||||
else
|
||||
parser.errors+=new/scriptError/InvalidID(parser.curToken)
|
||||
parser.errors+=new/datum/scriptError/InvalidID(parser.curToken)
|
||||
return KW_ERR
|
||||
if(!parser.CheckToken(")", /token/symbol))
|
||||
if(!parser.CheckToken(")", /datum/token/symbol))
|
||||
return KW_FAIL
|
||||
|
||||
if(istype(parser.curToken, /token/end)) //Function prototype
|
||||
if(istype(parser.curToken, /datum/token/end)) //Function prototype
|
||||
parser.curBlock.statements+=def
|
||||
else if(parser.curToken.value=="{" && istype(parser.curToken, /token/symbol))
|
||||
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/scriptError/BadToken(parser.curToken)
|
||||
parser.errors+=new/datum/scriptError/BadToken(parser.curToken)
|
||||
return KW_FAIL
|
||||
|
||||
#undef KW_FAIL
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Class: n_Parser
|
||||
An object that reads tokens and produces an AST (abstract syntax tree).
|
||||
*/
|
||||
/n_Parser
|
||||
/datum/n_Parser
|
||||
var/index = 1
|
||||
/*
|
||||
Var: index
|
||||
@@ -33,22 +33,22 @@
|
||||
Var: curToken
|
||||
The token at <index> in <tokens>.
|
||||
*/
|
||||
var/token/curToken
|
||||
var/stack/blocks=new
|
||||
var/node/BlockDefinition/GlobalBlock/global_block=new
|
||||
var/node/BlockDefinition/curBlock
|
||||
var/datum/token/curToken
|
||||
var/datum/stack/blocks=new
|
||||
var/datum/node/BlockDefinition/GlobalBlock/global_block=new
|
||||
var/datum/node/BlockDefinition/curBlock
|
||||
|
||||
/*
|
||||
Proc: Parse
|
||||
Reads the tokens and returns the AST's <GlobalBlock> node. Be sure to populate the tokens list before calling this procedure.
|
||||
*/
|
||||
/n_Parser/proc/Parse()
|
||||
/datum/n_Parser/proc/Parse()
|
||||
|
||||
/*
|
||||
Proc: NextToken
|
||||
Sets <curToken> to the next token in the <tokens> list, or null if there are no more tokens.
|
||||
*/
|
||||
/n_Parser/proc/NextToken()
|
||||
/datum/n_Parser/proc/NextToken()
|
||||
if(index>=tokens.len)
|
||||
curToken=null
|
||||
else
|
||||
@@ -59,8 +59,8 @@
|
||||
Class: nS_Parser
|
||||
An implmentation of a parser for n_Script.
|
||||
*/
|
||||
/n_Parser/nS_Parser
|
||||
var/n_scriptOptions/nS_Options/options
|
||||
/datum/n_Parser/nS_Parser
|
||||
var/datum/n_scriptOptions/nS_Options/options
|
||||
/*
|
||||
Constructor: New
|
||||
|
||||
@@ -68,101 +68,101 @@
|
||||
tokens - A list of tokens to parse.
|
||||
options - An object used for configuration.
|
||||
*/
|
||||
/n_Parser/nS_Parser/New(tokens[], n_scriptOptions/options)
|
||||
/datum/n_Parser/nS_Parser/New(tokens[], datum/n_scriptOptions/options)
|
||||
src.tokens=tokens
|
||||
src.options=options
|
||||
curBlock=global_block
|
||||
return ..()
|
||||
|
||||
/n_Parser/nS_Parser/Parse()
|
||||
/datum/n_Parser/nS_Parser/Parse()
|
||||
ASSERT(tokens)
|
||||
for(,src.index<=src.tokens.len, src.index++)
|
||||
curToken=tokens[index]
|
||||
switch(curToken.type)
|
||||
if(/token/keyword)
|
||||
var/n_Keyword/kw=options.keywords[curToken.value]
|
||||
if(/datum/token/keyword)
|
||||
var/datum/n_Keyword/kw=options.keywords[curToken.value]
|
||||
kw=new kw()
|
||||
if(kw)
|
||||
if(!kw.Parse(src))
|
||||
return
|
||||
if(/token/word)
|
||||
var/token/ntok
|
||||
if(/datum/token/word)
|
||||
var/datum/token/ntok
|
||||
if(index+1>tokens.len)
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
errors+=new/datum/scriptError/BadToken(curToken)
|
||||
continue
|
||||
ntok=tokens[index+1]
|
||||
if(!istype(ntok, /token/symbol))
|
||||
errors+=new/scriptError/BadToken(ntok)
|
||||
if(!istype(ntok, /datum/token/symbol))
|
||||
errors+=new/datum/scriptError/BadToken(ntok)
|
||||
continue
|
||||
if(ntok.value=="(")
|
||||
ParseFunctionStatement()
|
||||
else if(options.assign_operators.Find(ntok.value))
|
||||
ParseAssignment()
|
||||
else
|
||||
errors+=new/scriptError/BadToken(ntok)
|
||||
errors+=new/datum/scriptError/BadToken(ntok)
|
||||
continue
|
||||
if(!istype(curToken, /token/end))
|
||||
errors+=new/scriptError/ExpectedToken(";", curToken)
|
||||
if(!istype(curToken, /datum/token/end))
|
||||
errors+=new/datum/scriptError/ExpectedToken(";", curToken)
|
||||
continue
|
||||
if(/token/symbol)
|
||||
if(/datum/token/symbol)
|
||||
if(curToken.value=="}")
|
||||
if(!EndBlock())
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
errors+=new/datum/scriptError/BadToken(curToken)
|
||||
continue
|
||||
else
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
errors+=new/datum/scriptError/BadToken(curToken)
|
||||
continue
|
||||
if(/token/end)
|
||||
warnings+=new/scriptError/BadToken(curToken)
|
||||
if(/datum/token/end)
|
||||
warnings+=new/datum/scriptError/BadToken(curToken)
|
||||
continue
|
||||
else
|
||||
errors+=new/scriptError/BadToken(curToken)
|
||||
errors+=new/datum/scriptError/BadToken(curToken)
|
||||
return
|
||||
return global_block
|
||||
|
||||
/n_Parser/nS_Parser/proc/CheckToken(val, type, err=1, skip=1)
|
||||
/datum/n_Parser/nS_Parser/proc/CheckToken(val, type, err=1, skip=1)
|
||||
if(curToken.value!=val || !istype(curToken,type))
|
||||
if(err)
|
||||
errors+=new/scriptError/ExpectedToken(val, curToken)
|
||||
errors+=new/datum/scriptError/ExpectedToken(val, curToken)
|
||||
return 0
|
||||
if(skip)NextToken()
|
||||
return 1
|
||||
|
||||
/n_Parser/nS_Parser/proc/AddBlock(node/BlockDefinition/B)
|
||||
/datum/n_Parser/nS_Parser/proc/AddBlock(datum/node/BlockDefinition/B)
|
||||
blocks.Push(curBlock)
|
||||
curBlock=B
|
||||
|
||||
/n_Parser/nS_Parser/proc/EndBlock()
|
||||
/datum/n_Parser/nS_Parser/proc/EndBlock()
|
||||
if(curBlock==global_block) return 0
|
||||
curBlock=blocks.Pop()
|
||||
return 1
|
||||
|
||||
/n_Parser/nS_Parser/proc/ParseAssignment()
|
||||
/datum/n_Parser/nS_Parser/proc/ParseAssignment()
|
||||
var/name=curToken.value
|
||||
if(!options.IsValidID(name))
|
||||
errors+=new/scriptError/InvalidID(curToken)
|
||||
errors+=new/datum/scriptError/InvalidID(curToken)
|
||||
return
|
||||
NextToken()
|
||||
var/t=options.binary_operators[options.assign_operators[curToken.value]]
|
||||
var/node/statement/VariableAssignment/stmt=new()
|
||||
var/datum/node/statement/VariableAssignment/stmt=new()
|
||||
stmt.var_name=new(name)
|
||||
NextToken()
|
||||
if(t)
|
||||
stmt.value=new t()
|
||||
stmt.value:exp=new/node/expression/value/variable(stmt.var_name)
|
||||
stmt.value:exp=new/datum/node/expression/value/variable(stmt.var_name)
|
||||
stmt.value:exp2=ParseExpression()
|
||||
else
|
||||
stmt.value=ParseExpression()
|
||||
curBlock.statements+=stmt
|
||||
|
||||
/n_Parser/nS_Parser/proc/ParseFunctionStatement()
|
||||
if(!istype(curToken, /token/word))
|
||||
errors+=new/scriptError("Bad identifier in function call.")
|
||||
/datum/n_Parser/nS_Parser/proc/ParseFunctionStatement()
|
||||
if(!istype(curToken, /datum/token/word))
|
||||
errors+=new/datum/scriptError("Bad identifier in function call.")
|
||||
return
|
||||
var/node/statement/FunctionCall/stmt=new
|
||||
var/datum/node/statement/FunctionCall/stmt=new
|
||||
stmt.func_name=curToken.value
|
||||
NextToken() //skip function name
|
||||
if(!CheckToken("(", /token/symbol)) //Check for and skip open parenthesis
|
||||
if(!CheckToken("(", /datum/token/symbol)) //Check for and skip open parenthesis
|
||||
return
|
||||
var/loops = 0
|
||||
while(TRUE)
|
||||
@@ -171,12 +171,12 @@
|
||||
CRASH("Something TERRIBLE has gone wrong in ParseFunctionStatement ;__;")
|
||||
|
||||
if(!curToken)
|
||||
errors+=new/scriptError/EndOfFile()
|
||||
errors+=new/datum/scriptError/EndOfFile()
|
||||
return
|
||||
if(istype(curToken, /token/symbol) && curToken.value==")")
|
||||
if(istype(curToken, /datum/token/symbol) && curToken.value==")")
|
||||
curBlock.statements+=stmt
|
||||
NextToken() //Skip close parenthesis
|
||||
return
|
||||
var/node/expression/P=ParseParamExpression()
|
||||
var/datum/node/expression/P=ParseParamExpression()
|
||||
stmt.parameters+=P
|
||||
if(istype(curToken, /token/symbol) && curToken.value==",") NextToken()
|
||||
if(istype(curToken, /datum/token/symbol) && curToken.value==",") NextToken()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Class: n_Scanner
|
||||
An object responsible for breaking up source code into tokens for use by the parser.
|
||||
*/
|
||||
/n_Scanner
|
||||
/datum/n_Scanner
|
||||
var/code
|
||||
/*
|
||||
Var: errors
|
||||
@@ -25,27 +25,27 @@
|
||||
Proc: LoadCode
|
||||
Loads source code.
|
||||
*/
|
||||
/n_Scanner/proc/LoadCode(c)
|
||||
/datum/n_Scanner/proc/LoadCode(c)
|
||||
code=c
|
||||
|
||||
/*
|
||||
Proc: LoadCodeFromFile
|
||||
Gets the code from a file and calls <LoadCode()>.
|
||||
*/
|
||||
/n_Scanner/proc/LoadCodeFromFile(f)
|
||||
/datum/n_Scanner/proc/LoadCodeFromFile(f)
|
||||
LoadCode(file2text(f))
|
||||
|
||||
/*
|
||||
Proc: Scan
|
||||
Runs the scanner and returns the resulting list of tokens. Ensure that <LoadCode()> has been called first.
|
||||
*/
|
||||
/n_Scanner/proc/Scan()
|
||||
/datum/n_Scanner/proc/Scan()
|
||||
|
||||
/*
|
||||
Class: nS_Scanner
|
||||
A scanner implementation for n_Script.
|
||||
*/
|
||||
/n_Scanner/nS_Scanner
|
||||
/datum/n_Scanner/nS_Scanner
|
||||
|
||||
/*
|
||||
Variable: codepos
|
||||
@@ -54,7 +54,7 @@
|
||||
var/codepos = 1
|
||||
var/line = 1
|
||||
var/linepos = 0 //column=codepos-linepos
|
||||
var/n_scriptOptions/nS_Options/options
|
||||
var/datum/n_scriptOptions/nS_Options/options
|
||||
var/commenting = 0 /// 1 is a single-line comment, 2 is a multi-line comment
|
||||
/*
|
||||
Variable: ignore
|
||||
@@ -98,14 +98,14 @@
|
||||
code - The source code to tokenize.
|
||||
options - An <nS_Options> object used to configure the scanner.
|
||||
*/
|
||||
/n_Scanner/nS_Scanner/New(code, n_scriptOptions/nS_Options/options)
|
||||
/datum/n_Scanner/nS_Scanner/New(code, datum/n_scriptOptions/nS_Options/options)
|
||||
.=..()
|
||||
ignore+= ascii2text(13) //Carriage return
|
||||
delim += ignore + options.symbols + end_stmt + string_delim
|
||||
src.options=options
|
||||
LoadCode(code)
|
||||
|
||||
/n_Scanner/nS_Scanner/Scan() //Creates a list of tokens from source code
|
||||
/datum/n_Scanner/nS_Scanner/Scan() //Creates a list of tokens from source code
|
||||
var/list/tokens=new
|
||||
for(, src.codepos<=length(code), src.codepos++)
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
else if(char == "/")
|
||||
ReadComment()
|
||||
else if(end_stmt.Find(char))
|
||||
tokens+=new /token/end(char, line, COL)
|
||||
tokens+=new /datum/token/end(char, line, COL)
|
||||
else if(string_delim.Find(char))
|
||||
codepos++ //skip string delimiter
|
||||
tokens+=ReadString(char)
|
||||
@@ -143,7 +143,7 @@
|
||||
Parameters:
|
||||
start - The character used to start the string.
|
||||
*/
|
||||
/n_Scanner/nS_Scanner/proc/ReadString(start)
|
||||
/datum/n_Scanner/nS_Scanner/proc/ReadString(start)
|
||||
var/buf
|
||||
for(, codepos <= length(code), codepos++)//codepos to length(code))
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
@@ -162,8 +162,8 @@
|
||||
else //Unknown escaped text
|
||||
buf+=char
|
||||
if("\n")
|
||||
. = new/token/string(buf, line, COL)
|
||||
errors+=new/scriptError("Unterminated string. Newline reached.", .)
|
||||
. = new/datum/token/string(buf, line, COL)
|
||||
errors+=new/datum/scriptError("Unterminated string. Newline reached.", .)
|
||||
line++
|
||||
linepos=codepos
|
||||
break
|
||||
@@ -172,13 +172,13 @@
|
||||
break
|
||||
else
|
||||
buf+=char //Just a normal character in a string
|
||||
if(!.) return new/token/string(buf, line, COL)
|
||||
if(!.) return new/datum/token/string(buf, line, COL)
|
||||
|
||||
/*
|
||||
Proc: ReadWord
|
||||
Reads characters separated by an item in <delim> into a token.
|
||||
*/
|
||||
/n_Scanner/nS_Scanner/proc/ReadWord()
|
||||
/datum/n_Scanner/nS_Scanner/proc/ReadWord()
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
var/buf
|
||||
while(!delim.Find(char) && codepos<=length(code))
|
||||
@@ -186,15 +186,15 @@ Reads characters separated by an item in <delim> into a token.
|
||||
char=copytext(code, ++codepos, codepos+1)
|
||||
codepos-- //allow main Scan() proc to read the delimiter
|
||||
if(options.keywords.Find(buf))
|
||||
return new /token/keyword(buf, line, COL)
|
||||
return new /datum/token/keyword(buf, line, COL)
|
||||
else
|
||||
return new /token/word(buf, line, COL)
|
||||
return new /datum/token/word(buf, line, COL)
|
||||
|
||||
/*
|
||||
Proc: ReadSymbol
|
||||
Reads a symbol into a token.
|
||||
*/
|
||||
/n_Scanner/nS_Scanner/proc/ReadSymbol()
|
||||
/datum/n_Scanner/nS_Scanner/proc/ReadSymbol()
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
var/buf
|
||||
|
||||
@@ -204,13 +204,13 @@ Reads a symbol into a token.
|
||||
char=copytext(code, codepos, codepos+1)
|
||||
|
||||
codepos-- //allow main Scan() proc to read the next character
|
||||
return new /token/symbol(buf, line, COL)
|
||||
return new /datum/token/symbol(buf, line, COL)
|
||||
|
||||
/*
|
||||
Proc: ReadNumber
|
||||
Reads a number into a token.
|
||||
*/
|
||||
/n_Scanner/nS_Scanner/proc/ReadNumber()
|
||||
/datum/n_Scanner/nS_Scanner/proc/ReadNumber()
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
var/buf
|
||||
var/dec=0
|
||||
@@ -220,9 +220,9 @@ Reads a number into a token.
|
||||
buf+=char
|
||||
codepos++
|
||||
char=copytext(code, codepos, codepos+1)
|
||||
var/token/number/T=new(buf, line, COL)
|
||||
var/datum/token/number/T=new(buf, line, COL)
|
||||
if(isnull(text2num(buf)))
|
||||
errors+=new/scriptError("Bad number: ", T)
|
||||
errors+=new/datum/scriptError("Bad number: ", T)
|
||||
T.value=0
|
||||
codepos-- //allow main Scan() proc to read the next character
|
||||
return T
|
||||
@@ -232,7 +232,7 @@ Proc: ReadComment
|
||||
Reads a comment and outputs the type of comment
|
||||
*/
|
||||
|
||||
/n_Scanner/nS_Scanner/proc/ReadComment()
|
||||
/datum/n_Scanner/nS_Scanner/proc/ReadComment()
|
||||
var/char=copytext(code, codepos, codepos+1)
|
||||
var/nextchar=copytext(code, codepos+1, codepos+2)
|
||||
var/charstring = char+nextchar
|
||||
@@ -269,6 +269,6 @@ Reads a comment and outputs the type of comment
|
||||
if(expectedend) expectedend = 0
|
||||
|
||||
if(comm == 2)
|
||||
errors+=new/scriptError/UnterminatedComment()
|
||||
errors+=new/datum/scriptError/UnterminatedComment()
|
||||
|
||||
#undef COL
|
||||
|
||||
@@ -4,34 +4,34 @@
|
||||
Class: Token
|
||||
Represents an entity and position in the source code.
|
||||
*/
|
||||
/token
|
||||
/datum/token
|
||||
var/value
|
||||
var/line
|
||||
var/column
|
||||
|
||||
/token/New(v, l=0, c=0)
|
||||
/datum/token/New(v, l=0, c=0)
|
||||
value=v
|
||||
line=l
|
||||
column=c
|
||||
|
||||
/token/string
|
||||
/token/symbol
|
||||
/token/word
|
||||
/token/keyword
|
||||
/token/number/New()
|
||||
/datum/token/string
|
||||
/datum/token/symbol
|
||||
/datum/token/word
|
||||
/datum/token/keyword
|
||||
/datum/token/number/New()
|
||||
.=..()
|
||||
if(!isnum(value))
|
||||
value=text2num(value)
|
||||
ASSERT(!isnull(value))
|
||||
/token/accessor
|
||||
/datum/token/accessor
|
||||
var/object
|
||||
var/member
|
||||
|
||||
/token/accessor/New(object, member, l=0, c=0)
|
||||
/datum/token/accessor/New(object, member, l=0, c=0)
|
||||
src.object=object
|
||||
src.member=member
|
||||
src.value="[object].[member]" //for debugging only
|
||||
src.line=l
|
||||
src.column=c
|
||||
|
||||
/token/end
|
||||
/datum/token/end
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/stack
|
||||
/datum/stack
|
||||
var/list/contents=new
|
||||
/stack/proc/Push(value)
|
||||
/datum/stack/proc/Push(value)
|
||||
contents+=value
|
||||
|
||||
/stack/proc/Pop()
|
||||
/datum/stack/proc/Pop()
|
||||
if(!contents.len) return null
|
||||
. = contents[contents.len]
|
||||
contents.len--
|
||||
|
||||
/stack/proc/Top() //returns the item on the top of the stack without removing it
|
||||
/datum/stack/proc/Top() //returns the item on the top of the stack without removing it
|
||||
if(!contents.len) return null
|
||||
return contents[contents.len]
|
||||
|
||||
/stack/proc/Copy()
|
||||
var/stack/S=new()
|
||||
/datum/stack/proc/Copy()
|
||||
var/datum/stack/S=new()
|
||||
S.contents=src.contents.Copy()
|
||||
return S
|
||||
|
||||
/stack/proc/Clear()
|
||||
/datum/stack/proc/Clear()
|
||||
contents.Cut()
|
||||
|
||||
Reference in New Issue
Block a user