improved a bunch of things (again)
This commit is contained in:
parent
611fc399ae
commit
cda5fe8406
25
Dialogue.gd
25
Dialogue.gd
|
@ -1,7 +1,7 @@
|
|||
extends Control
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
$VBoxContainer/ButtonTemplate.hide()
|
||||
|
||||
func continue_dialogue():
|
||||
if $Tween.is_active():
|
||||
|
@ -12,7 +12,6 @@ func continue_dialogue():
|
|||
$Wol.resume()
|
||||
|
||||
func _on_Wol_line(line):
|
||||
print(var2str(line))
|
||||
$RichTextLabel.text = line.text
|
||||
|
||||
$Tween.remove_all()
|
||||
|
@ -27,9 +26,27 @@ func _on_Wol_line(line):
|
|||
$Tween.start()
|
||||
|
||||
func _on_Wol_options(options):
|
||||
prints('got some options', options)
|
||||
var button_template = $VBoxContainer/ButtonTemplate
|
||||
|
||||
for option in options:
|
||||
var button = button_template.duplicate()
|
||||
button.text = option.line.text
|
||||
button.name = 'Option%d' % option.id
|
||||
|
||||
$VBoxContainer.add_child(button)
|
||||
button.connect('pressed', self, '_on_option_selected', [option])
|
||||
button.show()
|
||||
|
||||
func _on_option_selected(option):
|
||||
$Wol.select_option(option.id)
|
||||
|
||||
for child in $VBoxContainer.get_children():
|
||||
if not 'Template' in child.name:
|
||||
child.queue_free()
|
||||
|
||||
func _on_Wol_finished():
|
||||
$RichTextLabel.text = ''
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey and event.scancode == KEY_ENTER and event.pressed:
|
||||
print('Pressed enter!')
|
||||
continue_dialogue()
|
||||
|
|
|
@ -50,5 +50,6 @@ text = "This is a dialogue option"
|
|||
|
||||
[node name="Tween" type="Tween" parent="."]
|
||||
|
||||
[connection signal="finished" from="Wol" to="." method="_on_Wol_finished"]
|
||||
[connection signal="line" from="Wol" to="." method="_on_Wol_line"]
|
||||
[connection signal="options" from="Wol" to="." method="_on_Wol_options"]
|
||||
|
|
|
@ -19,13 +19,13 @@ export(String, FILE, '*.wol,*.yarn') var path setget set_path
|
|||
export(String) var start_node = 'Start'
|
||||
export(bool) var auto_start = false
|
||||
export(NodePath) var variable_storage_path
|
||||
export var auto_show_options = true
|
||||
|
||||
onready var variable_storage = get_node(variable_storage_path)
|
||||
|
||||
var program
|
||||
|
||||
var dialogue
|
||||
var running = false
|
||||
|
||||
func _ready():
|
||||
if Engine.editor_hint:
|
||||
|
@ -62,18 +62,21 @@ func init_dialogue():
|
|||
dialogue.set_program(program)
|
||||
|
||||
func set_path(_path):
|
||||
var file = File.new()
|
||||
file.open(_path, File.READ)
|
||||
var source = file.get_as_text()
|
||||
file.close()
|
||||
program = WolCompiler.compile_string(source, _path)
|
||||
if not Engine.editor_hint:
|
||||
var file = File.new()
|
||||
file.open(_path, File.READ)
|
||||
var source = file.get_as_text()
|
||||
file.close()
|
||||
program = WolCompiler.compile_string(source, _path)
|
||||
path = _path
|
||||
|
||||
func _handle_line(line):
|
||||
var id = line.id
|
||||
var string = program.strings[id]
|
||||
call_deferred('emit_signal', 'line', string)
|
||||
return Constants.HandlerState.PauseExecution
|
||||
call_deferred('emit_signal', 'line', line)
|
||||
if auto_show_options \
|
||||
and dialogue.get_vm().get_next_instruction().operation == Constants.ByteCode.AddOption:
|
||||
return Constants.HandlerState.ContinueExecution
|
||||
else:
|
||||
return Constants.HandlerState.PauseExecution
|
||||
|
||||
func _handle_command(command):
|
||||
call_deferred('emit_signal', 'command', command)
|
||||
|
@ -84,16 +87,14 @@ func _handle_command(command):
|
|||
return Constants.HandlerState.ContinueExecution
|
||||
|
||||
func _handle_options(options):
|
||||
call_deferred('emit_signal' ,'options', options)
|
||||
call_deferred('emit_signal', 'options', options)
|
||||
return Constants.HandlerState.PauseExecution
|
||||
|
||||
func _handle_dialogue_complete():
|
||||
emit_signal('finished')
|
||||
running = false
|
||||
|
||||
func _handle_node_start(node):
|
||||
emit_signal('node_started', node)
|
||||
print('node started')
|
||||
dialogue.resume()
|
||||
|
||||
if !dialogue._visitedNodeCount.has(node):
|
||||
|
@ -101,28 +102,23 @@ func _handle_node_start(node):
|
|||
else:
|
||||
dialogue._visitedNodeCount[node] += 1
|
||||
|
||||
print(dialogue._visitedNodeCount)
|
||||
|
||||
func _handle_node_complete(node):
|
||||
emit_signal('node_completed', node)
|
||||
running = false
|
||||
return Constants.HandlerState.ContinueExecution
|
||||
|
||||
func select_option(id):
|
||||
dialogue.get_vm().set_selected_option(id)
|
||||
resume()
|
||||
|
||||
func pause():
|
||||
dialogue.call_deferred('pause')
|
||||
|
||||
func start(node = start_node):
|
||||
if running:
|
||||
return
|
||||
|
||||
init_dialogue()
|
||||
emit_signal('started')
|
||||
|
||||
running = true
|
||||
dialogue.set_node(node)
|
||||
dialogue.start()
|
||||
|
||||
func resume():
|
||||
dialogue.call_deferred('resume')
|
||||
|
|
|
@ -72,6 +72,7 @@ static func compile_string(source: String, filename: String):
|
|||
var value : String = result.get_string('value')
|
||||
|
||||
if field == 'title':
|
||||
assert(not ' ' in value, 'No space allowed in title "%s", correct to "%s"' % [value, value.replace(' ','')])
|
||||
title = value
|
||||
|
||||
if(line_number >= source_lines.size() || source_lines[line_number] == '---'):
|
||||
|
@ -83,7 +84,7 @@ static func compile_string(source: String, filename: String):
|
|||
#past header
|
||||
var body_lines : PoolStringArray = []
|
||||
|
||||
while line_number < source_lines.size() && source_lines[line_number]!='===':
|
||||
while line_number < source_lines.size() and source_lines[line_number]!='===':
|
||||
body_lines.append(source_lines[line_number])
|
||||
line_number+=1
|
||||
|
||||
|
@ -91,10 +92,9 @@ static func compile_string(source: String, filename: String):
|
|||
|
||||
body = body_lines.join('\n')
|
||||
var lexer = Lexer.new()
|
||||
var tokens = lexer.tokenize(body, title, filename)
|
||||
|
||||
var tokens : Array = lexer.tokenize(body)
|
||||
var parser = Parser.new(tokens)
|
||||
|
||||
var parser = Parser.new(tokens, title)
|
||||
var parser_node = parser.parse_node()
|
||||
|
||||
parser_node.name = title
|
||||
|
@ -150,7 +150,7 @@ func compile_node(program, parsed_node):
|
|||
|
||||
if dangling_options:
|
||||
emit(Constants.ByteCode.ShowOptions, node_compiled)
|
||||
emit(Constants.ByteCode.Run_node, node_compiled)
|
||||
emit(Constants.ByteCode.RunNode, node_compiled)
|
||||
else:
|
||||
emit(Constants.ByteCode.Stop, node_compiled)
|
||||
|
||||
|
@ -269,11 +269,15 @@ func generate_shortcut_group(node,shortcut_group):
|
|||
if option.condition != null :
|
||||
endof_clause = register_label('conditional_%s'%option_count)
|
||||
generate_expression(node,option.condition)
|
||||
emit(Constants.ByteCode.Jump_if_false,node,[Program.Operand.new(endof_clause)])
|
||||
emit(Constants.ByteCode.JumpIfFalse, node, [Program.Operand.new(endof_clause)])
|
||||
|
||||
var label_line_id : String = ''#no tag TODO: ADD TAG SUPPORT
|
||||
var label_string_id : String = register_string(option.label,node.node_name,
|
||||
label_line_id,option.line_number,[])
|
||||
var label_line_id = '' #TODO: Add tag support
|
||||
var label_string_id = register_string(
|
||||
option.label,
|
||||
node.name,
|
||||
label_line_id,option.line_number,
|
||||
[]
|
||||
)
|
||||
|
||||
emit(Constants.ByteCode.AddOption,node,[Program.Operand.new(label_string_id),Program.Operand.new(op_destination)])
|
||||
|
||||
|
@ -293,7 +297,7 @@ func generate_shortcut_group(node,shortcut_group):
|
|||
|
||||
if option.node != null :
|
||||
generate_block(node,option.node.statements)
|
||||
emit(Constants.ByteCode.Jump_to,node,[Program.Operand.new(end)])
|
||||
emit(Constants.ByteCode.JumpTo,node,[Program.Operand.new(end)])
|
||||
option_count+=1
|
||||
|
||||
#end of option group
|
||||
|
@ -323,10 +327,10 @@ func generate_if(node,if_statement):
|
|||
|
||||
if clause.expression!=null:
|
||||
generate_expression(node,clause.expression)
|
||||
emit(Constants.ByteCode.Jump_if_false,node,[Program.Operand.new(end_clause)])
|
||||
emit(Constants.ByteCode.JumpIfFalse,node,[Program.Operand.new(end_clause)])
|
||||
|
||||
generate_block(node,clause.statements)
|
||||
emit(Constants.ByteCode.Jump_to,node,[Program.Operand.new(endif)])
|
||||
emit(Constants.ByteCode.JumpTo,node,[Program.Operand.new(endif)])
|
||||
|
||||
if clause.expression!=null:
|
||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(end_clause)])
|
||||
|
@ -348,7 +352,7 @@ func generate_option(node,option):
|
|||
emit(Constants.ByteCode.RunNode,node,[Program.Operand.new(destination)])
|
||||
else :
|
||||
var line_iD : String = ''#tags not supported TODO: ADD TAG SUPPORT
|
||||
var string_iD = register_string(option.label,node.node_name,line_iD,option.line_number,[])
|
||||
var string_iD = register_string(option.label,node.name,line_iD,option.line_number,[])
|
||||
|
||||
emit(Constants.ByteCode.AddOption,node,[Program.Operand.new(string_iD),Program.Operand.new(destination)])
|
||||
|
||||
|
@ -357,13 +361,13 @@ func generate_option(node,option):
|
|||
func generate_assignment(node,assignment):
|
||||
# print('generating assign')
|
||||
#assignment
|
||||
if assignment.operation == Constants.TokenType.Equal_to_or_assign:
|
||||
if assignment.operation == Constants.TokenType.EqualToOrAssign:
|
||||
#evaluate the expression to a value for the stack
|
||||
generate_expression(node,assignment.value)
|
||||
else :
|
||||
#this is combined op
|
||||
#get value of var
|
||||
emit(Constants.ByteCode.Push_variable,node,[assignment.destination])
|
||||
emit(Constants.ByteCode.PushVariable,node,[assignment.destination])
|
||||
|
||||
#evaluate the expression and push value to stack
|
||||
generate_expression(node,assignment.value)
|
||||
|
@ -371,16 +375,16 @@ func generate_assignment(node,assignment):
|
|||
#stack contains oldvalue and result
|
||||
|
||||
match assignment.operation:
|
||||
Constants.TokenType.Add_assign:
|
||||
Constants.TokenType.AddAssign:
|
||||
emit(Constants.ByteCode.CallFunc,node,
|
||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Add))])
|
||||
Constants.TokenType.Minus_assign:
|
||||
Constants.TokenType.MinusAssign:
|
||||
emit(Constants.ByteCode.CallFunc,node,
|
||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Minus))])
|
||||
Constants.TokenType.Multiply_assign:
|
||||
Constants.TokenType.MultiplyAssign:
|
||||
emit(Constants.ByteCode.CallFunc,node,
|
||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.MultiplyAssign))])
|
||||
Constants.TokenType.Divide_assign:
|
||||
Constants.TokenType.DivideAssign:
|
||||
emit(Constants.ByteCode.CallFunc,node,
|
||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.DivideAssign))])
|
||||
_:
|
||||
|
@ -388,7 +392,7 @@ func generate_assignment(node,assignment):
|
|||
|
||||
#stack contains destination value
|
||||
#store the top of the stack in variable
|
||||
emit(Constants.ByteCode.Store_variable,node,[Program.Operand.new(assignment.destination)])
|
||||
emit(Constants.ByteCode.StoreVariable,node,[Program.Operand.new(assignment.destination)])
|
||||
|
||||
#clean stack
|
||||
emit(Constants.ByteCode.Pop,node)
|
||||
|
@ -399,9 +403,9 @@ func generate_expression(node,expression):
|
|||
# print('generating expression')
|
||||
#expression = value || func call
|
||||
match expression.type:
|
||||
Constants.Expression_type.Value:
|
||||
Constants.ExpressionType.Value:
|
||||
generate_value(node,expression.value)
|
||||
Constants.Expression_type.Function_call:
|
||||
Constants.ExpressionType.FunctionCall:
|
||||
#eval all parameters
|
||||
for param in expression.params:
|
||||
generate_expression(node,param)
|
||||
|
@ -422,8 +426,8 @@ func generate_value(node,value):
|
|||
Constants.ValueType.Number:
|
||||
emit(Constants.ByteCode.PushNumber,node,[Program.Operand.new(value.value.as_number())])
|
||||
Constants.ValueType.Str:
|
||||
var id : String = register_string(value.value.as_string(),
|
||||
node.node_name,'',value.line_number,[])
|
||||
var id = register_string(value.value.as_string(),
|
||||
node.name,'',value.line_number,[])
|
||||
emit(Constants.ByteCode.PushString,node,[Program.Operand.new(id)])
|
||||
Constants.ValueType.Boolean:
|
||||
emit(Constants.ByteCode.PushBool,node,[Program.Operand.new(value.value.as_bool())])
|
||||
|
|
|
@ -35,50 +35,50 @@ func _init():
|
|||
|
||||
func create_states():
|
||||
var patterns : Dictionary = {}
|
||||
patterns[Constants.TokenType.Text] = '.*'
|
||||
patterns[Constants.TokenType.Text] = ['.*', 'any text']
|
||||
|
||||
patterns[Constants.TokenType.Number] = '\\-?[0-9]+(\\.[0-9+])?'
|
||||
patterns[Constants.TokenType.Str] = '\'([^\'\\\\]*(?:\\.[^\'\\\\]*)*)\''
|
||||
patterns[Constants.TokenType.TagMarker] = '\\#'
|
||||
patterns[Constants.TokenType.LeftParen] = '\\('
|
||||
patterns[Constants.TokenType.RightParen] = '\\)'
|
||||
patterns[Constants.TokenType.EqualTo] = '(==|is(?!\\w)|eq(?!\\w))'
|
||||
patterns[Constants.TokenType.EqualToOrAssign] = '(=|to(?!\\w))'
|
||||
patterns[Constants.TokenType.NotEqualTo] = '(\\!=|neq(?!\\w))'
|
||||
patterns[Constants.TokenType.GreaterThanOrEqualTo] = '(\\>=|gte(?!\\w))'
|
||||
patterns[Constants.TokenType.GreaterThan] = '(\\>|gt(?!\\w))'
|
||||
patterns[Constants.TokenType.LessThanOrEqualTo] = '(\\<=|lte(?!\\w))'
|
||||
patterns[Constants.TokenType.LessThan] = '(\\<|lt(?!\\w))'
|
||||
patterns[Constants.TokenType.AddAssign] = '\\+='
|
||||
patterns[Constants.TokenType.MinusAssign] = '\\-='
|
||||
patterns[Constants.TokenType.MultiplyAssign] = '\\*='
|
||||
patterns[Constants.TokenType.DivideAssign] = '\\/='
|
||||
patterns[Constants.TokenType.Add] = '\\+'
|
||||
patterns[Constants.TokenType.Minus] = '\\-'
|
||||
patterns[Constants.TokenType.Multiply] = '\\*'
|
||||
patterns[Constants.TokenType.Divide] = '\\/'
|
||||
patterns[Constants.TokenType.Modulo] = '\\%'
|
||||
patterns[Constants.TokenType.And] = '(\\&\\&|and(?!\\w))'
|
||||
patterns[Constants.TokenType.Or] = '(\\|\\||or(?!\\w))'
|
||||
patterns[Constants.TokenType.Xor] = '(\\^|xor(?!\\w))'
|
||||
patterns[Constants.TokenType.Not] = '(\\!|not(?!\\w))'
|
||||
patterns[Constants.TokenType.Variable] = '\\$([A-Za-z0-9_\\.])+'
|
||||
patterns[Constants.TokenType.Comma] = '\\,'
|
||||
patterns[Constants.TokenType.TrueToken] = 'true(?!\\w)'
|
||||
patterns[Constants.TokenType.FalseToken] = 'false(?!\\w)'
|
||||
patterns[Constants.TokenType.NullToken] = 'null(?!\\w)'
|
||||
patterns[Constants.TokenType.BeginCommand] = '\\<\\<'
|
||||
patterns[Constants.TokenType.EndCommand] = '\\>\\>'
|
||||
patterns[Constants.TokenType.OptionStart] = '\\[\\['
|
||||
patterns[Constants.TokenType.OptionEnd] = '\\]\\]'
|
||||
patterns[Constants.TokenType.OptionDelimit] = '\\|'
|
||||
patterns[Constants.TokenType.Identifier] = '[a-zA-Z0-9_:\\.]+'
|
||||
patterns[Constants.TokenType.IfToken] = 'if(?!\\w)'
|
||||
patterns[Constants.TokenType.ElseToken] = 'else(?!\\w)'
|
||||
patterns[Constants.TokenType.ElseIf] = 'elseif(?!\\w)'
|
||||
patterns[Constants.TokenType.EndIf] = 'endif(?!\\w)'
|
||||
patterns[Constants.TokenType.Set] = 'set(?!\\w)'
|
||||
patterns[Constants.TokenType.ShortcutOption] = '\\-\\>\\s*'
|
||||
patterns[Constants.TokenType.Number] = ['\\-?[0-9]+(\\.[0-9+])?', 'any number']
|
||||
patterns[Constants.TokenType.Str] = ['\'([^\'\\\\]*(?:\\.[^\'\\\\]*)*)\'', 'any text']
|
||||
patterns[Constants.TokenType.TagMarker] = ['\\#', 'a tag #']
|
||||
patterns[Constants.TokenType.LeftParen] = ['\\(', 'left parenthesis (']
|
||||
patterns[Constants.TokenType.RightParen] = ['\\)', 'right parenthesis )']
|
||||
patterns[Constants.TokenType.EqualTo] = ['(==|is(?!\\w)|eq(?!\\w))', '"=", "is" or "eq"']
|
||||
patterns[Constants.TokenType.EqualToOrAssign] = ['(=|to(?!\\w))', 'equal to "=" or assign "="']
|
||||
patterns[Constants.TokenType.NotEqualTo] = ['(\\!=|neq(?!\\w))', '"!=" or "neq"']
|
||||
patterns[Constants.TokenType.GreaterThanOrEqualTo] = ['(\\>=|gte(?!\\w))', '">=" or "gte"']
|
||||
patterns[Constants.TokenType.GreaterThan] = ['(\\>|gt(?!\\w))', '">" or "gt"']
|
||||
patterns[Constants.TokenType.LessThanOrEqualTo] = ['(\\<=|lte(?!\\w))', '"<=" or "lte"']
|
||||
patterns[Constants.TokenType.LessThan] = ['(\\<|lt(?!\\w))', '"<" or "lt"']
|
||||
patterns[Constants.TokenType.AddAssign] = ['\\+=', '"+="']
|
||||
patterns[Constants.TokenType.MinusAssign] = ['\\-=', '"-="']
|
||||
patterns[Constants.TokenType.MultiplyAssign] = ['\\*=', '"*="']
|
||||
patterns[Constants.TokenType.DivideAssign] = ['\\/=', '"/="']
|
||||
patterns[Constants.TokenType.Add] = ['\\+', '"+"']
|
||||
patterns[Constants.TokenType.Minus] = ['\\-', '"-"']
|
||||
patterns[Constants.TokenType.Multiply] = ['\\*', '"*"']
|
||||
patterns[Constants.TokenType.Divide] = ['\\/', '"/"']
|
||||
patterns[Constants.TokenType.Modulo] = ['\\%', '"%"']
|
||||
patterns[Constants.TokenType.And] = ['(\\&\\&|and(?!\\w))', '"&&" or "and"']
|
||||
patterns[Constants.TokenType.Or] = ['(\\|\\||or(?!\\w))', '"||" or "or"']
|
||||
patterns[Constants.TokenType.Xor] = ['(\\^|xor(?!\\w))', '"^" or "xor"']
|
||||
patterns[Constants.TokenType.Not] = ['(\\!|not(?!\\w))', '"!" or "not"']
|
||||
patterns[Constants.TokenType.Variable] = ['\\$([A-Za-z0-9_\\.])+', 'any variable']
|
||||
patterns[Constants.TokenType.Comma] = ['\\,', '","']
|
||||
patterns[Constants.TokenType.TrueToken] = ['true(?!\\w)', '"true"']
|
||||
patterns[Constants.TokenType.FalseToken] = ['false(?!\\w)', '"false"']
|
||||
patterns[Constants.TokenType.NullToken] = ['null(?!\\w)', '"null"']
|
||||
patterns[Constants.TokenType.BeginCommand] = ['\\<\\<', 'beginning of a command "<<"']
|
||||
patterns[Constants.TokenType.EndCommand] = ['\\>\\>', 'ending of a command ">>"']
|
||||
patterns[Constants.TokenType.OptionStart] = ['\\[\\[', 'start of an option "[["']
|
||||
patterns[Constants.TokenType.OptionEnd] = ['\\]\\]', 'end of an option "]]"']
|
||||
patterns[Constants.TokenType.OptionDelimit] = ['\\|', 'middle of an option "|"']
|
||||
patterns[Constants.TokenType.Identifier] = ['[a-zA-Z0-9_:\\.]+', 'any reference to another node']
|
||||
patterns[Constants.TokenType.IfToken] = ['if(?!\\w)', '"if"']
|
||||
patterns[Constants.TokenType.ElseToken] = ['else(?!\\w)', '"else"']
|
||||
patterns[Constants.TokenType.ElseIf] = ['elseif(?!\\w)', '"elseif"']
|
||||
patterns[Constants.TokenType.EndIf] = ['endif(?!\\w)', '"endif"']
|
||||
patterns[Constants.TokenType.Set] = ['set(?!\\w)', '"set"']
|
||||
patterns[Constants.TokenType.ShortcutOption] = ['\\-\\>\\s*', '"->"']
|
||||
|
||||
#compound states
|
||||
var shortcut_option : String= SHORTCUT + DASH + OPTION
|
||||
|
@ -173,10 +173,7 @@ func create_states():
|
|||
for stateKey in _states.keys():
|
||||
_states[stateKey].stateName = stateKey
|
||||
|
||||
pass
|
||||
|
||||
func tokenize(text:String)->Array:
|
||||
|
||||
func tokenize(text, title, filename):
|
||||
_indentStack.clear()
|
||||
_indentStack.push_front(IntBoolPair.new(0,false))
|
||||
_shouldTrackIndent = false
|
||||
|
@ -191,17 +188,20 @@ func tokenize(text:String)->Array:
|
|||
var line_number : int = 1
|
||||
|
||||
for line in lines:
|
||||
tokens+=tokenize_line(line,line_number)
|
||||
line_number+=1
|
||||
tokens += tokenize_line(line, line_number, title, filename)
|
||||
line_number += 1
|
||||
|
||||
var endOfInput : Token = Token.new(Constants.TokenType.EndOfInput,_currentState,line_number,0)
|
||||
var endOfInput = Token.new(
|
||||
Constants.TokenType.EndOfInput,
|
||||
_currentState,
|
||||
line_number,
|
||||
0
|
||||
)
|
||||
tokens.append(endOfInput)
|
||||
|
||||
# print(tokens)
|
||||
|
||||
return tokens
|
||||
|
||||
func tokenize_line(line:String, line_number : int)->Array:
|
||||
func tokenize_line(line, line_number, title, filename):
|
||||
var tokenStack : Array = []
|
||||
|
||||
var freshLine = line.replace('\t',' ').replace('\r','')
|
||||
|
@ -214,7 +214,13 @@ func tokenize_line(line:String, line_number : int)->Array:
|
|||
#we add an indenation token to record indent level
|
||||
_indentStack.push_front(IntBoolPair.new(indentation,true))
|
||||
|
||||
var indent : Token = Token.new(Constants.TokenType.Indent,_currentState,line_number,prevIndentation.key)
|
||||
var indent : Token = Token.new(
|
||||
Constants.TokenType.Indent,
|
||||
_currentState,
|
||||
filename,
|
||||
line_number,
|
||||
prevIndentation.key
|
||||
)
|
||||
indent.value = '%*s' % [indentation - prevIndentation.key,'']
|
||||
|
||||
_shouldTrackIndent = false
|
||||
|
@ -246,7 +252,7 @@ func tokenize_line(line:String, line_number : int)->Array:
|
|||
var matched : bool = false
|
||||
|
||||
for rule in _currentState.rules:
|
||||
var found : RegExMatch = rule.regex.search(freshLine, column)
|
||||
var found = rule.regex.search(freshLine, column)
|
||||
|
||||
if !found:
|
||||
continue
|
||||
|
@ -273,9 +279,9 @@ func tokenize_line(line:String, line_number : int)->Array:
|
|||
#
|
||||
|
||||
column = startIndex
|
||||
var endIndex : int = found.get_start() + found.get_string().length()
|
||||
var end_index = found.get_start() + found.get_string().length()
|
||||
|
||||
tokenText = freshLine.substr(startIndex,endIndex-startIndex)
|
||||
tokenText = freshLine.substr(startIndex, end_index - startIndex)
|
||||
|
||||
else:
|
||||
tokenText = found.get_string()
|
||||
|
@ -284,36 +290,51 @@ func tokenize_line(line:String, line_number : int)->Array:
|
|||
|
||||
#pre-proccess string
|
||||
if rule.tokenType == Constants.TokenType.Str:
|
||||
tokenText = tokenText.substr(1,tokenText.length() - 2)
|
||||
tokenText = tokenText.substr(1, tokenText.length() - 2)
|
||||
tokenText = tokenText.replace('\\\\', '\\')
|
||||
tokenText = tokenText.replace('\\\'','\'')
|
||||
|
||||
var token : Token = Token.new(rule.tokenType,_currentState,line_number,column,tokenText)
|
||||
var token = Token.new(
|
||||
rule.tokenType,
|
||||
_currentState,
|
||||
filename,
|
||||
line_number,
|
||||
column,
|
||||
tokenText
|
||||
)
|
||||
token.delimitsText = rule.delimitsText
|
||||
|
||||
tokenStack.push_front(token)
|
||||
|
||||
if rule.enterState != null && rule.enterState.length() > 0:
|
||||
|
||||
if !_states.has(rule.enterState):
|
||||
printerr('State[%s] not known - line(%s) col(%s)'%[rule.enterState,line_number,column])
|
||||
if rule.enterState != null and rule.enterState.length() > 0:
|
||||
if not _states.has(rule.enterState):
|
||||
printerr('State[%s] not known - line(%s) col(%s)' % [rule.enterState, line_number, column])
|
||||
return []
|
||||
|
||||
enter_state(_states[rule.enterState])
|
||||
|
||||
if _shouldTrackIndent:
|
||||
if _indentStack.front().key < indentation:
|
||||
_indentStack.append(IntBoolPair.new(indentation,false))
|
||||
_indentStack.append(IntBoolPair.new(indentation, false))
|
||||
|
||||
matched = true
|
||||
break
|
||||
|
||||
if !matched:
|
||||
# TODO: Send out some helpful messages
|
||||
printerr('expectedTokens [%s] - line(%s) col(%s)'%['refineErrors.Lexer.tokenize_line',line_number,column])
|
||||
return []
|
||||
if not matched:
|
||||
var rules = []
|
||||
for rule in _currentState.rules:
|
||||
rules.append('"%s" (%s)' % [Constants.token_type_name(rule.tokenType), rule.human_readable_identifier])
|
||||
|
||||
var lastWhiteSpace : RegExMatch = whitespace.search(line,column)
|
||||
var error_data = [
|
||||
PoolStringArray(rules).join(', ') if rules.size() == 1 else PoolStringArray(rules.slice(0, rules.size() - 2)).join(', ') + ' or %s' % rules[-1],
|
||||
filename,
|
||||
title,
|
||||
line_number,
|
||||
column
|
||||
]
|
||||
assert(false, 'Expected %s in file %s in node "%s" on line #%d (column #%d)' % error_data)
|
||||
|
||||
var lastWhiteSpace = whitespace.search(line, column)
|
||||
if lastWhiteSpace:
|
||||
column += lastWhiteSpace.get_string().length()
|
||||
|
||||
|
@ -339,20 +360,22 @@ func enter_state(state:LexerState):
|
|||
_shouldTrackIndent = true
|
||||
|
||||
class Token:
|
||||
var type : int
|
||||
var value : String
|
||||
var type = -1
|
||||
var value = ''
|
||||
|
||||
var line_number : int
|
||||
var column : int
|
||||
var text : String
|
||||
var filename = ''
|
||||
var line_number = -1
|
||||
var column = -1
|
||||
var text = ''
|
||||
|
||||
var delimitsText : bool= false
|
||||
var paramCount : int
|
||||
var lexerState : String
|
||||
var delimitsText = false
|
||||
var paramCount = -1
|
||||
var lexerState = ''
|
||||
|
||||
func _init(type:int,state: LexerState, line_number:int = -1,column:int = -1,value:String =''):
|
||||
func _init(type, state, filename, line_number = -1, column = -1, value = ''):
|
||||
self.type = type
|
||||
self.lexerState = state.stateName
|
||||
self.filename = filename
|
||||
self.line_number = line_number
|
||||
self.column = column
|
||||
self.value = value
|
||||
|
@ -360,7 +383,6 @@ class Token:
|
|||
func _to_string():
|
||||
return '%s (%s) at %s:%s (state: %s)' % [Constants.token_type_name(type),value,line_number,column,lexerState]
|
||||
|
||||
|
||||
class LexerState:
|
||||
|
||||
var stateName : String
|
||||
|
@ -372,9 +394,9 @@ class LexerState:
|
|||
self.patterns = patterns
|
||||
|
||||
func add_transition(type : int, state : String = '',delimitText : bool = false)->Rule:
|
||||
var pattern = '\\G%s' % patterns[type]
|
||||
var pattern = '\\G%s' % patterns[type][0]
|
||||
# print('pattern = %s' % pattern)
|
||||
var rule = Rule.new(type,pattern,state,delimitText)
|
||||
var rule = Rule.new(type, pattern, patterns[type][1], state, delimitText)
|
||||
rules.append(rule)
|
||||
return rule
|
||||
|
||||
|
@ -409,16 +431,18 @@ class Rule:
|
|||
var tokenType : int
|
||||
var isTextRule : bool
|
||||
var delimitsText : bool
|
||||
var human_readable_identifier = ''
|
||||
|
||||
func _init(type : int , regex : String, enterState : String, delimitsText:bool):
|
||||
func _init(type : int , regex : String, human_readable_identifier, enterState : String, delimitsText:bool):
|
||||
self.tokenType = type
|
||||
self.regex = RegEx.new()
|
||||
self.regex.compile(regex)
|
||||
self.human_readable_identifier = human_readable_identifier
|
||||
self.enterState = enterState
|
||||
self.delimitsText = delimitsText
|
||||
|
||||
func _to_string():
|
||||
return '[Rule : %s - %s]' % [Constants.token_type_name(tokenType),regex]
|
||||
return '[Rule : %s (%s) - %s]' % [Constants.token_type_name(tokenType), human_readable_identifier, regex]
|
||||
|
||||
class IntBoolPair:
|
||||
var key : int
|
||||
|
|
|
@ -4,9 +4,11 @@ const Constants = preload('res://addons/Wol/core/constants.gd')
|
|||
const Lexer = preload('res://addons/Wol/core/compiler/lexer.gd')
|
||||
|
||||
var _tokens = []
|
||||
var title = ''
|
||||
|
||||
func _init(tokens):
|
||||
func _init(tokens, title):
|
||||
self._tokens = tokens
|
||||
self.title = title
|
||||
|
||||
enum Associativity {
|
||||
Left,
|
||||
|
@ -37,7 +39,7 @@ func expect_symbol(token_types = []):
|
|||
|
||||
if token_types.size() == 0:
|
||||
if token.type == Constants.TokenType.EndOfInput:
|
||||
printerr('Unexpected end of input.')
|
||||
assert(false, 'Unexpected end of input')
|
||||
return null
|
||||
return token
|
||||
|
||||
|
@ -45,8 +47,29 @@ func expect_symbol(token_types = []):
|
|||
if token.type == type:
|
||||
return token
|
||||
|
||||
printerr('Unexpexted token: expected[ %s ] but got [ %s ]' % token_types + [token.type])
|
||||
return
|
||||
var token_names = []
|
||||
for type in token_types:
|
||||
token_names.append(Constants.token_type_name(type))
|
||||
|
||||
|
||||
var error_guess = '\n'
|
||||
|
||||
if Constants.token_type_name(token.type) == 'Identifier' \
|
||||
and Constants.token_type_name(token_types[0]) == 'OptionEnd':
|
||||
error_guess += 'Does the node your refer to have a space in it?'
|
||||
else:
|
||||
error_guess = ''
|
||||
|
||||
var error_data = [
|
||||
token.filename,
|
||||
title,
|
||||
token.line_number,
|
||||
token.column,
|
||||
PoolStringArray(token_names).join(', '),
|
||||
Constants.token_type_name(token.type),
|
||||
error_guess
|
||||
]
|
||||
assert(false, '[%s|%s:%d:%d]:\nExpected token "%s" but got "%s"%s' % error_data)
|
||||
|
||||
static func tab(indent_level, input, newline = true):
|
||||
return '%*s| %s%s' % [indent_level * 2, '', input, '' if not newline else '\n']
|
||||
|
@ -55,12 +78,15 @@ func tokens():
|
|||
return _tokens
|
||||
|
||||
class ParseNode:
|
||||
var name = ''
|
||||
|
||||
var parent
|
||||
var line_number = -1
|
||||
var tags = []
|
||||
|
||||
func _init(parent, parser):
|
||||
self.parent = parent
|
||||
|
||||
var tokens = parser.tokens() as Array
|
||||
if tokens.size() > 0:
|
||||
line_number = tokens.front().line_number
|
||||
|
@ -77,7 +103,7 @@ class ParseNode:
|
|||
func get_node_parent():
|
||||
var node = self
|
||||
while node != null:
|
||||
if node.has_method('wol_node'):
|
||||
if node is ParseNode:
|
||||
return node as WolNode
|
||||
node = node.parent
|
||||
return null
|
||||
|
@ -90,7 +116,6 @@ class ParseNode:
|
|||
|
||||
#this is a Wol Node - contains all the text
|
||||
class WolNode extends ParseNode:
|
||||
var name = ''
|
||||
var source = ''
|
||||
|
||||
var editor_node_tags = []
|
||||
|
@ -140,7 +165,7 @@ class Statement extends ParseNode:
|
|||
|
||||
elif Assignment.can_parse(parser):
|
||||
assignment = Assignment.new(self, parser)
|
||||
type = Type.Assignment_statement
|
||||
type = Type.AssignmentStatement
|
||||
|
||||
elif ShortcutOptionGroup.can_parse(parser):
|
||||
shortcut_option_group = ShortcutOptionGroup.new(self, parser)
|
||||
|
@ -175,7 +200,7 @@ class Statement extends ParseNode:
|
|||
info.append(block.tree_string(indent_level))
|
||||
Type.IfStatement:
|
||||
info.append(if_statement.tree_string(indent_level))
|
||||
Type.Assignment_statement:
|
||||
Type.AssignmentStatement:
|
||||
info.append(assignment.tree_string(indent_level))
|
||||
Type.OptionStatement:
|
||||
info.append(option_statement.tree_string(indent_level))
|
||||
|
@ -194,7 +219,7 @@ class CustomCommand extends ParseNode:
|
|||
|
||||
enum Type {
|
||||
Expression,
|
||||
Client_command
|
||||
ClientCommand
|
||||
}
|
||||
|
||||
var type = -1
|
||||
|
@ -215,21 +240,21 @@ class CustomCommand extends ParseNode:
|
|||
#if first token is identifier and second is leftt parenthesis
|
||||
#evaluate as function
|
||||
if (command_tokens.size() > 1 && command_tokens[0].type == Constants.TokenType.Identifier
|
||||
&& command_tokens[1].type == Constants.TokenType.Left_paren):
|
||||
&& command_tokens[1].type == Constants.TokenType.LeftParen):
|
||||
var p = get_script().new(command_tokens, parser.library)
|
||||
var expression = Expression_node.parse(self, p)
|
||||
var expression = ExpressionNode.parse(self, p)
|
||||
type = Type.Expression
|
||||
self.expression = expression
|
||||
else:
|
||||
#otherwise evaluuate command
|
||||
type = Type.Client_command
|
||||
type = Type.ClientCommand
|
||||
self.client_command = command_tokens[0].value
|
||||
|
||||
func tree_string(indent_level):
|
||||
match type:
|
||||
Type.Expression:
|
||||
return tab(indent_level,'Expression: %s'% expression.tree_string(indent_level+1))
|
||||
Type.Client_command:
|
||||
Type.ClientCommand:
|
||||
return tab(indent_level,'Command: %s' % client_command)
|
||||
return ''
|
||||
|
||||
|
@ -246,10 +271,10 @@ class ShortcutOptionGroup extends ParseNode:
|
|||
# expect one otherwise invalid
|
||||
|
||||
var index = 1
|
||||
options.append(Short_cut_option.new(index, self, parser))
|
||||
options.append(ShortCutOption.new(index, self, parser))
|
||||
index += 1
|
||||
while parser.next_symbol_is([Constants.TokenType.ShortcutOption]):
|
||||
options.append(Short_cut_option.new(index, self, parser))
|
||||
options.append(ShortCutOption.new(index, self, parser))
|
||||
index += 1
|
||||
|
||||
func tree_string(indent_level):
|
||||
|
@ -267,7 +292,7 @@ class ShortcutOptionGroup extends ParseNode:
|
|||
static func can_parse(parser):
|
||||
return parser.next_symbol_is([Constants.TokenType.ShortcutOption])
|
||||
|
||||
class Short_cut_option extends ParseNode:
|
||||
class ShortCutOption extends ParseNode:
|
||||
var label = ''
|
||||
var condition
|
||||
var node
|
||||
|
@ -285,7 +310,7 @@ class Short_cut_option extends ParseNode:
|
|||
if parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.IfToken]):
|
||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||
parser.expect_symbol([Constants.TokenType.IfToken])
|
||||
condition = Expression_node.parse(self, parser)
|
||||
condition = ExpressionNode.parse(self, parser)
|
||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||
|
||||
elif parser.next_symbol_is([Constants.TokenType.TagMarker]):
|
||||
|
@ -299,7 +324,7 @@ class Short_cut_option extends ParseNode:
|
|||
|
||||
if parser.next_symbol_is([Constants.TokenType.Indent]):
|
||||
parser.expect_symbol([Constants.TokenType.Indent])
|
||||
node = WolNode.new('%s.%s' %[self.get_node_parent().name , index], self, parser)
|
||||
node = WolNode.new('%s.%s' % [parent.name, index], self, parser)
|
||||
parser.expect_symbol([Constants.TokenType.Dedent])
|
||||
|
||||
|
||||
|
@ -359,7 +384,6 @@ class OptionStatement extends ParseNode:
|
|||
var label = ''
|
||||
|
||||
func _init(parent, parser).(parent, parser):
|
||||
|
||||
var strings = []
|
||||
|
||||
# NOTE: parse [[LABEL
|
||||
|
@ -397,14 +421,14 @@ class IfStatement extends ParseNode:
|
|||
|
||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||
parser.expect_symbol([Constants.TokenType.IfToken])
|
||||
prime.expression = Expression_node.parse(self, parser)
|
||||
prime.expression = ExpressionNode.parse(self, parser)
|
||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||
|
||||
#read statements until 'endif' or 'else' or 'else if'
|
||||
var statements = []#statement
|
||||
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.End_if]) \
|
||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_token]) \
|
||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_if]):
|
||||
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.EndIf]) \
|
||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseToken]) \
|
||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseIf]):
|
||||
|
||||
statements.append(Statement.new(self, parser))
|
||||
|
||||
|
@ -416,20 +440,20 @@ class IfStatement extends ParseNode:
|
|||
clauses.append(prime)
|
||||
|
||||
#handle all else if
|
||||
while parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_if]):
|
||||
while parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseIf]):
|
||||
var clause_elif = Clause.new()
|
||||
|
||||
#parse condition syntax
|
||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||
parser.expect_symbol([Constants.TokenType.Else_if])
|
||||
clause_elif.expression = Expression_node.parse(self, parser)
|
||||
parser.expect_symbol([Constants.TokenType.ElseIf])
|
||||
clause_elif.expression = ExpressionNode.parse(self, parser)
|
||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||
|
||||
|
||||
var elif_statements = []#statement
|
||||
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.End_if]) \
|
||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_token]) \
|
||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_if]):
|
||||
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.EndIf]) \
|
||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseToken]) \
|
||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseIf]):
|
||||
|
||||
elif_statements.append(Statement.new(self, parser))
|
||||
|
||||
|
@ -442,17 +466,17 @@ class IfStatement extends ParseNode:
|
|||
|
||||
#handle else if exists
|
||||
if (parser.next_symbols_are([Constants.TokenType.BeginCommand,
|
||||
Constants.TokenType.Else_token, Constants.TokenType.EndCommand])):
|
||||
Constants.TokenType.ElseToken, Constants.TokenType.EndCommand])):
|
||||
|
||||
#expect no expression - just <<else>>
|
||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||
parser.expect_symbol([Constants.TokenType.Else_token])
|
||||
parser.expect_symbol([Constants.TokenType.ElseToken])
|
||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||
|
||||
#parse until hit endif
|
||||
var clause_else = Clause.new()
|
||||
var el_statements = []#statement
|
||||
while !parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.End_if]):
|
||||
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.EndIf]):
|
||||
el_statements.append(Statement.new(self, parser))
|
||||
|
||||
clause_else.statements = el_statements
|
||||
|
@ -464,7 +488,7 @@ class IfStatement extends ParseNode:
|
|||
|
||||
#finish
|
||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||
parser.expect_symbol([Constants.TokenType.End_if])
|
||||
parser.expect_symbol([Constants.TokenType.EndIf])
|
||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||
|
||||
|
||||
|
@ -488,7 +512,7 @@ class IfStatement extends ParseNode:
|
|||
return parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.IfToken])
|
||||
pass
|
||||
|
||||
class Value_node extends ParseNode:
|
||||
class ValueNode extends ParseNode:
|
||||
const Value = preload('res://addons/Wol/core/value.gd')
|
||||
const Lexer = preload('res://addons/Wol/core/compiler/lexer.gd')
|
||||
var value
|
||||
|
@ -508,15 +532,15 @@ class Value_node extends ParseNode:
|
|||
value = Value.new(float(token.value))
|
||||
Constants.TokenType.Str:
|
||||
value = Value.new(token.value)
|
||||
Constants.TokenType.False_token:
|
||||
Constants.TokenType.FalseToken:
|
||||
value = Value.new(false)
|
||||
Constants.TokenType.True_token:
|
||||
Constants.TokenType.TrueToken:
|
||||
value = Value.new(true)
|
||||
Constants.TokenType.Variable:
|
||||
value = Value.new(null)
|
||||
value.type = Constants.Value_type.Variable
|
||||
value.type = Constants.ValueType.Variable
|
||||
value.variable = token.value
|
||||
Constants.TokenType.Null_token:
|
||||
Constants.TokenType.NullToken:
|
||||
value = Value.new(null)
|
||||
_:
|
||||
printerr('%s, Invalid token type' % token.name)
|
||||
|
@ -529,33 +553,32 @@ class Value_node extends ParseNode:
|
|||
# math (1 + 2 - 5 * 3 / 10 % 2)
|
||||
# Identifiers
|
||||
# Values
|
||||
class Expression_node extends ParseNode:
|
||||
class ExpressionNode extends ParseNode:
|
||||
var type
|
||||
var value
|
||||
var function
|
||||
var params = []#Expression_node
|
||||
var params = []#ExpressionNode
|
||||
|
||||
func _init(parent, parser, value, function = '', params = []).(parent, parser):
|
||||
|
||||
#no function - means value
|
||||
if value != null:
|
||||
self.type = Constants.Expression_type.Value
|
||||
self.type = Constants.ExpressionType.Value
|
||||
self.value = value
|
||||
else:#function
|
||||
|
||||
self.type = Constants.Expression_type.Function_call
|
||||
self.type = Constants.ExpressionType.FunctionCall
|
||||
self.function = function
|
||||
self.params = params
|
||||
|
||||
func tree_string(indent_level):
|
||||
var info = []
|
||||
match type:
|
||||
Constants.Expression_type.Value:
|
||||
Constants.ExpressionType.Value:
|
||||
return value.tree_string(indent_level)
|
||||
Constants.Expression_type.Function_call:
|
||||
Constants.ExpressionType.FunctionCall:
|
||||
info.append(tab(indent_level,'Func[%s - params(%s)]:{'%[function, params.size()]))
|
||||
for param in params:
|
||||
#print('----> %s param_size:%s'%[(function) , params.size()])
|
||||
info.append(param.tree_string(indent_level+1))
|
||||
info.append(tab(indent_level,'}'))
|
||||
|
||||
|
@ -575,13 +598,13 @@ class Expression_node extends ParseNode:
|
|||
Constants.TokenType.Number,
|
||||
Constants.TokenType.Variable,
|
||||
Constants.TokenType.Str,
|
||||
Constants.TokenType.Left_paren,
|
||||
Constants.TokenType.Right_paren,
|
||||
Constants.TokenType.LeftParen,
|
||||
Constants.TokenType.RightParen,
|
||||
Constants.TokenType.Identifier,
|
||||
Constants.TokenType.Comma,
|
||||
Constants.TokenType.True_token,
|
||||
Constants.TokenType.False_token,
|
||||
Constants.TokenType.Null_token
|
||||
Constants.TokenType.TrueToken,
|
||||
Constants.TokenType.FalseToken,
|
||||
Constants.TokenType.NullToken
|
||||
]
|
||||
valid_types += Operator.op_types()
|
||||
valid_types.invert()
|
||||
|
@ -595,9 +618,9 @@ class Expression_node extends ParseNode:
|
|||
if next.type == Constants.TokenType.Variable \
|
||||
or next.type == Constants.TokenType.Number \
|
||||
or next.type == Constants.TokenType.Str \
|
||||
or next.type == Constants.TokenType.False_token \
|
||||
or next.type == Constants.TokenType.True_token \
|
||||
or next.type == Constants.TokenType.Null_token:
|
||||
or next.type == Constants.TokenType.FalseToken \
|
||||
or next.type == Constants.TokenType.TrueToken \
|
||||
or next.type == Constants.TokenType.NullToken:
|
||||
|
||||
#output primitives
|
||||
rpn.append(next)
|
||||
|
@ -606,12 +629,12 @@ class Expression_node extends ParseNode:
|
|||
func_stack.push_back(next)
|
||||
|
||||
#next token is parent - left
|
||||
next = parser.expect_symbol([Constants.TokenType.Left_paren])
|
||||
next = parser.expect_symbol([Constants.TokenType.LeftParen])
|
||||
op_stack.push_back(next)
|
||||
|
||||
elif next.type == Constants.TokenType.Comma:
|
||||
#resolve sub expression before moving on
|
||||
while op_stack.back().type != Constants.TokenType.Left_paren:
|
||||
while op_stack.back().type != Constants.TokenType.LeftParen:
|
||||
var p = op_stack.pop_back()
|
||||
if p == null:
|
||||
printerr('unbalanced parenthesis %s ' % next.name)
|
||||
|
@ -621,7 +644,7 @@ class Expression_node extends ParseNode:
|
|||
|
||||
#next token in op_stack left paren
|
||||
# next parser token not allowed to be right paren or comma
|
||||
if parser.next_symbol_is([Constants.TokenType.Right_paren,
|
||||
if parser.next_symbol_is([Constants.TokenType.RightParen,
|
||||
Constants.TokenType.Comma]):
|
||||
printerr('Expected Expression : %s' % parser.tokens().front().name)
|
||||
|
||||
|
@ -643,34 +666,33 @@ class Expression_node extends ParseNode:
|
|||
|
||||
if next.type == Constants.TokenType.Minus:
|
||||
if last == null \
|
||||
or last.type == Constants.TokenType.Left_paren \
|
||||
or last.type == Constants.TokenType.LeftParen \
|
||||
or Operator.is_op(last.type):
|
||||
#unary minus
|
||||
next.type = Constants.TokenType.Unary_minus
|
||||
next.type = Constants.TokenType.UnaryMinus
|
||||
|
||||
#cannot assign inside expression
|
||||
# x = a is the same as x == a
|
||||
if next.type == Constants.TokenType.EqualToOrAssign:
|
||||
next.type = Constants.TokenType.EqualTo
|
||||
|
||||
|
||||
#operator precedence
|
||||
while (Expression_node.is_apply_precedence(next.type, op_stack)):
|
||||
while (ExpressionNode.is_apply_precedence(next.type, op_stack)):
|
||||
var op = op_stack.pop_back()
|
||||
rpn.append(op)
|
||||
|
||||
op_stack.push_back(next)
|
||||
|
||||
elif next.type == Constants.TokenType.Left_paren:
|
||||
elif next.type == Constants.TokenType.LeftParen:
|
||||
#entered parenthesis sub expression
|
||||
op_stack.push_back(next)
|
||||
elif next.type == Constants.TokenType.Right_paren:
|
||||
elif next.type == Constants.TokenType.RightParen:
|
||||
#leaving sub expression
|
||||
# resolve order of operations
|
||||
while op_stack.back().type != Constants.TokenType.Left_paren:
|
||||
while op_stack.back().type != Constants.TokenType.LeftParen:
|
||||
rpn.append(op_stack.pop_back())
|
||||
if op_stack.back() == null:
|
||||
printerr('Unbalanced parenthasis #Right_paren. Parser.Expression_node')
|
||||
printerr('Unbalanced parenthasis #RightParen. Parser.ExpressionNode')
|
||||
|
||||
|
||||
op_stack.pop_back()
|
||||
|
@ -679,7 +701,7 @@ class Expression_node extends ParseNode:
|
|||
#last token == left paren this == no params
|
||||
#else
|
||||
#we have more than 1 param
|
||||
if last.type != Constants.TokenType.Left_paren:
|
||||
if last.type != Constants.TokenType.LeftParen:
|
||||
func_stack.back().param_count+=1
|
||||
|
||||
rpn.append(op_stack.pop_back())
|
||||
|
@ -698,10 +720,9 @@ class Expression_node extends ParseNode:
|
|||
|
||||
#build expression tree
|
||||
var first = rpn.front()
|
||||
var eval_stack = []#Expression_node
|
||||
var eval_stack = []#ExpressionNode
|
||||
|
||||
while rpn.size() > 0:
|
||||
|
||||
var next = rpn.pop_front()
|
||||
if Operator.is_op(next.type):
|
||||
#operation
|
||||
|
@ -710,7 +731,7 @@ class Expression_node extends ParseNode:
|
|||
if eval_stack.size() < info.arguments:
|
||||
printerr('Error parsing : Not enough arguments for %s [ got %s expected - was %s]'%[Constants.token_type_name(next.type), eval_stack.size(), info.arguments])
|
||||
|
||||
var params = []#Expression_node
|
||||
var params = []#ExpressionNode
|
||||
for i in range(info.arguments):
|
||||
params.append(eval_stack.pop_back())
|
||||
|
||||
|
@ -718,7 +739,7 @@ class Expression_node extends ParseNode:
|
|||
|
||||
var function = get_func_name(next.type)
|
||||
|
||||
var expression = Expression_node.new(parent, parser, null, function, params)
|
||||
var expression = ExpressionNode.new(parent, parser, null, function, params)
|
||||
|
||||
eval_stack.append(expression)
|
||||
|
||||
|
@ -727,19 +748,19 @@ class Expression_node extends ParseNode:
|
|||
|
||||
var function = next.value
|
||||
|
||||
var params = []#Expression_node
|
||||
var params = []#ExpressionNode
|
||||
for i in range(next.param_count):
|
||||
|
||||
params.append(eval_stack.pop_back())
|
||||
|
||||
params.invert()
|
||||
|
||||
var expression = Expression_node.new(parent, parser, null, function, params)
|
||||
var expression = ExpressionNode.new(parent, parser, null, function, params)
|
||||
|
||||
eval_stack.append(expression)
|
||||
else: #raw value
|
||||
var value = Value_node.new(parent, parser, next)
|
||||
var expression = Expression_node.new(parent, parser, value)
|
||||
var value = ValueNode.new(parent, parser, next)
|
||||
var expression = ExpressionNode.new(parent, parser, value)
|
||||
eval_stack.append(expression)
|
||||
|
||||
|
||||
|
@ -796,7 +817,7 @@ class Assignment extends ParseNode:
|
|||
parser.expect_symbol([Constants.TokenType.Set])
|
||||
destination = parser.expect_symbol([Constants.TokenType.Variable]).value
|
||||
operation = parser.expect_symbol(Assignment.valid_ops()).type
|
||||
value = Expression_node.parse(self, parser)
|
||||
value = ExpressionNode.parse(self, parser)
|
||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||
|
||||
func tree_string(indent_level):
|
||||
|
@ -817,10 +838,10 @@ class Assignment extends ParseNode:
|
|||
static func valid_ops():
|
||||
return [
|
||||
Constants.TokenType.EqualToOrAssign,
|
||||
Constants.TokenType.Add_assign,
|
||||
Constants.TokenType.Minus_assign,
|
||||
Constants.TokenType.Divide_assign,
|
||||
Constants.TokenType.Multiply_assign
|
||||
Constants.TokenType.AddAssign,
|
||||
Constants.TokenType.MinusAssign,
|
||||
Constants.TokenType.DivideAssign,
|
||||
Constants.TokenType.MultiplyAssign
|
||||
]
|
||||
|
||||
class Operator extends ParseNode:
|
||||
|
@ -848,22 +869,22 @@ class Operator extends ParseNode:
|
|||
var TokenType = Constants.TokenType
|
||||
|
||||
match op:
|
||||
TokenType.Not, TokenType.Unary_minus:
|
||||
return Operator_info.new(Associativity.Right, 30, 1)
|
||||
TokenType.Not, TokenType.UnaryMinus:
|
||||
return OperatorInfo.new(Associativity.Right, 30, 1)
|
||||
TokenType.Multiply, TokenType.Divide, TokenType.Modulo:
|
||||
return Operator_info.new(Associativity.Left, 20, 2)
|
||||
return OperatorInfo.new(Associativity.Left, 20, 2)
|
||||
TokenType.Add, TokenType.Minus:
|
||||
return Operator_info.new(Associativity.Left, 15, 2)
|
||||
return OperatorInfo.new(Associativity.Left, 15, 2)
|
||||
TokenType.GreaterThan, TokenType.LessThan, TokenType.GreaterThanOrEqualTo, TokenType.LessThanOrEqualTo:
|
||||
return Operator_info.new(Associativity.Left, 10, 2)
|
||||
return OperatorInfo.new(Associativity.Left, 10, 2)
|
||||
TokenType.EqualTo, TokenType.EqualToOrAssign, TokenType.NotEqualTo:
|
||||
return Operator_info.new(Associativity.Left, 5, 2)
|
||||
return OperatorInfo.new(Associativity.Left, 5, 2)
|
||||
TokenType.And:
|
||||
return Operator_info.new(Associativity.Left, 4, 2)
|
||||
return OperatorInfo.new(Associativity.Left, 4, 2)
|
||||
TokenType.Or:
|
||||
return Operator_info.new(Associativity.Left, 3, 2)
|
||||
return OperatorInfo.new(Associativity.Left, 3, 2)
|
||||
TokenType.Xor:
|
||||
return Operator_info.new(Associativity.Left, 2, 2)
|
||||
return OperatorInfo.new(Associativity.Left, 2, 2)
|
||||
_:
|
||||
printerr('Unknown operator: %s' % op.name)
|
||||
return null
|
||||
|
@ -874,7 +895,7 @@ class Operator extends ParseNode:
|
|||
static func op_types():
|
||||
return [
|
||||
Constants.TokenType.Not,
|
||||
Constants.TokenType.Unary_minus,
|
||||
Constants.TokenType.UnaryMinus,
|
||||
|
||||
Constants.TokenType.Add,
|
||||
Constants.TokenType.Minus,
|
||||
|
@ -897,7 +918,7 @@ class Operator extends ParseNode:
|
|||
]
|
||||
|
||||
|
||||
class Operator_info:
|
||||
class OperatorInfo:
|
||||
var associativity
|
||||
var precedence = -1
|
||||
var arguments = -1
|
||||
|
|
|
@ -198,3 +198,9 @@ static func bytecode_name(bytecode):
|
|||
'Stop',
|
||||
'RunNode'
|
||||
][bytecode]
|
||||
|
||||
static func token_name(type):
|
||||
for key in TokenType.keys():
|
||||
if TokenType[key] == type:
|
||||
return key
|
||||
return ''
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
extends Node
|
||||
|
||||
const DEFAULT_START = 'Start'
|
||||
const FMF_PLACEHOLDE = '<VALUE PLACEHOLDER>'
|
||||
|
||||
const Constants = preload('res://addons/Wol/core/constants.gd')
|
||||
const StandardLibrary = preload('res://addons/Wol/core/libraries/standard.gd')
|
||||
|
@ -11,24 +10,19 @@ const Value = preload('res://addons/Wol/core/value.gd')
|
|||
|
||||
var _variableStorage
|
||||
|
||||
var _debugLog
|
||||
var _errLog
|
||||
|
||||
var _program
|
||||
var library
|
||||
|
||||
var _vm : VirtualMachine
|
||||
var _vm
|
||||
|
||||
var _visitedNodeCount : Dictionary = {}
|
||||
var _visitedNodeCount = {}
|
||||
|
||||
var executionComplete : bool
|
||||
var executionComplete
|
||||
|
||||
func _init(variableStorage):
|
||||
_variableStorage = variableStorage
|
||||
_vm = VirtualMachine.new(self)
|
||||
library = WolLibrary.new()
|
||||
_debugLog = funcref(self, 'dlog')
|
||||
_errLog = funcref(self, 'elog')
|
||||
executionComplete = false
|
||||
|
||||
# import the standard library
|
||||
|
@ -41,13 +35,6 @@ func _init(variableStorage):
|
|||
#add function to lib that gets the node visit count
|
||||
library.register_function('visit_count', -1, funcref(self, 'node_visit_count'), true)
|
||||
|
||||
|
||||
func dlog(message:String):
|
||||
print('YARN_DEBUG : %s' % message)
|
||||
|
||||
func elog(message:String):
|
||||
print('YARN_ERROR : %s' % message)
|
||||
|
||||
func is_active():
|
||||
return get_exec_state() != Constants.ExecutionState.Stopped
|
||||
|
||||
|
@ -55,15 +42,19 @@ func is_active():
|
|||
func get_exec_state():
|
||||
return _vm.executionState
|
||||
|
||||
func set_selected_option(option:int):
|
||||
func set_selected_option(option):
|
||||
_vm.set_selected_option(option)
|
||||
|
||||
func set_node(name:String = DEFAULT_START):
|
||||
func set_node(name = DEFAULT_START):
|
||||
_vm.set_node(name)
|
||||
|
||||
func start():
|
||||
if _vm.executionState == Constants.ExecutionState.Stopped:
|
||||
_vm.resume()
|
||||
|
||||
func resume():
|
||||
if _vm.executionState == Constants.ExecutionState.Running:
|
||||
print('BLOCKED')
|
||||
if _vm.executionState == Constants.ExecutionState.Running \
|
||||
or _vm.executionState == Constants.ExecutionState.Stopped:
|
||||
return
|
||||
_vm.resume()
|
||||
|
||||
|
@ -81,12 +72,10 @@ func current_node():
|
|||
|
||||
func get_node_id(name):
|
||||
if _program.nodes.size() == 0:
|
||||
_errLog.call_func('No nodes loaded')
|
||||
return ''
|
||||
if _program.nodes.has(name):
|
||||
return 'id:'+name
|
||||
else:
|
||||
_errLog.call_func('No node named [%s] exists' % name)
|
||||
return ''
|
||||
|
||||
func unloadAll(clear_visited:bool = true):
|
||||
|
@ -116,7 +105,7 @@ func is_node_visited(node = _vm.current_node_name()):
|
|||
|
||||
func node_visit_count(node = _vm.current_node_name()):
|
||||
if node is Value:
|
||||
node = _program.wolStrings[node.value()].text
|
||||
node = _program.strings[node.value()].text
|
||||
|
||||
var visitCount : int = 0
|
||||
if _visitedNodeCount.has(node):
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
extends Object
|
||||
|
||||
var command : String
|
||||
|
||||
func _init(command : String):
|
||||
self.command = command
|
|
@ -1,16 +0,0 @@
|
|||
extends Node
|
||||
|
||||
|
||||
# Declare member variables here. Examples:
|
||||
# var a = 2
|
||||
# var b = "text"
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
#func _process(delta):
|
||||
# pass
|
|
@ -1,8 +0,0 @@
|
|||
extends Object
|
||||
# class_name DialogueLine
|
||||
|
||||
var id = ''
|
||||
var substitutions = []
|
||||
|
||||
func _init(id):
|
||||
self.id = id
|
|
@ -1,13 +0,0 @@
|
|||
extends Object
|
||||
|
||||
const Line = preload("res://addons/Wol/core/dialogue/line.gd")
|
||||
|
||||
var line : Line
|
||||
var id : int
|
||||
var destination : String
|
||||
|
||||
func _init(line : Line,id : int, destination: String):
|
||||
self.line = line
|
||||
self.id = id
|
||||
self.destination = destination
|
||||
|
|
@ -1,69 +1,69 @@
|
|||
extends "res://addons/Wol/core/library.gd"
|
||||
extends 'res://addons/Wol/core/library.gd'
|
||||
|
||||
const Value = preload("res://addons/Wol/core/value.gd")
|
||||
const Value = preload('res://addons/Wol/core/value.gd')
|
||||
|
||||
func _init():
|
||||
register_function("Add",2,funcref(self,"add"),true)
|
||||
register_function("Minus",2,funcref(self,"sub"),true)
|
||||
register_function("UnaryMinus",1,funcref(self,"unary_minus"),true)
|
||||
register_function("Divide",2,funcref(self,"div"),true)
|
||||
register_function("Multiply",2,funcref(self,"mul"),true)
|
||||
register_function("Modulo",2,funcref(self,"mod"),true)
|
||||
register_function("EqualTo",2,funcref(self,"equal"),true)
|
||||
register_function("NotEqualTo",2,funcref(self,"noteq"),true)
|
||||
register_function("GreaterThan",2,funcref(self,"ge"),true)
|
||||
register_function("GreaterThanOrEqualTo",2,funcref(self,"geq"),true)
|
||||
register_function("LessThan",2,funcref(self,"le"),true)
|
||||
register_function("LessThanOrEqualTo",2,funcref(self,"leq"),true)
|
||||
register_function("And",2,funcref(self,"land"),true)
|
||||
register_function("Or",2,funcref(self,"lor"),true)
|
||||
register_function("Xor",2,funcref(self,"xor"),true)
|
||||
register_function("Not",1,funcref(self,"lnot"),true)
|
||||
register_function('Add', 2, funcref(self, 'add'), true)
|
||||
register_function('Minus', 2, funcref(self, 'sub'), true)
|
||||
register_function('UnaryMinus', 1, funcref(self, 'unary_minus'), true)
|
||||
register_function('Divide', 2, funcref(self, 'div'), true)
|
||||
register_function('Multiply', 2, funcref(self, 'mul'), true)
|
||||
register_function('Modulo', 2, funcref(self, 'mod'), true)
|
||||
register_function('EqualTo', 2, funcref(self, 'equal'), true)
|
||||
register_function('NotEqualTo', 2, funcref(self, 'noteq'), true)
|
||||
register_function('GreaterThan', 2, funcref(self, 'ge'), true)
|
||||
register_function('GreaterThanOrEqualTo', 2, funcref(self, 'geq'), true)
|
||||
register_function('LessThan', 2, funcref(self, 'le'), true)
|
||||
register_function('LessThanOrEqualTo', 2, funcref(self, 'leq'), true)
|
||||
register_function('And', 2, funcref(self, 'land'), true)
|
||||
register_function('Or', 2, funcref(self, 'lor'), true)
|
||||
register_function('Xor', 2, funcref(self, 'xor'), true)
|
||||
register_function('Not', 1, funcref(self, 'lnot'), true)
|
||||
|
||||
func add(param1:Value,param2:Value):
|
||||
func add(param1, param2):
|
||||
return param1.add(param2)
|
||||
|
||||
func sub(param1:Value,param2:Value):
|
||||
func sub(param1, param2):
|
||||
return param1.sub(param2)
|
||||
|
||||
func unary_minus(param1:Value):
|
||||
func unary_minus(param1):
|
||||
return param1.negative()
|
||||
|
||||
func div(param1:Value,param2:Value):
|
||||
func div(param1, param2):
|
||||
return param1.div(param2)
|
||||
|
||||
func mul(param1:Value,param2:Value):
|
||||
func mul(param1, param2):
|
||||
return param1.mult(param2)
|
||||
|
||||
func mod(param1:Value,param2:Value):
|
||||
func mod(param1, param2):
|
||||
return param1.mod(param2)
|
||||
|
||||
func equal(param1:Value,param2:Value):
|
||||
func equal(param1, param2):
|
||||
return param1.equals(param2)
|
||||
|
||||
func noteq(param1:Value,param2:Value):
|
||||
func noteq(param1, param2):
|
||||
return !param1.equals(param2)
|
||||
|
||||
func ge(param1:Value,param2:Value):
|
||||
func ge(param1, param2):
|
||||
return param1.greater(param2)
|
||||
|
||||
func geq(param1:Value,param2:Value):
|
||||
func geq(param1, param2):
|
||||
return param1.geq(param2)
|
||||
|
||||
func le(param1:Value,param2:Value):
|
||||
func le(param1, param2):
|
||||
return param1.less(param2)
|
||||
|
||||
func leq(param1:Value,param2:Value):
|
||||
func leq(param1, param2):
|
||||
return param1.leq(param2)
|
||||
|
||||
func land(param1:Value,param2:Value):
|
||||
return param1.as_bool() && param2.as_bool()
|
||||
func land(param1, param2):
|
||||
return param1.as_bool() and param2.as_bool()
|
||||
|
||||
func lor(param1:Value,param2:Value):
|
||||
return param1.as_bool() || param2.as_bool()
|
||||
func lor(param1, param2):
|
||||
return param1.as_bool() or param2.as_bool()
|
||||
|
||||
func xor(param1:Value,param2:Value):
|
||||
func xor(param1, param2):
|
||||
return param1.as_bool() != param2.as_bool()
|
||||
|
||||
func lnot(param1:Value):
|
||||
return !param1.as_bool()
|
||||
func lnot(param1):
|
||||
return not param1.as_bool()
|
||||
|
|
|
@ -22,6 +22,22 @@ class Line:
|
|||
self.implicit = implicit
|
||||
self.meta = meta
|
||||
|
||||
class Option:
|
||||
var line
|
||||
var id = -1
|
||||
var destination = ''
|
||||
|
||||
func _init(line, id, destination):
|
||||
self.line = line
|
||||
self.id = id
|
||||
self.destination = destination
|
||||
|
||||
class Command:
|
||||
var command = ''
|
||||
|
||||
func _init(command):
|
||||
self.command = command
|
||||
|
||||
class WolNode:
|
||||
var name = ''
|
||||
var instructions = []
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
extends Node
|
||||
|
||||
const Constants = preload('res://addons/Wol/core/constants.gd')
|
||||
|
||||
var FunctionInfo = load('res://addons/Wol/core/function_info.gd')
|
||||
var Value = load('res://addons/Wol/core/value.gd')
|
||||
var WolProgram = load('res://addons/Wol/core/program/program.gd')
|
||||
var WolNode = load('res://addons/Wol/core/program/wol_node.gd')
|
||||
var Instruction = load('res://addons/Wol/core/program/instruction.gd')
|
||||
var Line = load('res://addons/Wol/core/dialogue/line.gd')
|
||||
var Command = load('res://addons/Wol/core/dialogue/command.gd')
|
||||
var Option = load('res://addons/Wol/core/dialogue/option.gd')
|
||||
|
||||
const EXECUTION_COMPLETE : String = 'execution_complete_command'
|
||||
|
||||
|
@ -54,15 +46,12 @@ func set_node(name:String) -> bool:
|
|||
printerr('No node named %s has been loaded' % name)
|
||||
return false
|
||||
|
||||
_dialogue.dlog('Running node %s' % name)
|
||||
|
||||
_currentNode = _program.nodes[name]
|
||||
reset()
|
||||
_state.currentNodeName = name
|
||||
nodeStartHandler.call_func(name)
|
||||
return true
|
||||
|
||||
|
||||
func current_node_name()->String:
|
||||
return _currentNode.nodeName
|
||||
|
||||
|
@ -86,8 +75,8 @@ func set_selected_option(id):
|
|||
printerr('Unable to select option when dialogue not waiting for option')
|
||||
return false
|
||||
|
||||
if id < 0 || id >= _state.currentOptions.size():
|
||||
printerr('%d is not a valid option '%id)
|
||||
if id < 0 or id >= _state.currentOptions.size():
|
||||
printerr('%d is not a valid option ' % id)
|
||||
return false
|
||||
|
||||
var destination = _state.currentOptions[id].value
|
||||
|
@ -99,40 +88,39 @@ func set_selected_option(id):
|
|||
|
||||
return true
|
||||
|
||||
func has_options()->bool:
|
||||
return _state.currentOptions.size() > 0
|
||||
|
||||
func reset():
|
||||
_state = VmState.new()
|
||||
|
||||
#continue execution
|
||||
func resume()->bool:
|
||||
if _currentNode == null :
|
||||
func get_next_instruction():
|
||||
return null if _currentNode.instructions.size() - 1 <= _state.programCounter else _currentNode.instructions[_state.programCounter + 1]
|
||||
|
||||
func resume():
|
||||
if _currentNode == null:
|
||||
printerr('Cannot run dialogue with no node selected')
|
||||
return false
|
||||
|
||||
if executionState == Constants.ExecutionState.WaitingForOption:
|
||||
printerr('Cannot run while waiting for option')
|
||||
return false
|
||||
|
||||
if lineHandler == null :
|
||||
if lineHandler == null:
|
||||
printerr('Cannot run without a lineHandler')
|
||||
return false
|
||||
|
||||
if optionsHandler == null :
|
||||
if optionsHandler == null:
|
||||
printerr('Cannot run without an optionsHandler')
|
||||
return false
|
||||
|
||||
if commandHandler == null :
|
||||
if commandHandler == null:
|
||||
printerr('Cannot run without an commandHandler')
|
||||
return false
|
||||
if nodeStartHandler == null :
|
||||
if nodeStartHandler == null:
|
||||
printerr('Cannot run without a nodeStartHandler')
|
||||
return false
|
||||
if nodeCompleteHandler == null :
|
||||
if nodeCompleteHandler == null:
|
||||
printerr('Cannot run without an nodeCompleteHandler')
|
||||
return false
|
||||
|
||||
|
||||
executionState = Constants.ExecutionState.Running
|
||||
|
||||
#execute instruction until something cool happens
|
||||
|
@ -140,14 +128,13 @@ func resume()->bool:
|
|||
var currentInstruction = _currentNode.instructions[_state.programCounter]
|
||||
|
||||
run_instruction(currentInstruction)
|
||||
_state.programCounter+=1
|
||||
_state.programCounter += 1
|
||||
|
||||
if _state.programCounter >= _currentNode.instructions.size():
|
||||
nodeCompleteHandler.call_func(_currentNode.nodeName)
|
||||
executionState = Constants.ExecutionState.Stopped
|
||||
reset()
|
||||
dialogueCompleteHandler.call_func()
|
||||
_dialogue.dlog('Run Complete')
|
||||
|
||||
return true
|
||||
|
||||
|
@ -171,7 +158,7 @@ func run_instruction(instruction)->bool:
|
|||
#pass it to client as line
|
||||
var key = instruction.operands[0].value
|
||||
|
||||
var line = Line.new(key)
|
||||
var line = _program.strings[key]
|
||||
|
||||
#the second operand is the expression count
|
||||
# of format function
|
||||
|
@ -180,7 +167,6 @@ func run_instruction(instruction)->bool:
|
|||
|
||||
var pause : int = lineHandler.call_func(line)
|
||||
|
||||
|
||||
if pause == Constants.HandlerState.PauseExecution:
|
||||
executionState = Constants.ExecutionState.Suspended
|
||||
|
||||
|
@ -190,7 +176,7 @@ func run_instruction(instruction)->bool:
|
|||
if instruction.operands.size() > 1:
|
||||
pass#add format function
|
||||
|
||||
var command = Command.new(commandText)
|
||||
var command = Program.Command.new(commandText)
|
||||
|
||||
var pause = commandHandler.call_func(command) as int
|
||||
if pause == Constants.HandlerState.PauseExecution:
|
||||
|
@ -275,7 +261,7 @@ func run_instruction(instruction)->bool:
|
|||
|
||||
Constants.ByteCode.Stop:
|
||||
#stop execution and repost it
|
||||
nodeCompleteHandler.call_func(_currentNode.nodeName)
|
||||
nodeCompleteHandler.call_func(_currentNode.name)
|
||||
dialogueCompleteHandler.call_func()
|
||||
executionState = Constants.ExecutionState.Stopped
|
||||
reset()
|
||||
|
@ -290,7 +276,7 @@ func run_instruction(instruction)->bool:
|
|||
else :
|
||||
name = instruction.operands[0].value
|
||||
|
||||
var pause = nodeCompleteHandler.call_func(_currentNode.nodeName)
|
||||
var pause = nodeCompleteHandler.call_func(_currentNode.name)
|
||||
set_node(name)
|
||||
_state.programCounter-=1
|
||||
if pause == Constants.HandlerState.PauseExecution:
|
||||
|
@ -300,13 +286,13 @@ func run_instruction(instruction)->bool:
|
|||
# add an option to current state
|
||||
var key = instruction.operands[0].value
|
||||
|
||||
var line = Line.new(key)
|
||||
var line = _program.strings[key]
|
||||
|
||||
if instruction.operands.size() > 2:
|
||||
pass #formated text options
|
||||
|
||||
# line to show and node name
|
||||
_state.currentOptions.append(SimpleEntry.new(line,instruction.operands[1].value))
|
||||
_state.currentOptions.append(SimpleEntry.new(line, instruction.operands[1].value))
|
||||
|
||||
Constants.ByteCode.ShowOptions:
|
||||
#show options - stop if none
|
||||
|
@ -320,7 +306,7 @@ func run_instruction(instruction)->bool:
|
|||
var choices : Array = []#Option
|
||||
for optionIndex in range(_state.currentOptions.size()):
|
||||
var option : SimpleEntry = _state.currentOptions[optionIndex]
|
||||
choices.append(Option.new(option.key, optionIndex, option.value))
|
||||
choices.append(Program.Option.new(option.key, optionIndex, option.value))
|
||||
|
||||
#we cant continue until option chosen
|
||||
executionState = Constants.ExecutionState.WaitingForOption
|
||||
|
@ -334,7 +320,7 @@ func run_instruction(instruction)->bool:
|
|||
#bytecode messed up woopsise
|
||||
executionState = Constants.ExecutionState.Stopped
|
||||
reset()
|
||||
printerr('Unknown Bytecode %s '%instruction.operation)
|
||||
printerr('Unknown Bytecode %s' % instruction.operation)
|
||||
return false
|
||||
|
||||
return true
|
||||
|
@ -353,7 +339,6 @@ class VmState:
|
|||
else:
|
||||
stack.push_back(Value.new(value))
|
||||
|
||||
|
||||
func pop_value():
|
||||
return stack.pop_back()
|
||||
|
||||
|
@ -365,8 +350,8 @@ class VmState:
|
|||
|
||||
class SimpleEntry:
|
||||
var key
|
||||
var value : String
|
||||
var value
|
||||
|
||||
func _init(key,value:String):
|
||||
func _init(key, value):
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
|
|
@ -1,78 +1,41 @@
|
|||
title: Start
|
||||
tags:
|
||||
colorID: 0
|
||||
position: -1892,-1013
|
||||
position: 0, 0
|
||||
---
|
||||
<<load_situation The Revolver>>
|
||||
<<animation elevator door open>>
|
||||
<<a_custom_command>>
|
||||
<<command_with multiple arguments>>
|
||||
|
||||
Masami: Gina, this way! #line:5d7a7c
|
||||
Gina: Patience! I’m coming.
|
||||
>Still, she didn’t pick up her pace and kept hesitantly looking around.<
|
||||
Masami: Everything should be fine, let’s just go. We won.
|
||||
Masami: Unless you are planning on backstabbing me at the finish line, that is.
|
||||
Gina: How funny. You are not that special.
|
||||
Masami: Har har. Now start walking or I’ll carry you out the front door.
|
||||
Masami: I don’t want to give Monokuma the time to come up with a new death game for two while we are trying to get through the exit.
|
||||
Gina: ...
|
||||
// remove "to" to trigger error
|
||||
<<set $direction to 'this'>>
|
||||
<<set $one to 1>>
|
||||
|
||||
<<zoom to vault door>>
|
||||
// Implement inline expressions
|
||||
Bob: Theresa, {$direction} way! #line:5d7a7c
|
||||
Theresa: Did you know one + one equals {$one + $one}?
|
||||
Bob: You wanna go somewhere?
|
||||
|
||||
Masami: Wait, the vault door… It’s not open.
|
||||
Gina: So it seems.
|
||||
Masami: But that doesn’t make sense! So far we have opened one lock per two deceased. All seven locks should be open by now.
|
||||
>In desperation I tried the vault handle. I wasn’t exceptionally strong, but I doubted even a weightlifter could open this door whether it was held shut by one or dozen locks.<
|
||||
Gina: Rather than using your energy by tearing at the 700kg door-
|
||||
Masami: I wasn’t trying to brute force it.
|
||||
Gina: Anyway, I would suggest you spare a glance at the reception desk. It appears the staff has given us one last gift.
|
||||
Masami: The reception desk?
|
||||
|
||||
<<zoom to gun>>
|
||||
|
||||
Masami: A paper and...
|
||||
Masami: ... That’s a gun.
|
||||
Gina: A revolver, in fact. Such an old fashioned choice of firearm. Though, I appreciate the aesthetic. How pretty.
|
||||
Masami: I don’t like this. Why is it here?
|
||||
>I took the paper from the table and briskly unfolded it.<
|
||||
- Congratulations on reaching the final part of the game!-
|
||||
- Unfortunately, no one remembers a silver medalist.-
|
||||
- Let’s round up the game with a match of our favorite luck game! Russian roulette should be simple enough.-
|
||||
- Now then, ladies first!-
|
||||
-Staff-
|
||||
Masami: Russian roulette… Are you kidding me?
|
||||
Masami: This can’t be part of the game. This wasn’t in the rules!
|
||||
Masami: I know the winning condition hasn’t been met but-
|
||||
Gina: It’s rigged.
|
||||
Masami: What?
|
||||
>Gina had picked up the revolver from the table and without better judgement, opened the cylinder for inspection.<
|
||||
Gina: It’s rigged.
|
||||
Masami: ... “Ladies first.”
|
||||
Masami: The cylinder is full, isn't it?
|
||||
>Gina let out a tired sigh. Her shoulders slumping heavily from disappointment.<
|
||||
Gina: I got so far.
|
||||
Gina: I don’t know what led me to believe the outcome would be any different.
|
||||
Gina: This is such a waste of resources as well.
|
||||
Masami: Gina, put the revolver down. If the game is rigged, you don’t have to play. The rules won’t matter then.
|
||||
Gina: Let it rest.
|
||||
Gina: Like any of it matters.
|
||||
Masami: What do you mean?
|
||||
>She didn’t answer.<
|
||||
>Instead, she absentmindedly fiddled with the cylinder before locking it in place.<
|
||||
>Then she spun the cylinder for the hell of it before raising the revolver’s barrel against her very own temple.<
|
||||
>She looked resigned. Though I couldn’t help but notice the slight glint of fear in her eyes.<
|
||||
>None of us wanted to die.<
|
||||
Masami: Gina, please.
|
||||
Gina: Congratulations.
|
||||
Masami: Gina!
|
||||
<<sound revolver_bang>>
|
||||
<<fade_out>>
|
||||
|
||||
[[Waking up]]
|
||||
[[Go to the store|TheStore]]
|
||||
[[Lets stay here and talk|Talk]]
|
||||
===
|
||||
title: Waking up
|
||||
title: TheStore
|
||||
tags:
|
||||
colorID: 0
|
||||
position: -1527,-881
|
||||
position: 0, 200
|
||||
---
|
||||
You: *waking up noices*
|
||||
Clerk: Welcome to the store.
|
||||
Clerk: Can I help you with anything?
|
||||
[[Go home|Start]]
|
||||
===
|
||||
title: Talk
|
||||
tags:
|
||||
colorID: 0
|
||||
position: 0, 400
|
||||
---
|
||||
Bob: So how are you really?
|
||||
Theresa: I'm good!
|
||||
Bob: Do you want to continue talking?
|
||||
-> Yes
|
||||
[[Start]]
|
||||
-> No
|
||||
===
|
||||
|
|
|
@ -38,7 +38,7 @@ _global_script_class_icons={
|
|||
|
||||
[application]
|
||||
|
||||
config/name="YarnSpinner"
|
||||
config/name="Wol"
|
||||
run/main_scene="res://Dialogue.tscn"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
|
|
Reference in a new issue