-
-
Notifications
You must be signed in to change notification settings - Fork 444
/
Copy pathParser.dm
88 lines (79 loc) · 2.5 KB
/
Parser.dm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
* n_Parser
* An object that reads tokens and produces an AST (abstract syntax tree).
*/
/datum/n_Parser
///The parser's current position in the token's list.
var/index = 1
///The token at <index> in <tokens>.
var/datum/token/curToken
var/datum/stack/blocks = new
var/datum/node/BlockDefinition/GlobalBlock/global_block = new
var/datum/node/BlockDefinition/curBlock
///A list of tokens in the source code generated by a scanner.
var/list/tokens = new
///A list of fatal errors found by the parser. If there are any items in this list, then it is not safe to run the returned AST.
var/list/errors = new
////A list of non-fatal problems in the script.
var/list/warnings = new
///Reads the tokens and returns the AST's <GlobalBlock> node. Be sure to populate the tokens list before calling this procedure.
/datum/n_Parser/proc/Parse()
///Sets <curToken> to the next token in the <tokens> list, or null if there are no more tokens.
/datum/n_Parser/proc/NextToken()
if(index >= length(tokens))
curToken = null
else
curToken = tokens[++index]
return curToken
/*
* nS_Parser
* An implmentation of a parser for n_Script.
*/
/datum/n_Parser/nS_Parser
var/datum/n_scriptOptions/options
/datum/n_Parser/nS_Parser/New(tokens[], datum/n_scriptOptions/options)
src.tokens = tokens
src.options = options
src.curBlock = global_block
return ..()
/datum/n_Parser/nS_Parser/Parse()
ASSERT(tokens)
for(,index <= length(tokens), index++)
curToken = tokens[index]
switch(curToken.type)
if(/datum/token/keyword)
var/datum/n_Keyword/kw = options.keywords[curToken.value]
kw = new kw()
if(kw)
if(!kw.Parse(src))
return
continue
if(/datum/token/symbol)
if(curToken.value == "}")
if(!EndBlock())
errors += new /datum/scriptError/BadToken(curToken)
continue
continue
if(/datum/token/end)
continue
curBlock.statements += ParseExpression()
if(!istype(curToken, /datum/token/end))
errors += new /datum/scriptError/ExpectedToken(";", curToken)
continue
return global_block
/datum/n_Parser/nS_Parser/proc/CheckToken(val, type, err = 1, skip = 1)
if(!curToken || !istype(curToken, type) || curToken.value != val)
if(err)
errors += new /datum/scriptError/ExpectedToken(val, curToken)
return FALSE
if(skip)
NextToken()
return TRUE
/datum/n_Parser/nS_Parser/proc/AddBlock(datum/node/BlockDefinition/B)
blocks.Push(curBlock)
curBlock = B
/datum/n_Parser/nS_Parser/proc/EndBlock()
if(curBlock == global_block)
return FALSE
curBlock = blocks.Pop()
return TRUE