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
|
extends Control
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
pass
|
$VBoxContainer/ButtonTemplate.hide()
|
||||||
|
|
||||||
func continue_dialogue():
|
func continue_dialogue():
|
||||||
if $Tween.is_active():
|
if $Tween.is_active():
|
||||||
|
@ -12,7 +12,6 @@ func continue_dialogue():
|
||||||
$Wol.resume()
|
$Wol.resume()
|
||||||
|
|
||||||
func _on_Wol_line(line):
|
func _on_Wol_line(line):
|
||||||
print(var2str(line))
|
|
||||||
$RichTextLabel.text = line.text
|
$RichTextLabel.text = line.text
|
||||||
|
|
||||||
$Tween.remove_all()
|
$Tween.remove_all()
|
||||||
|
@ -27,9 +26,27 @@ func _on_Wol_line(line):
|
||||||
$Tween.start()
|
$Tween.start()
|
||||||
|
|
||||||
func _on_Wol_options(options):
|
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):
|
func _input(event):
|
||||||
if event is InputEventKey and event.scancode == KEY_ENTER and event.pressed:
|
if event is InputEventKey and event.scancode == KEY_ENTER and event.pressed:
|
||||||
print('Pressed enter!')
|
|
||||||
continue_dialogue()
|
continue_dialogue()
|
||||||
|
|
|
@ -50,5 +50,6 @@ text = "This is a dialogue option"
|
||||||
|
|
||||||
[node name="Tween" type="Tween" parent="."]
|
[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="line" from="Wol" to="." method="_on_Wol_line"]
|
||||||
[connection signal="options" from="Wol" to="." method="_on_Wol_options"]
|
[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(String) var start_node = 'Start'
|
||||||
export(bool) var auto_start = false
|
export(bool) var auto_start = false
|
||||||
export(NodePath) var variable_storage_path
|
export(NodePath) var variable_storage_path
|
||||||
|
export var auto_show_options = true
|
||||||
|
|
||||||
onready var variable_storage = get_node(variable_storage_path)
|
onready var variable_storage = get_node(variable_storage_path)
|
||||||
|
|
||||||
var program
|
var program
|
||||||
|
|
||||||
var dialogue
|
var dialogue
|
||||||
var running = false
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
if Engine.editor_hint:
|
if Engine.editor_hint:
|
||||||
|
@ -62,6 +62,7 @@ func init_dialogue():
|
||||||
dialogue.set_program(program)
|
dialogue.set_program(program)
|
||||||
|
|
||||||
func set_path(_path):
|
func set_path(_path):
|
||||||
|
if not Engine.editor_hint:
|
||||||
var file = File.new()
|
var file = File.new()
|
||||||
file.open(_path, File.READ)
|
file.open(_path, File.READ)
|
||||||
var source = file.get_as_text()
|
var source = file.get_as_text()
|
||||||
|
@ -70,9 +71,11 @@ func set_path(_path):
|
||||||
path = _path
|
path = _path
|
||||||
|
|
||||||
func _handle_line(line):
|
func _handle_line(line):
|
||||||
var id = line.id
|
call_deferred('emit_signal', 'line', line)
|
||||||
var string = program.strings[id]
|
if auto_show_options \
|
||||||
call_deferred('emit_signal', 'line', string)
|
and dialogue.get_vm().get_next_instruction().operation == Constants.ByteCode.AddOption:
|
||||||
|
return Constants.HandlerState.ContinueExecution
|
||||||
|
else:
|
||||||
return Constants.HandlerState.PauseExecution
|
return Constants.HandlerState.PauseExecution
|
||||||
|
|
||||||
func _handle_command(command):
|
func _handle_command(command):
|
||||||
|
@ -84,16 +87,14 @@ func _handle_command(command):
|
||||||
return Constants.HandlerState.ContinueExecution
|
return Constants.HandlerState.ContinueExecution
|
||||||
|
|
||||||
func _handle_options(options):
|
func _handle_options(options):
|
||||||
call_deferred('emit_signal' ,'options', options)
|
call_deferred('emit_signal', 'options', options)
|
||||||
return Constants.HandlerState.PauseExecution
|
return Constants.HandlerState.PauseExecution
|
||||||
|
|
||||||
func _handle_dialogue_complete():
|
func _handle_dialogue_complete():
|
||||||
emit_signal('finished')
|
emit_signal('finished')
|
||||||
running = false
|
|
||||||
|
|
||||||
func _handle_node_start(node):
|
func _handle_node_start(node):
|
||||||
emit_signal('node_started', node)
|
emit_signal('node_started', node)
|
||||||
print('node started')
|
|
||||||
dialogue.resume()
|
dialogue.resume()
|
||||||
|
|
||||||
if !dialogue._visitedNodeCount.has(node):
|
if !dialogue._visitedNodeCount.has(node):
|
||||||
|
@ -101,28 +102,23 @@ func _handle_node_start(node):
|
||||||
else:
|
else:
|
||||||
dialogue._visitedNodeCount[node] += 1
|
dialogue._visitedNodeCount[node] += 1
|
||||||
|
|
||||||
print(dialogue._visitedNodeCount)
|
|
||||||
|
|
||||||
func _handle_node_complete(node):
|
func _handle_node_complete(node):
|
||||||
emit_signal('node_completed', node)
|
emit_signal('node_completed', node)
|
||||||
running = false
|
|
||||||
return Constants.HandlerState.ContinueExecution
|
return Constants.HandlerState.ContinueExecution
|
||||||
|
|
||||||
func select_option(id):
|
func select_option(id):
|
||||||
dialogue.get_vm().set_selected_option(id)
|
dialogue.get_vm().set_selected_option(id)
|
||||||
|
resume()
|
||||||
|
|
||||||
func pause():
|
func pause():
|
||||||
dialogue.call_deferred('pause')
|
dialogue.call_deferred('pause')
|
||||||
|
|
||||||
func start(node = start_node):
|
func start(node = start_node):
|
||||||
if running:
|
|
||||||
return
|
|
||||||
|
|
||||||
init_dialogue()
|
init_dialogue()
|
||||||
emit_signal('started')
|
emit_signal('started')
|
||||||
|
|
||||||
running = true
|
|
||||||
dialogue.set_node(node)
|
dialogue.set_node(node)
|
||||||
|
dialogue.start()
|
||||||
|
|
||||||
func resume():
|
func resume():
|
||||||
dialogue.call_deferred('resume')
|
dialogue.call_deferred('resume')
|
||||||
|
|
|
@ -72,6 +72,7 @@ static func compile_string(source: String, filename: String):
|
||||||
var value : String = result.get_string('value')
|
var value : String = result.get_string('value')
|
||||||
|
|
||||||
if field == 'title':
|
if field == 'title':
|
||||||
|
assert(not ' ' in value, 'No space allowed in title "%s", correct to "%s"' % [value, value.replace(' ','')])
|
||||||
title = value
|
title = value
|
||||||
|
|
||||||
if(line_number >= source_lines.size() || source_lines[line_number] == '---'):
|
if(line_number >= source_lines.size() || source_lines[line_number] == '---'):
|
||||||
|
@ -83,7 +84,7 @@ static func compile_string(source: String, filename: String):
|
||||||
#past header
|
#past header
|
||||||
var body_lines : PoolStringArray = []
|
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])
|
body_lines.append(source_lines[line_number])
|
||||||
line_number+=1
|
line_number+=1
|
||||||
|
|
||||||
|
@ -91,10 +92,9 @@ static func compile_string(source: String, filename: String):
|
||||||
|
|
||||||
body = body_lines.join('\n')
|
body = body_lines.join('\n')
|
||||||
var lexer = Lexer.new()
|
var lexer = Lexer.new()
|
||||||
|
var tokens = lexer.tokenize(body, title, filename)
|
||||||
|
|
||||||
var tokens : Array = lexer.tokenize(body)
|
var parser = Parser.new(tokens, title)
|
||||||
var parser = Parser.new(tokens)
|
|
||||||
|
|
||||||
var parser_node = parser.parse_node()
|
var parser_node = parser.parse_node()
|
||||||
|
|
||||||
parser_node.name = title
|
parser_node.name = title
|
||||||
|
@ -150,7 +150,7 @@ func compile_node(program, parsed_node):
|
||||||
|
|
||||||
if dangling_options:
|
if dangling_options:
|
||||||
emit(Constants.ByteCode.ShowOptions, node_compiled)
|
emit(Constants.ByteCode.ShowOptions, node_compiled)
|
||||||
emit(Constants.ByteCode.Run_node, node_compiled)
|
emit(Constants.ByteCode.RunNode, node_compiled)
|
||||||
else:
|
else:
|
||||||
emit(Constants.ByteCode.Stop, node_compiled)
|
emit(Constants.ByteCode.Stop, node_compiled)
|
||||||
|
|
||||||
|
@ -269,11 +269,15 @@ func generate_shortcut_group(node,shortcut_group):
|
||||||
if option.condition != null :
|
if option.condition != null :
|
||||||
endof_clause = register_label('conditional_%s'%option_count)
|
endof_clause = register_label('conditional_%s'%option_count)
|
||||||
generate_expression(node,option.condition)
|
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_line_id = '' #TODO: Add tag support
|
||||||
var label_string_id : String = register_string(option.label,node.node_name,
|
var label_string_id = register_string(
|
||||||
label_line_id,option.line_number,[])
|
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)])
|
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 :
|
if option.node != null :
|
||||||
generate_block(node,option.node.statements)
|
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
|
option_count+=1
|
||||||
|
|
||||||
#end of option group
|
#end of option group
|
||||||
|
@ -323,10 +327,10 @@ func generate_if(node,if_statement):
|
||||||
|
|
||||||
if clause.expression!=null:
|
if clause.expression!=null:
|
||||||
generate_expression(node,clause.expression)
|
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)
|
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:
|
if clause.expression!=null:
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(end_clause)])
|
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)])
|
emit(Constants.ByteCode.RunNode,node,[Program.Operand.new(destination)])
|
||||||
else :
|
else :
|
||||||
var line_iD : String = ''#tags not supported TODO: ADD TAG SUPPORT
|
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)])
|
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):
|
func generate_assignment(node,assignment):
|
||||||
# print('generating assign')
|
# print('generating assign')
|
||||||
#assignment
|
#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
|
#evaluate the expression to a value for the stack
|
||||||
generate_expression(node,assignment.value)
|
generate_expression(node,assignment.value)
|
||||||
else :
|
else :
|
||||||
#this is combined op
|
#this is combined op
|
||||||
#get value of var
|
#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
|
#evaluate the expression and push value to stack
|
||||||
generate_expression(node,assignment.value)
|
generate_expression(node,assignment.value)
|
||||||
|
@ -371,16 +375,16 @@ func generate_assignment(node,assignment):
|
||||||
#stack contains oldvalue and result
|
#stack contains oldvalue and result
|
||||||
|
|
||||||
match assignment.operation:
|
match assignment.operation:
|
||||||
Constants.TokenType.Add_assign:
|
Constants.TokenType.AddAssign:
|
||||||
emit(Constants.ByteCode.CallFunc,node,
|
emit(Constants.ByteCode.CallFunc,node,
|
||||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Add))])
|
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Add))])
|
||||||
Constants.TokenType.Minus_assign:
|
Constants.TokenType.MinusAssign:
|
||||||
emit(Constants.ByteCode.CallFunc,node,
|
emit(Constants.ByteCode.CallFunc,node,
|
||||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Minus))])
|
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.Minus))])
|
||||||
Constants.TokenType.Multiply_assign:
|
Constants.TokenType.MultiplyAssign:
|
||||||
emit(Constants.ByteCode.CallFunc,node,
|
emit(Constants.ByteCode.CallFunc,node,
|
||||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.MultiplyAssign))])
|
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.MultiplyAssign))])
|
||||||
Constants.TokenType.Divide_assign:
|
Constants.TokenType.DivideAssign:
|
||||||
emit(Constants.ByteCode.CallFunc,node,
|
emit(Constants.ByteCode.CallFunc,node,
|
||||||
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.DivideAssign))])
|
[Program.Operand.new(Constants.token_type_name(Constants.TokenType.DivideAssign))])
|
||||||
_:
|
_:
|
||||||
|
@ -388,7 +392,7 @@ func generate_assignment(node,assignment):
|
||||||
|
|
||||||
#stack contains destination value
|
#stack contains destination value
|
||||||
#store the top of the stack in variable
|
#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
|
#clean stack
|
||||||
emit(Constants.ByteCode.Pop,node)
|
emit(Constants.ByteCode.Pop,node)
|
||||||
|
@ -399,9 +403,9 @@ func generate_expression(node,expression):
|
||||||
# print('generating expression')
|
# print('generating expression')
|
||||||
#expression = value || func call
|
#expression = value || func call
|
||||||
match expression.type:
|
match expression.type:
|
||||||
Constants.Expression_type.Value:
|
Constants.ExpressionType.Value:
|
||||||
generate_value(node,expression.value)
|
generate_value(node,expression.value)
|
||||||
Constants.Expression_type.Function_call:
|
Constants.ExpressionType.FunctionCall:
|
||||||
#eval all parameters
|
#eval all parameters
|
||||||
for param in expression.params:
|
for param in expression.params:
|
||||||
generate_expression(node,param)
|
generate_expression(node,param)
|
||||||
|
@ -422,8 +426,8 @@ func generate_value(node,value):
|
||||||
Constants.ValueType.Number:
|
Constants.ValueType.Number:
|
||||||
emit(Constants.ByteCode.PushNumber,node,[Program.Operand.new(value.value.as_number())])
|
emit(Constants.ByteCode.PushNumber,node,[Program.Operand.new(value.value.as_number())])
|
||||||
Constants.ValueType.Str:
|
Constants.ValueType.Str:
|
||||||
var id : String = register_string(value.value.as_string(),
|
var id = register_string(value.value.as_string(),
|
||||||
node.node_name,'',value.line_number,[])
|
node.name,'',value.line_number,[])
|
||||||
emit(Constants.ByteCode.PushString,node,[Program.Operand.new(id)])
|
emit(Constants.ByteCode.PushString,node,[Program.Operand.new(id)])
|
||||||
Constants.ValueType.Boolean:
|
Constants.ValueType.Boolean:
|
||||||
emit(Constants.ByteCode.PushBool,node,[Program.Operand.new(value.value.as_bool())])
|
emit(Constants.ByteCode.PushBool,node,[Program.Operand.new(value.value.as_bool())])
|
||||||
|
|
|
@ -35,50 +35,50 @@ func _init():
|
||||||
|
|
||||||
func create_states():
|
func create_states():
|
||||||
var patterns : Dictionary = {}
|
var patterns : Dictionary = {}
|
||||||
patterns[Constants.TokenType.Text] = '.*'
|
patterns[Constants.TokenType.Text] = ['.*', 'any text']
|
||||||
|
|
||||||
patterns[Constants.TokenType.Number] = '\\-?[0-9]+(\\.[0-9+])?'
|
patterns[Constants.TokenType.Number] = ['\\-?[0-9]+(\\.[0-9+])?', 'any number']
|
||||||
patterns[Constants.TokenType.Str] = '\'([^\'\\\\]*(?:\\.[^\'\\\\]*)*)\''
|
patterns[Constants.TokenType.Str] = ['\'([^\'\\\\]*(?:\\.[^\'\\\\]*)*)\'', 'any text']
|
||||||
patterns[Constants.TokenType.TagMarker] = '\\#'
|
patterns[Constants.TokenType.TagMarker] = ['\\#', 'a tag #']
|
||||||
patterns[Constants.TokenType.LeftParen] = '\\('
|
patterns[Constants.TokenType.LeftParen] = ['\\(', 'left parenthesis (']
|
||||||
patterns[Constants.TokenType.RightParen] = '\\)'
|
patterns[Constants.TokenType.RightParen] = ['\\)', 'right parenthesis )']
|
||||||
patterns[Constants.TokenType.EqualTo] = '(==|is(?!\\w)|eq(?!\\w))'
|
patterns[Constants.TokenType.EqualTo] = ['(==|is(?!\\w)|eq(?!\\w))', '"=", "is" or "eq"']
|
||||||
patterns[Constants.TokenType.EqualToOrAssign] = '(=|to(?!\\w))'
|
patterns[Constants.TokenType.EqualToOrAssign] = ['(=|to(?!\\w))', 'equal to "=" or assign "="']
|
||||||
patterns[Constants.TokenType.NotEqualTo] = '(\\!=|neq(?!\\w))'
|
patterns[Constants.TokenType.NotEqualTo] = ['(\\!=|neq(?!\\w))', '"!=" or "neq"']
|
||||||
patterns[Constants.TokenType.GreaterThanOrEqualTo] = '(\\>=|gte(?!\\w))'
|
patterns[Constants.TokenType.GreaterThanOrEqualTo] = ['(\\>=|gte(?!\\w))', '">=" or "gte"']
|
||||||
patterns[Constants.TokenType.GreaterThan] = '(\\>|gt(?!\\w))'
|
patterns[Constants.TokenType.GreaterThan] = ['(\\>|gt(?!\\w))', '">" or "gt"']
|
||||||
patterns[Constants.TokenType.LessThanOrEqualTo] = '(\\<=|lte(?!\\w))'
|
patterns[Constants.TokenType.LessThanOrEqualTo] = ['(\\<=|lte(?!\\w))', '"<=" or "lte"']
|
||||||
patterns[Constants.TokenType.LessThan] = '(\\<|lt(?!\\w))'
|
patterns[Constants.TokenType.LessThan] = ['(\\<|lt(?!\\w))', '"<" or "lt"']
|
||||||
patterns[Constants.TokenType.AddAssign] = '\\+='
|
patterns[Constants.TokenType.AddAssign] = ['\\+=', '"+="']
|
||||||
patterns[Constants.TokenType.MinusAssign] = '\\-='
|
patterns[Constants.TokenType.MinusAssign] = ['\\-=', '"-="']
|
||||||
patterns[Constants.TokenType.MultiplyAssign] = '\\*='
|
patterns[Constants.TokenType.MultiplyAssign] = ['\\*=', '"*="']
|
||||||
patterns[Constants.TokenType.DivideAssign] = '\\/='
|
patterns[Constants.TokenType.DivideAssign] = ['\\/=', '"/="']
|
||||||
patterns[Constants.TokenType.Add] = '\\+'
|
patterns[Constants.TokenType.Add] = ['\\+', '"+"']
|
||||||
patterns[Constants.TokenType.Minus] = '\\-'
|
patterns[Constants.TokenType.Minus] = ['\\-', '"-"']
|
||||||
patterns[Constants.TokenType.Multiply] = '\\*'
|
patterns[Constants.TokenType.Multiply] = ['\\*', '"*"']
|
||||||
patterns[Constants.TokenType.Divide] = '\\/'
|
patterns[Constants.TokenType.Divide] = ['\\/', '"/"']
|
||||||
patterns[Constants.TokenType.Modulo] = '\\%'
|
patterns[Constants.TokenType.Modulo] = ['\\%', '"%"']
|
||||||
patterns[Constants.TokenType.And] = '(\\&\\&|and(?!\\w))'
|
patterns[Constants.TokenType.And] = ['(\\&\\&|and(?!\\w))', '"&&" or "and"']
|
||||||
patterns[Constants.TokenType.Or] = '(\\|\\||or(?!\\w))'
|
patterns[Constants.TokenType.Or] = ['(\\|\\||or(?!\\w))', '"||" or "or"']
|
||||||
patterns[Constants.TokenType.Xor] = '(\\^|xor(?!\\w))'
|
patterns[Constants.TokenType.Xor] = ['(\\^|xor(?!\\w))', '"^" or "xor"']
|
||||||
patterns[Constants.TokenType.Not] = '(\\!|not(?!\\w))'
|
patterns[Constants.TokenType.Not] = ['(\\!|not(?!\\w))', '"!" or "not"']
|
||||||
patterns[Constants.TokenType.Variable] = '\\$([A-Za-z0-9_\\.])+'
|
patterns[Constants.TokenType.Variable] = ['\\$([A-Za-z0-9_\\.])+', 'any variable']
|
||||||
patterns[Constants.TokenType.Comma] = '\\,'
|
patterns[Constants.TokenType.Comma] = ['\\,', '","']
|
||||||
patterns[Constants.TokenType.TrueToken] = 'true(?!\\w)'
|
patterns[Constants.TokenType.TrueToken] = ['true(?!\\w)', '"true"']
|
||||||
patterns[Constants.TokenType.FalseToken] = 'false(?!\\w)'
|
patterns[Constants.TokenType.FalseToken] = ['false(?!\\w)', '"false"']
|
||||||
patterns[Constants.TokenType.NullToken] = 'null(?!\\w)'
|
patterns[Constants.TokenType.NullToken] = ['null(?!\\w)', '"null"']
|
||||||
patterns[Constants.TokenType.BeginCommand] = '\\<\\<'
|
patterns[Constants.TokenType.BeginCommand] = ['\\<\\<', 'beginning of a command "<<"']
|
||||||
patterns[Constants.TokenType.EndCommand] = '\\>\\>'
|
patterns[Constants.TokenType.EndCommand] = ['\\>\\>', 'ending of a command ">>"']
|
||||||
patterns[Constants.TokenType.OptionStart] = '\\[\\['
|
patterns[Constants.TokenType.OptionStart] = ['\\[\\[', 'start of an option "[["']
|
||||||
patterns[Constants.TokenType.OptionEnd] = '\\]\\]'
|
patterns[Constants.TokenType.OptionEnd] = ['\\]\\]', 'end of an option "]]"']
|
||||||
patterns[Constants.TokenType.OptionDelimit] = '\\|'
|
patterns[Constants.TokenType.OptionDelimit] = ['\\|', 'middle of an option "|"']
|
||||||
patterns[Constants.TokenType.Identifier] = '[a-zA-Z0-9_:\\.]+'
|
patterns[Constants.TokenType.Identifier] = ['[a-zA-Z0-9_:\\.]+', 'any reference to another node']
|
||||||
patterns[Constants.TokenType.IfToken] = 'if(?!\\w)'
|
patterns[Constants.TokenType.IfToken] = ['if(?!\\w)', '"if"']
|
||||||
patterns[Constants.TokenType.ElseToken] = 'else(?!\\w)'
|
patterns[Constants.TokenType.ElseToken] = ['else(?!\\w)', '"else"']
|
||||||
patterns[Constants.TokenType.ElseIf] = 'elseif(?!\\w)'
|
patterns[Constants.TokenType.ElseIf] = ['elseif(?!\\w)', '"elseif"']
|
||||||
patterns[Constants.TokenType.EndIf] = 'endif(?!\\w)'
|
patterns[Constants.TokenType.EndIf] = ['endif(?!\\w)', '"endif"']
|
||||||
patterns[Constants.TokenType.Set] = 'set(?!\\w)'
|
patterns[Constants.TokenType.Set] = ['set(?!\\w)', '"set"']
|
||||||
patterns[Constants.TokenType.ShortcutOption] = '\\-\\>\\s*'
|
patterns[Constants.TokenType.ShortcutOption] = ['\\-\\>\\s*', '"->"']
|
||||||
|
|
||||||
#compound states
|
#compound states
|
||||||
var shortcut_option : String= SHORTCUT + DASH + OPTION
|
var shortcut_option : String= SHORTCUT + DASH + OPTION
|
||||||
|
@ -173,10 +173,7 @@ func create_states():
|
||||||
for stateKey in _states.keys():
|
for stateKey in _states.keys():
|
||||||
_states[stateKey].stateName = stateKey
|
_states[stateKey].stateName = stateKey
|
||||||
|
|
||||||
pass
|
func tokenize(text, title, filename):
|
||||||
|
|
||||||
func tokenize(text:String)->Array:
|
|
||||||
|
|
||||||
_indentStack.clear()
|
_indentStack.clear()
|
||||||
_indentStack.push_front(IntBoolPair.new(0,false))
|
_indentStack.push_front(IntBoolPair.new(0,false))
|
||||||
_shouldTrackIndent = false
|
_shouldTrackIndent = false
|
||||||
|
@ -191,17 +188,20 @@ func tokenize(text:String)->Array:
|
||||||
var line_number : int = 1
|
var line_number : int = 1
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
tokens+=tokenize_line(line,line_number)
|
tokens += tokenize_line(line, line_number, title, filename)
|
||||||
line_number+=1
|
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)
|
tokens.append(endOfInput)
|
||||||
|
|
||||||
# print(tokens)
|
|
||||||
|
|
||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
func tokenize_line(line:String, line_number : int)->Array:
|
func tokenize_line(line, line_number, title, filename):
|
||||||
var tokenStack : Array = []
|
var tokenStack : Array = []
|
||||||
|
|
||||||
var freshLine = line.replace('\t',' ').replace('\r','')
|
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
|
#we add an indenation token to record indent level
|
||||||
_indentStack.push_front(IntBoolPair.new(indentation,true))
|
_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,'']
|
indent.value = '%*s' % [indentation - prevIndentation.key,'']
|
||||||
|
|
||||||
_shouldTrackIndent = false
|
_shouldTrackIndent = false
|
||||||
|
@ -246,7 +252,7 @@ func tokenize_line(line:String, line_number : int)->Array:
|
||||||
var matched : bool = false
|
var matched : bool = false
|
||||||
|
|
||||||
for rule in _currentState.rules:
|
for rule in _currentState.rules:
|
||||||
var found : RegExMatch = rule.regex.search(freshLine, column)
|
var found = rule.regex.search(freshLine, column)
|
||||||
|
|
||||||
if !found:
|
if !found:
|
||||||
continue
|
continue
|
||||||
|
@ -273,9 +279,9 @@ func tokenize_line(line:String, line_number : int)->Array:
|
||||||
#
|
#
|
||||||
|
|
||||||
column = startIndex
|
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:
|
else:
|
||||||
tokenText = found.get_string()
|
tokenText = found.get_string()
|
||||||
|
@ -284,36 +290,51 @@ func tokenize_line(line:String, line_number : int)->Array:
|
||||||
|
|
||||||
#pre-proccess string
|
#pre-proccess string
|
||||||
if rule.tokenType == Constants.TokenType.Str:
|
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('\\\\', '\\')
|
||||||
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
|
token.delimitsText = rule.delimitsText
|
||||||
|
|
||||||
tokenStack.push_front(token)
|
tokenStack.push_front(token)
|
||||||
|
|
||||||
if rule.enterState != null && rule.enterState.length() > 0:
|
if rule.enterState != null and rule.enterState.length() > 0:
|
||||||
|
if not _states.has(rule.enterState):
|
||||||
if !_states.has(rule.enterState):
|
printerr('State[%s] not known - line(%s) col(%s)' % [rule.enterState, line_number, column])
|
||||||
printerr('State[%s] not known - line(%s) col(%s)'%[rule.enterState,line_number,column])
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
enter_state(_states[rule.enterState])
|
enter_state(_states[rule.enterState])
|
||||||
|
|
||||||
if _shouldTrackIndent:
|
if _shouldTrackIndent:
|
||||||
if _indentStack.front().key < indentation:
|
if _indentStack.front().key < indentation:
|
||||||
_indentStack.append(IntBoolPair.new(indentation,false))
|
_indentStack.append(IntBoolPair.new(indentation, false))
|
||||||
|
|
||||||
matched = true
|
matched = true
|
||||||
break
|
break
|
||||||
|
|
||||||
if !matched:
|
if not matched:
|
||||||
# TODO: Send out some helpful messages
|
var rules = []
|
||||||
printerr('expectedTokens [%s] - line(%s) col(%s)'%['refineErrors.Lexer.tokenize_line',line_number,column])
|
for rule in _currentState.rules:
|
||||||
return []
|
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:
|
if lastWhiteSpace:
|
||||||
column += lastWhiteSpace.get_string().length()
|
column += lastWhiteSpace.get_string().length()
|
||||||
|
|
||||||
|
@ -339,20 +360,22 @@ func enter_state(state:LexerState):
|
||||||
_shouldTrackIndent = true
|
_shouldTrackIndent = true
|
||||||
|
|
||||||
class Token:
|
class Token:
|
||||||
var type : int
|
var type = -1
|
||||||
var value : String
|
var value = ''
|
||||||
|
|
||||||
var line_number : int
|
var filename = ''
|
||||||
var column : int
|
var line_number = -1
|
||||||
var text : String
|
var column = -1
|
||||||
|
var text = ''
|
||||||
|
|
||||||
var delimitsText : bool= false
|
var delimitsText = false
|
||||||
var paramCount : int
|
var paramCount = -1
|
||||||
var lexerState : String
|
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.type = type
|
||||||
self.lexerState = state.stateName
|
self.lexerState = state.stateName
|
||||||
|
self.filename = filename
|
||||||
self.line_number = line_number
|
self.line_number = line_number
|
||||||
self.column = column
|
self.column = column
|
||||||
self.value = value
|
self.value = value
|
||||||
|
@ -360,7 +383,6 @@ class Token:
|
||||||
func _to_string():
|
func _to_string():
|
||||||
return '%s (%s) at %s:%s (state: %s)' % [Constants.token_type_name(type),value,line_number,column,lexerState]
|
return '%s (%s) at %s:%s (state: %s)' % [Constants.token_type_name(type),value,line_number,column,lexerState]
|
||||||
|
|
||||||
|
|
||||||
class LexerState:
|
class LexerState:
|
||||||
|
|
||||||
var stateName : String
|
var stateName : String
|
||||||
|
@ -372,9 +394,9 @@ class LexerState:
|
||||||
self.patterns = patterns
|
self.patterns = patterns
|
||||||
|
|
||||||
func add_transition(type : int, state : String = '',delimitText : bool = false)->Rule:
|
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)
|
# 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)
|
rules.append(rule)
|
||||||
return rule
|
return rule
|
||||||
|
|
||||||
|
@ -409,16 +431,18 @@ class Rule:
|
||||||
var tokenType : int
|
var tokenType : int
|
||||||
var isTextRule : bool
|
var isTextRule : bool
|
||||||
var delimitsText : 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.tokenType = type
|
||||||
self.regex = RegEx.new()
|
self.regex = RegEx.new()
|
||||||
self.regex.compile(regex)
|
self.regex.compile(regex)
|
||||||
|
self.human_readable_identifier = human_readable_identifier
|
||||||
self.enterState = enterState
|
self.enterState = enterState
|
||||||
self.delimitsText = delimitsText
|
self.delimitsText = delimitsText
|
||||||
|
|
||||||
func _to_string():
|
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:
|
class IntBoolPair:
|
||||||
var key : int
|
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')
|
const Lexer = preload('res://addons/Wol/core/compiler/lexer.gd')
|
||||||
|
|
||||||
var _tokens = []
|
var _tokens = []
|
||||||
|
var title = ''
|
||||||
|
|
||||||
func _init(tokens):
|
func _init(tokens, title):
|
||||||
self._tokens = tokens
|
self._tokens = tokens
|
||||||
|
self.title = title
|
||||||
|
|
||||||
enum Associativity {
|
enum Associativity {
|
||||||
Left,
|
Left,
|
||||||
|
@ -37,7 +39,7 @@ func expect_symbol(token_types = []):
|
||||||
|
|
||||||
if token_types.size() == 0:
|
if token_types.size() == 0:
|
||||||
if token.type == Constants.TokenType.EndOfInput:
|
if token.type == Constants.TokenType.EndOfInput:
|
||||||
printerr('Unexpected end of input.')
|
assert(false, 'Unexpected end of input')
|
||||||
return null
|
return null
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
@ -45,8 +47,29 @@ func expect_symbol(token_types = []):
|
||||||
if token.type == type:
|
if token.type == type:
|
||||||
return token
|
return token
|
||||||
|
|
||||||
printerr('Unexpexted token: expected[ %s ] but got [ %s ]' % token_types + [token.type])
|
var token_names = []
|
||||||
return
|
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):
|
static func tab(indent_level, input, newline = true):
|
||||||
return '%*s| %s%s' % [indent_level * 2, '', input, '' if not newline else '\n']
|
return '%*s| %s%s' % [indent_level * 2, '', input, '' if not newline else '\n']
|
||||||
|
@ -55,12 +78,15 @@ func tokens():
|
||||||
return _tokens
|
return _tokens
|
||||||
|
|
||||||
class ParseNode:
|
class ParseNode:
|
||||||
|
var name = ''
|
||||||
|
|
||||||
var parent
|
var parent
|
||||||
var line_number = -1
|
var line_number = -1
|
||||||
var tags = []
|
var tags = []
|
||||||
|
|
||||||
func _init(parent, parser):
|
func _init(parent, parser):
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
var tokens = parser.tokens() as Array
|
var tokens = parser.tokens() as Array
|
||||||
if tokens.size() > 0:
|
if tokens.size() > 0:
|
||||||
line_number = tokens.front().line_number
|
line_number = tokens.front().line_number
|
||||||
|
@ -77,7 +103,7 @@ class ParseNode:
|
||||||
func get_node_parent():
|
func get_node_parent():
|
||||||
var node = self
|
var node = self
|
||||||
while node != null:
|
while node != null:
|
||||||
if node.has_method('wol_node'):
|
if node is ParseNode:
|
||||||
return node as WolNode
|
return node as WolNode
|
||||||
node = node.parent
|
node = node.parent
|
||||||
return null
|
return null
|
||||||
|
@ -90,7 +116,6 @@ class ParseNode:
|
||||||
|
|
||||||
#this is a Wol Node - contains all the text
|
#this is a Wol Node - contains all the text
|
||||||
class WolNode extends ParseNode:
|
class WolNode extends ParseNode:
|
||||||
var name = ''
|
|
||||||
var source = ''
|
var source = ''
|
||||||
|
|
||||||
var editor_node_tags = []
|
var editor_node_tags = []
|
||||||
|
@ -140,7 +165,7 @@ class Statement extends ParseNode:
|
||||||
|
|
||||||
elif Assignment.can_parse(parser):
|
elif Assignment.can_parse(parser):
|
||||||
assignment = Assignment.new(self, parser)
|
assignment = Assignment.new(self, parser)
|
||||||
type = Type.Assignment_statement
|
type = Type.AssignmentStatement
|
||||||
|
|
||||||
elif ShortcutOptionGroup.can_parse(parser):
|
elif ShortcutOptionGroup.can_parse(parser):
|
||||||
shortcut_option_group = ShortcutOptionGroup.new(self, parser)
|
shortcut_option_group = ShortcutOptionGroup.new(self, parser)
|
||||||
|
@ -175,7 +200,7 @@ class Statement extends ParseNode:
|
||||||
info.append(block.tree_string(indent_level))
|
info.append(block.tree_string(indent_level))
|
||||||
Type.IfStatement:
|
Type.IfStatement:
|
||||||
info.append(if_statement.tree_string(indent_level))
|
info.append(if_statement.tree_string(indent_level))
|
||||||
Type.Assignment_statement:
|
Type.AssignmentStatement:
|
||||||
info.append(assignment.tree_string(indent_level))
|
info.append(assignment.tree_string(indent_level))
|
||||||
Type.OptionStatement:
|
Type.OptionStatement:
|
||||||
info.append(option_statement.tree_string(indent_level))
|
info.append(option_statement.tree_string(indent_level))
|
||||||
|
@ -194,7 +219,7 @@ class CustomCommand extends ParseNode:
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
Expression,
|
Expression,
|
||||||
Client_command
|
ClientCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = -1
|
var type = -1
|
||||||
|
@ -215,21 +240,21 @@ class CustomCommand extends ParseNode:
|
||||||
#if first token is identifier and second is leftt parenthesis
|
#if first token is identifier and second is leftt parenthesis
|
||||||
#evaluate as function
|
#evaluate as function
|
||||||
if (command_tokens.size() > 1 && command_tokens[0].type == Constants.TokenType.Identifier
|
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 p = get_script().new(command_tokens, parser.library)
|
||||||
var expression = Expression_node.parse(self, p)
|
var expression = ExpressionNode.parse(self, p)
|
||||||
type = Type.Expression
|
type = Type.Expression
|
||||||
self.expression = expression
|
self.expression = expression
|
||||||
else:
|
else:
|
||||||
#otherwise evaluuate command
|
#otherwise evaluuate command
|
||||||
type = Type.Client_command
|
type = Type.ClientCommand
|
||||||
self.client_command = command_tokens[0].value
|
self.client_command = command_tokens[0].value
|
||||||
|
|
||||||
func tree_string(indent_level):
|
func tree_string(indent_level):
|
||||||
match type:
|
match type:
|
||||||
Type.Expression:
|
Type.Expression:
|
||||||
return tab(indent_level,'Expression: %s'% expression.tree_string(indent_level+1))
|
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 tab(indent_level,'Command: %s' % client_command)
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
@ -246,10 +271,10 @@ class ShortcutOptionGroup extends ParseNode:
|
||||||
# expect one otherwise invalid
|
# expect one otherwise invalid
|
||||||
|
|
||||||
var index = 1
|
var index = 1
|
||||||
options.append(Short_cut_option.new(index, self, parser))
|
options.append(ShortCutOption.new(index, self, parser))
|
||||||
index += 1
|
index += 1
|
||||||
while parser.next_symbol_is([Constants.TokenType.ShortcutOption]):
|
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
|
index += 1
|
||||||
|
|
||||||
func tree_string(indent_level):
|
func tree_string(indent_level):
|
||||||
|
@ -267,7 +292,7 @@ class ShortcutOptionGroup extends ParseNode:
|
||||||
static func can_parse(parser):
|
static func can_parse(parser):
|
||||||
return parser.next_symbol_is([Constants.TokenType.ShortcutOption])
|
return parser.next_symbol_is([Constants.TokenType.ShortcutOption])
|
||||||
|
|
||||||
class Short_cut_option extends ParseNode:
|
class ShortCutOption extends ParseNode:
|
||||||
var label = ''
|
var label = ''
|
||||||
var condition
|
var condition
|
||||||
var node
|
var node
|
||||||
|
@ -285,7 +310,7 @@ class Short_cut_option extends ParseNode:
|
||||||
if parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.IfToken]):
|
if parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.IfToken]):
|
||||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||||
parser.expect_symbol([Constants.TokenType.IfToken])
|
parser.expect_symbol([Constants.TokenType.IfToken])
|
||||||
condition = Expression_node.parse(self, parser)
|
condition = ExpressionNode.parse(self, parser)
|
||||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||||
|
|
||||||
elif parser.next_symbol_is([Constants.TokenType.TagMarker]):
|
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]):
|
if parser.next_symbol_is([Constants.TokenType.Indent]):
|
||||||
parser.expect_symbol([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])
|
parser.expect_symbol([Constants.TokenType.Dedent])
|
||||||
|
|
||||||
|
|
||||||
|
@ -359,7 +384,6 @@ class OptionStatement extends ParseNode:
|
||||||
var label = ''
|
var label = ''
|
||||||
|
|
||||||
func _init(parent, parser).(parent, parser):
|
func _init(parent, parser).(parent, parser):
|
||||||
|
|
||||||
var strings = []
|
var strings = []
|
||||||
|
|
||||||
# NOTE: parse [[LABEL
|
# NOTE: parse [[LABEL
|
||||||
|
@ -397,14 +421,14 @@ class IfStatement extends ParseNode:
|
||||||
|
|
||||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||||
parser.expect_symbol([Constants.TokenType.IfToken])
|
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])
|
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||||
|
|
||||||
#read statements until 'endif' or 'else' or 'else if'
|
#read statements until 'endif' or 'else' or 'else if'
|
||||||
var statements = []#statement
|
var statements = []#statement
|
||||||
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.End_if]) \
|
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.EndIf]) \
|
||||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_token]) \
|
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseToken]) \
|
||||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_if]):
|
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseIf]):
|
||||||
|
|
||||||
statements.append(Statement.new(self, parser))
|
statements.append(Statement.new(self, parser))
|
||||||
|
|
||||||
|
@ -416,20 +440,20 @@ class IfStatement extends ParseNode:
|
||||||
clauses.append(prime)
|
clauses.append(prime)
|
||||||
|
|
||||||
#handle all else if
|
#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()
|
var clause_elif = Clause.new()
|
||||||
|
|
||||||
#parse condition syntax
|
#parse condition syntax
|
||||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||||
parser.expect_symbol([Constants.TokenType.Else_if])
|
parser.expect_symbol([Constants.TokenType.ElseIf])
|
||||||
clause_elif.expression = Expression_node.parse(self, parser)
|
clause_elif.expression = ExpressionNode.parse(self, parser)
|
||||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||||
|
|
||||||
|
|
||||||
var elif_statements = []#statement
|
var elif_statements = []#statement
|
||||||
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.End_if]) \
|
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.EndIf]) \
|
||||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_token]) \
|
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseToken]) \
|
||||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_if]):
|
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseIf]):
|
||||||
|
|
||||||
elif_statements.append(Statement.new(self, parser))
|
elif_statements.append(Statement.new(self, parser))
|
||||||
|
|
||||||
|
@ -442,17 +466,17 @@ class IfStatement extends ParseNode:
|
||||||
|
|
||||||
#handle else if exists
|
#handle else if exists
|
||||||
if (parser.next_symbols_are([Constants.TokenType.BeginCommand,
|
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>>
|
#expect no expression - just <<else>>
|
||||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
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])
|
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||||
|
|
||||||
#parse until hit endif
|
#parse until hit endif
|
||||||
var clause_else = Clause.new()
|
var clause_else = Clause.new()
|
||||||
var el_statements = []#statement
|
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))
|
el_statements.append(Statement.new(self, parser))
|
||||||
|
|
||||||
clause_else.statements = el_statements
|
clause_else.statements = el_statements
|
||||||
|
@ -464,7 +488,7 @@ class IfStatement extends ParseNode:
|
||||||
|
|
||||||
#finish
|
#finish
|
||||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
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])
|
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])
|
return parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.IfToken])
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Value_node extends ParseNode:
|
class ValueNode extends ParseNode:
|
||||||
const Value = preload('res://addons/Wol/core/value.gd')
|
const Value = preload('res://addons/Wol/core/value.gd')
|
||||||
const Lexer = preload('res://addons/Wol/core/compiler/lexer.gd')
|
const Lexer = preload('res://addons/Wol/core/compiler/lexer.gd')
|
||||||
var value
|
var value
|
||||||
|
@ -508,15 +532,15 @@ class Value_node extends ParseNode:
|
||||||
value = Value.new(float(token.value))
|
value = Value.new(float(token.value))
|
||||||
Constants.TokenType.Str:
|
Constants.TokenType.Str:
|
||||||
value = Value.new(token.value)
|
value = Value.new(token.value)
|
||||||
Constants.TokenType.False_token:
|
Constants.TokenType.FalseToken:
|
||||||
value = Value.new(false)
|
value = Value.new(false)
|
||||||
Constants.TokenType.True_token:
|
Constants.TokenType.TrueToken:
|
||||||
value = Value.new(true)
|
value = Value.new(true)
|
||||||
Constants.TokenType.Variable:
|
Constants.TokenType.Variable:
|
||||||
value = Value.new(null)
|
value = Value.new(null)
|
||||||
value.type = Constants.Value_type.Variable
|
value.type = Constants.ValueType.Variable
|
||||||
value.variable = token.value
|
value.variable = token.value
|
||||||
Constants.TokenType.Null_token:
|
Constants.TokenType.NullToken:
|
||||||
value = Value.new(null)
|
value = Value.new(null)
|
||||||
_:
|
_:
|
||||||
printerr('%s, Invalid token type' % token.name)
|
printerr('%s, Invalid token type' % token.name)
|
||||||
|
@ -529,33 +553,32 @@ class Value_node extends ParseNode:
|
||||||
# math (1 + 2 - 5 * 3 / 10 % 2)
|
# math (1 + 2 - 5 * 3 / 10 % 2)
|
||||||
# Identifiers
|
# Identifiers
|
||||||
# Values
|
# Values
|
||||||
class Expression_node extends ParseNode:
|
class ExpressionNode extends ParseNode:
|
||||||
var type
|
var type
|
||||||
var value
|
var value
|
||||||
var function
|
var function
|
||||||
var params = []#Expression_node
|
var params = []#ExpressionNode
|
||||||
|
|
||||||
func _init(parent, parser, value, function = '', params = []).(parent, parser):
|
func _init(parent, parser, value, function = '', params = []).(parent, parser):
|
||||||
|
|
||||||
#no function - means value
|
#no function - means value
|
||||||
if value != null:
|
if value != null:
|
||||||
self.type = Constants.Expression_type.Value
|
self.type = Constants.ExpressionType.Value
|
||||||
self.value = value
|
self.value = value
|
||||||
else:#function
|
else:#function
|
||||||
|
|
||||||
self.type = Constants.Expression_type.Function_call
|
self.type = Constants.ExpressionType.FunctionCall
|
||||||
self.function = function
|
self.function = function
|
||||||
self.params = params
|
self.params = params
|
||||||
|
|
||||||
func tree_string(indent_level):
|
func tree_string(indent_level):
|
||||||
var info = []
|
var info = []
|
||||||
match type:
|
match type:
|
||||||
Constants.Expression_type.Value:
|
Constants.ExpressionType.Value:
|
||||||
return value.tree_string(indent_level)
|
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()]))
|
info.append(tab(indent_level,'Func[%s - params(%s)]:{'%[function, params.size()]))
|
||||||
for param in params:
|
for param in params:
|
||||||
#print('----> %s param_size:%s'%[(function) , params.size()])
|
|
||||||
info.append(param.tree_string(indent_level+1))
|
info.append(param.tree_string(indent_level+1))
|
||||||
info.append(tab(indent_level,'}'))
|
info.append(tab(indent_level,'}'))
|
||||||
|
|
||||||
|
@ -575,13 +598,13 @@ class Expression_node extends ParseNode:
|
||||||
Constants.TokenType.Number,
|
Constants.TokenType.Number,
|
||||||
Constants.TokenType.Variable,
|
Constants.TokenType.Variable,
|
||||||
Constants.TokenType.Str,
|
Constants.TokenType.Str,
|
||||||
Constants.TokenType.Left_paren,
|
Constants.TokenType.LeftParen,
|
||||||
Constants.TokenType.Right_paren,
|
Constants.TokenType.RightParen,
|
||||||
Constants.TokenType.Identifier,
|
Constants.TokenType.Identifier,
|
||||||
Constants.TokenType.Comma,
|
Constants.TokenType.Comma,
|
||||||
Constants.TokenType.True_token,
|
Constants.TokenType.TrueToken,
|
||||||
Constants.TokenType.False_token,
|
Constants.TokenType.FalseToken,
|
||||||
Constants.TokenType.Null_token
|
Constants.TokenType.NullToken
|
||||||
]
|
]
|
||||||
valid_types += Operator.op_types()
|
valid_types += Operator.op_types()
|
||||||
valid_types.invert()
|
valid_types.invert()
|
||||||
|
@ -595,9 +618,9 @@ class Expression_node extends ParseNode:
|
||||||
if next.type == Constants.TokenType.Variable \
|
if next.type == Constants.TokenType.Variable \
|
||||||
or next.type == Constants.TokenType.Number \
|
or next.type == Constants.TokenType.Number \
|
||||||
or next.type == Constants.TokenType.Str \
|
or next.type == Constants.TokenType.Str \
|
||||||
or next.type == Constants.TokenType.False_token \
|
or next.type == Constants.TokenType.FalseToken \
|
||||||
or next.type == Constants.TokenType.True_token \
|
or next.type == Constants.TokenType.TrueToken \
|
||||||
or next.type == Constants.TokenType.Null_token:
|
or next.type == Constants.TokenType.NullToken:
|
||||||
|
|
||||||
#output primitives
|
#output primitives
|
||||||
rpn.append(next)
|
rpn.append(next)
|
||||||
|
@ -606,12 +629,12 @@ class Expression_node extends ParseNode:
|
||||||
func_stack.push_back(next)
|
func_stack.push_back(next)
|
||||||
|
|
||||||
#next token is parent - left
|
#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)
|
op_stack.push_back(next)
|
||||||
|
|
||||||
elif next.type == Constants.TokenType.Comma:
|
elif next.type == Constants.TokenType.Comma:
|
||||||
#resolve sub expression before moving on
|
#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()
|
var p = op_stack.pop_back()
|
||||||
if p == null:
|
if p == null:
|
||||||
printerr('unbalanced parenthesis %s ' % next.name)
|
printerr('unbalanced parenthesis %s ' % next.name)
|
||||||
|
@ -621,7 +644,7 @@ class Expression_node extends ParseNode:
|
||||||
|
|
||||||
#next token in op_stack left paren
|
#next token in op_stack left paren
|
||||||
# next parser token not allowed to be right paren or comma
|
# 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]):
|
Constants.TokenType.Comma]):
|
||||||
printerr('Expected Expression : %s' % parser.tokens().front().name)
|
printerr('Expected Expression : %s' % parser.tokens().front().name)
|
||||||
|
|
||||||
|
@ -643,34 +666,33 @@ class Expression_node extends ParseNode:
|
||||||
|
|
||||||
if next.type == Constants.TokenType.Minus:
|
if next.type == Constants.TokenType.Minus:
|
||||||
if last == null \
|
if last == null \
|
||||||
or last.type == Constants.TokenType.Left_paren \
|
or last.type == Constants.TokenType.LeftParen \
|
||||||
or Operator.is_op(last.type):
|
or Operator.is_op(last.type):
|
||||||
#unary minus
|
#unary minus
|
||||||
next.type = Constants.TokenType.Unary_minus
|
next.type = Constants.TokenType.UnaryMinus
|
||||||
|
|
||||||
#cannot assign inside expression
|
#cannot assign inside expression
|
||||||
# x = a is the same as x == a
|
# x = a is the same as x == a
|
||||||
if next.type == Constants.TokenType.EqualToOrAssign:
|
if next.type == Constants.TokenType.EqualToOrAssign:
|
||||||
next.type = Constants.TokenType.EqualTo
|
next.type = Constants.TokenType.EqualTo
|
||||||
|
|
||||||
|
|
||||||
#operator precedence
|
#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()
|
var op = op_stack.pop_back()
|
||||||
rpn.append(op)
|
rpn.append(op)
|
||||||
|
|
||||||
op_stack.push_back(next)
|
op_stack.push_back(next)
|
||||||
|
|
||||||
elif next.type == Constants.TokenType.Left_paren:
|
elif next.type == Constants.TokenType.LeftParen:
|
||||||
#entered parenthesis sub expression
|
#entered parenthesis sub expression
|
||||||
op_stack.push_back(next)
|
op_stack.push_back(next)
|
||||||
elif next.type == Constants.TokenType.Right_paren:
|
elif next.type == Constants.TokenType.RightParen:
|
||||||
#leaving sub expression
|
#leaving sub expression
|
||||||
# resolve order of operations
|
# 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())
|
rpn.append(op_stack.pop_back())
|
||||||
if op_stack.back() == null:
|
if op_stack.back() == null:
|
||||||
printerr('Unbalanced parenthasis #Right_paren. Parser.Expression_node')
|
printerr('Unbalanced parenthasis #RightParen. Parser.ExpressionNode')
|
||||||
|
|
||||||
|
|
||||||
op_stack.pop_back()
|
op_stack.pop_back()
|
||||||
|
@ -679,7 +701,7 @@ class Expression_node extends ParseNode:
|
||||||
#last token == left paren this == no params
|
#last token == left paren this == no params
|
||||||
#else
|
#else
|
||||||
#we have more than 1 param
|
#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
|
func_stack.back().param_count+=1
|
||||||
|
|
||||||
rpn.append(op_stack.pop_back())
|
rpn.append(op_stack.pop_back())
|
||||||
|
@ -698,10 +720,9 @@ class Expression_node extends ParseNode:
|
||||||
|
|
||||||
#build expression tree
|
#build expression tree
|
||||||
var first = rpn.front()
|
var first = rpn.front()
|
||||||
var eval_stack = []#Expression_node
|
var eval_stack = []#ExpressionNode
|
||||||
|
|
||||||
while rpn.size() > 0:
|
while rpn.size() > 0:
|
||||||
|
|
||||||
var next = rpn.pop_front()
|
var next = rpn.pop_front()
|
||||||
if Operator.is_op(next.type):
|
if Operator.is_op(next.type):
|
||||||
#operation
|
#operation
|
||||||
|
@ -710,7 +731,7 @@ class Expression_node extends ParseNode:
|
||||||
if eval_stack.size() < info.arguments:
|
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])
|
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):
|
for i in range(info.arguments):
|
||||||
params.append(eval_stack.pop_back())
|
params.append(eval_stack.pop_back())
|
||||||
|
|
||||||
|
@ -718,7 +739,7 @@ class Expression_node extends ParseNode:
|
||||||
|
|
||||||
var function = get_func_name(next.type)
|
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)
|
eval_stack.append(expression)
|
||||||
|
|
||||||
|
@ -727,19 +748,19 @@ class Expression_node extends ParseNode:
|
||||||
|
|
||||||
var function = next.value
|
var function = next.value
|
||||||
|
|
||||||
var params = []#Expression_node
|
var params = []#ExpressionNode
|
||||||
for i in range(next.param_count):
|
for i in range(next.param_count):
|
||||||
|
|
||||||
params.append(eval_stack.pop_back())
|
params.append(eval_stack.pop_back())
|
||||||
|
|
||||||
params.invert()
|
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)
|
eval_stack.append(expression)
|
||||||
else: #raw value
|
else: #raw value
|
||||||
var value = Value_node.new(parent, parser, next)
|
var value = ValueNode.new(parent, parser, next)
|
||||||
var expression = Expression_node.new(parent, parser, value)
|
var expression = ExpressionNode.new(parent, parser, value)
|
||||||
eval_stack.append(expression)
|
eval_stack.append(expression)
|
||||||
|
|
||||||
|
|
||||||
|
@ -796,7 +817,7 @@ class Assignment extends ParseNode:
|
||||||
parser.expect_symbol([Constants.TokenType.Set])
|
parser.expect_symbol([Constants.TokenType.Set])
|
||||||
destination = parser.expect_symbol([Constants.TokenType.Variable]).value
|
destination = parser.expect_symbol([Constants.TokenType.Variable]).value
|
||||||
operation = parser.expect_symbol(Assignment.valid_ops()).type
|
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])
|
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||||
|
|
||||||
func tree_string(indent_level):
|
func tree_string(indent_level):
|
||||||
|
@ -817,10 +838,10 @@ class Assignment extends ParseNode:
|
||||||
static func valid_ops():
|
static func valid_ops():
|
||||||
return [
|
return [
|
||||||
Constants.TokenType.EqualToOrAssign,
|
Constants.TokenType.EqualToOrAssign,
|
||||||
Constants.TokenType.Add_assign,
|
Constants.TokenType.AddAssign,
|
||||||
Constants.TokenType.Minus_assign,
|
Constants.TokenType.MinusAssign,
|
||||||
Constants.TokenType.Divide_assign,
|
Constants.TokenType.DivideAssign,
|
||||||
Constants.TokenType.Multiply_assign
|
Constants.TokenType.MultiplyAssign
|
||||||
]
|
]
|
||||||
|
|
||||||
class Operator extends ParseNode:
|
class Operator extends ParseNode:
|
||||||
|
@ -848,22 +869,22 @@ class Operator extends ParseNode:
|
||||||
var TokenType = Constants.TokenType
|
var TokenType = Constants.TokenType
|
||||||
|
|
||||||
match op:
|
match op:
|
||||||
TokenType.Not, TokenType.Unary_minus:
|
TokenType.Not, TokenType.UnaryMinus:
|
||||||
return Operator_info.new(Associativity.Right, 30, 1)
|
return OperatorInfo.new(Associativity.Right, 30, 1)
|
||||||
TokenType.Multiply, TokenType.Divide, TokenType.Modulo:
|
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:
|
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:
|
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:
|
TokenType.EqualTo, TokenType.EqualToOrAssign, TokenType.NotEqualTo:
|
||||||
return Operator_info.new(Associativity.Left, 5, 2)
|
return OperatorInfo.new(Associativity.Left, 5, 2)
|
||||||
TokenType.And:
|
TokenType.And:
|
||||||
return Operator_info.new(Associativity.Left, 4, 2)
|
return OperatorInfo.new(Associativity.Left, 4, 2)
|
||||||
TokenType.Or:
|
TokenType.Or:
|
||||||
return Operator_info.new(Associativity.Left, 3, 2)
|
return OperatorInfo.new(Associativity.Left, 3, 2)
|
||||||
TokenType.Xor:
|
TokenType.Xor:
|
||||||
return Operator_info.new(Associativity.Left, 2, 2)
|
return OperatorInfo.new(Associativity.Left, 2, 2)
|
||||||
_:
|
_:
|
||||||
printerr('Unknown operator: %s' % op.name)
|
printerr('Unknown operator: %s' % op.name)
|
||||||
return null
|
return null
|
||||||
|
@ -874,7 +895,7 @@ class Operator extends ParseNode:
|
||||||
static func op_types():
|
static func op_types():
|
||||||
return [
|
return [
|
||||||
Constants.TokenType.Not,
|
Constants.TokenType.Not,
|
||||||
Constants.TokenType.Unary_minus,
|
Constants.TokenType.UnaryMinus,
|
||||||
|
|
||||||
Constants.TokenType.Add,
|
Constants.TokenType.Add,
|
||||||
Constants.TokenType.Minus,
|
Constants.TokenType.Minus,
|
||||||
|
@ -897,7 +918,7 @@ class Operator extends ParseNode:
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class Operator_info:
|
class OperatorInfo:
|
||||||
var associativity
|
var associativity
|
||||||
var precedence = -1
|
var precedence = -1
|
||||||
var arguments = -1
|
var arguments = -1
|
||||||
|
|
|
@ -198,3 +198,9 @@ static func bytecode_name(bytecode):
|
||||||
'Stop',
|
'Stop',
|
||||||
'RunNode'
|
'RunNode'
|
||||||
][bytecode]
|
][bytecode]
|
||||||
|
|
||||||
|
static func token_name(type):
|
||||||
|
for key in TokenType.keys():
|
||||||
|
if TokenType[key] == type:
|
||||||
|
return key
|
||||||
|
return ''
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
const DEFAULT_START = 'Start'
|
const DEFAULT_START = 'Start'
|
||||||
const FMF_PLACEHOLDE = '<VALUE PLACEHOLDER>'
|
|
||||||
|
|
||||||
const Constants = preload('res://addons/Wol/core/constants.gd')
|
const Constants = preload('res://addons/Wol/core/constants.gd')
|
||||||
const StandardLibrary = preload('res://addons/Wol/core/libraries/standard.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 _variableStorage
|
||||||
|
|
||||||
var _debugLog
|
|
||||||
var _errLog
|
|
||||||
|
|
||||||
var _program
|
var _program
|
||||||
var library
|
var library
|
||||||
|
|
||||||
var _vm : VirtualMachine
|
var _vm
|
||||||
|
|
||||||
var _visitedNodeCount : Dictionary = {}
|
var _visitedNodeCount = {}
|
||||||
|
|
||||||
var executionComplete : bool
|
var executionComplete
|
||||||
|
|
||||||
func _init(variableStorage):
|
func _init(variableStorage):
|
||||||
_variableStorage = variableStorage
|
_variableStorage = variableStorage
|
||||||
_vm = VirtualMachine.new(self)
|
_vm = VirtualMachine.new(self)
|
||||||
library = WolLibrary.new()
|
library = WolLibrary.new()
|
||||||
_debugLog = funcref(self, 'dlog')
|
|
||||||
_errLog = funcref(self, 'elog')
|
|
||||||
executionComplete = false
|
executionComplete = false
|
||||||
|
|
||||||
# import the standard library
|
# import the standard library
|
||||||
|
@ -41,13 +35,6 @@ func _init(variableStorage):
|
||||||
#add function to lib that gets the node visit count
|
#add function to lib that gets the node visit count
|
||||||
library.register_function('visit_count', -1, funcref(self, 'node_visit_count'), true)
|
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():
|
func is_active():
|
||||||
return get_exec_state() != Constants.ExecutionState.Stopped
|
return get_exec_state() != Constants.ExecutionState.Stopped
|
||||||
|
|
||||||
|
@ -55,15 +42,19 @@ func is_active():
|
||||||
func get_exec_state():
|
func get_exec_state():
|
||||||
return _vm.executionState
|
return _vm.executionState
|
||||||
|
|
||||||
func set_selected_option(option:int):
|
func set_selected_option(option):
|
||||||
_vm.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)
|
_vm.set_node(name)
|
||||||
|
|
||||||
|
func start():
|
||||||
|
if _vm.executionState == Constants.ExecutionState.Stopped:
|
||||||
|
_vm.resume()
|
||||||
|
|
||||||
func resume():
|
func resume():
|
||||||
if _vm.executionState == Constants.ExecutionState.Running:
|
if _vm.executionState == Constants.ExecutionState.Running \
|
||||||
print('BLOCKED')
|
or _vm.executionState == Constants.ExecutionState.Stopped:
|
||||||
return
|
return
|
||||||
_vm.resume()
|
_vm.resume()
|
||||||
|
|
||||||
|
@ -81,12 +72,10 @@ func current_node():
|
||||||
|
|
||||||
func get_node_id(name):
|
func get_node_id(name):
|
||||||
if _program.nodes.size() == 0:
|
if _program.nodes.size() == 0:
|
||||||
_errLog.call_func('No nodes loaded')
|
|
||||||
return ''
|
return ''
|
||||||
if _program.nodes.has(name):
|
if _program.nodes.has(name):
|
||||||
return 'id:'+name
|
return 'id:'+name
|
||||||
else:
|
else:
|
||||||
_errLog.call_func('No node named [%s] exists' % name)
|
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
func unloadAll(clear_visited:bool = true):
|
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()):
|
func node_visit_count(node = _vm.current_node_name()):
|
||||||
if node is Value:
|
if node is Value:
|
||||||
node = _program.wolStrings[node.value()].text
|
node = _program.strings[node.value()].text
|
||||||
|
|
||||||
var visitCount : int = 0
|
var visitCount : int = 0
|
||||||
if _visitedNodeCount.has(node):
|
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():
|
func _init():
|
||||||
register_function("Add",2,funcref(self,"add"),true)
|
register_function('Add', 2, funcref(self, 'add'), true)
|
||||||
register_function("Minus",2,funcref(self,"sub"),true)
|
register_function('Minus', 2, funcref(self, 'sub'), true)
|
||||||
register_function("UnaryMinus",1,funcref(self,"unary_minus"),true)
|
register_function('UnaryMinus', 1, funcref(self, 'unary_minus'), true)
|
||||||
register_function("Divide",2,funcref(self,"div"),true)
|
register_function('Divide', 2, funcref(self, 'div'), true)
|
||||||
register_function("Multiply",2,funcref(self,"mul"),true)
|
register_function('Multiply', 2, funcref(self, 'mul'), true)
|
||||||
register_function("Modulo",2,funcref(self,"mod"),true)
|
register_function('Modulo', 2, funcref(self, 'mod'), true)
|
||||||
register_function("EqualTo",2,funcref(self,"equal"),true)
|
register_function('EqualTo', 2, funcref(self, 'equal'), true)
|
||||||
register_function("NotEqualTo",2,funcref(self,"noteq"),true)
|
register_function('NotEqualTo', 2, funcref(self, 'noteq'), true)
|
||||||
register_function("GreaterThan",2,funcref(self,"ge"),true)
|
register_function('GreaterThan', 2, funcref(self, 'ge'), true)
|
||||||
register_function("GreaterThanOrEqualTo",2,funcref(self,"geq"),true)
|
register_function('GreaterThanOrEqualTo', 2, funcref(self, 'geq'), true)
|
||||||
register_function("LessThan",2,funcref(self,"le"),true)
|
register_function('LessThan', 2, funcref(self, 'le'), true)
|
||||||
register_function("LessThanOrEqualTo",2,funcref(self,"leq"),true)
|
register_function('LessThanOrEqualTo', 2, funcref(self, 'leq'), true)
|
||||||
register_function("And",2,funcref(self,"land"),true)
|
register_function('And', 2, funcref(self, 'land'), true)
|
||||||
register_function("Or",2,funcref(self,"lor"),true)
|
register_function('Or', 2, funcref(self, 'lor'), true)
|
||||||
register_function("Xor",2,funcref(self,"xor"),true)
|
register_function('Xor', 2, funcref(self, 'xor'), true)
|
||||||
register_function("Not",1,funcref(self,"lnot"),true)
|
register_function('Not', 1, funcref(self, 'lnot'), true)
|
||||||
|
|
||||||
func add(param1:Value,param2:Value):
|
func add(param1, param2):
|
||||||
return param1.add(param2)
|
return param1.add(param2)
|
||||||
|
|
||||||
func sub(param1:Value,param2:Value):
|
func sub(param1, param2):
|
||||||
return param1.sub(param2)
|
return param1.sub(param2)
|
||||||
|
|
||||||
func unary_minus(param1:Value):
|
func unary_minus(param1):
|
||||||
return param1.negative()
|
return param1.negative()
|
||||||
|
|
||||||
func div(param1:Value,param2:Value):
|
func div(param1, param2):
|
||||||
return param1.div(param2)
|
return param1.div(param2)
|
||||||
|
|
||||||
func mul(param1:Value,param2:Value):
|
func mul(param1, param2):
|
||||||
return param1.mult(param2)
|
return param1.mult(param2)
|
||||||
|
|
||||||
func mod(param1:Value,param2:Value):
|
func mod(param1, param2):
|
||||||
return param1.mod(param2)
|
return param1.mod(param2)
|
||||||
|
|
||||||
func equal(param1:Value,param2:Value):
|
func equal(param1, param2):
|
||||||
return param1.equals(param2)
|
return param1.equals(param2)
|
||||||
|
|
||||||
func noteq(param1:Value,param2:Value):
|
func noteq(param1, param2):
|
||||||
return !param1.equals(param2)
|
return !param1.equals(param2)
|
||||||
|
|
||||||
func ge(param1:Value,param2:Value):
|
func ge(param1, param2):
|
||||||
return param1.greater(param2)
|
return param1.greater(param2)
|
||||||
|
|
||||||
func geq(param1:Value,param2:Value):
|
func geq(param1, param2):
|
||||||
return param1.geq(param2)
|
return param1.geq(param2)
|
||||||
|
|
||||||
func le(param1:Value,param2:Value):
|
func le(param1, param2):
|
||||||
return param1.less(param2)
|
return param1.less(param2)
|
||||||
|
|
||||||
func leq(param1:Value,param2:Value):
|
func leq(param1, param2):
|
||||||
return param1.leq(param2)
|
return param1.leq(param2)
|
||||||
|
|
||||||
func land(param1:Value,param2:Value):
|
func land(param1, param2):
|
||||||
return param1.as_bool() && param2.as_bool()
|
return param1.as_bool() and param2.as_bool()
|
||||||
|
|
||||||
func lor(param1:Value,param2:Value):
|
func lor(param1, param2):
|
||||||
return param1.as_bool() || param2.as_bool()
|
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()
|
return param1.as_bool() != param2.as_bool()
|
||||||
|
|
||||||
func lnot(param1:Value):
|
func lnot(param1):
|
||||||
return !param1.as_bool()
|
return not param1.as_bool()
|
||||||
|
|
|
@ -22,6 +22,22 @@ class Line:
|
||||||
self.implicit = implicit
|
self.implicit = implicit
|
||||||
self.meta = meta
|
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:
|
class WolNode:
|
||||||
var name = ''
|
var name = ''
|
||||||
var instructions = []
|
var instructions = []
|
||||||
|
|
|
@ -1,15 +1,7 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
const Constants = preload('res://addons/Wol/core/constants.gd')
|
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 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'
|
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)
|
printerr('No node named %s has been loaded' % name)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
_dialogue.dlog('Running node %s' % name)
|
|
||||||
|
|
||||||
_currentNode = _program.nodes[name]
|
_currentNode = _program.nodes[name]
|
||||||
reset()
|
reset()
|
||||||
_state.currentNodeName = name
|
_state.currentNodeName = name
|
||||||
nodeStartHandler.call_func(name)
|
nodeStartHandler.call_func(name)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
func current_node_name()->String:
|
func current_node_name()->String:
|
||||||
return _currentNode.nodeName
|
return _currentNode.nodeName
|
||||||
|
|
||||||
|
@ -86,8 +75,8 @@ func set_selected_option(id):
|
||||||
printerr('Unable to select option when dialogue not waiting for option')
|
printerr('Unable to select option when dialogue not waiting for option')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if id < 0 || id >= _state.currentOptions.size():
|
if id < 0 or id >= _state.currentOptions.size():
|
||||||
printerr('%d is not a valid option '%id)
|
printerr('%d is not a valid option ' % id)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
var destination = _state.currentOptions[id].value
|
var destination = _state.currentOptions[id].value
|
||||||
|
@ -99,40 +88,39 @@ func set_selected_option(id):
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func has_options()->bool:
|
|
||||||
return _state.currentOptions.size() > 0
|
|
||||||
|
|
||||||
func reset():
|
func reset():
|
||||||
_state = VmState.new()
|
_state = VmState.new()
|
||||||
|
|
||||||
#continue execution
|
func get_next_instruction():
|
||||||
func resume()->bool:
|
return null if _currentNode.instructions.size() - 1 <= _state.programCounter else _currentNode.instructions[_state.programCounter + 1]
|
||||||
if _currentNode == null :
|
|
||||||
|
func resume():
|
||||||
|
if _currentNode == null:
|
||||||
printerr('Cannot run dialogue with no node selected')
|
printerr('Cannot run dialogue with no node selected')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if executionState == Constants.ExecutionState.WaitingForOption:
|
if executionState == Constants.ExecutionState.WaitingForOption:
|
||||||
printerr('Cannot run while waiting for option')
|
printerr('Cannot run while waiting for option')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if lineHandler == null :
|
if lineHandler == null:
|
||||||
printerr('Cannot run without a lineHandler')
|
printerr('Cannot run without a lineHandler')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if optionsHandler == null :
|
if optionsHandler == null:
|
||||||
printerr('Cannot run without an optionsHandler')
|
printerr('Cannot run without an optionsHandler')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if commandHandler == null :
|
if commandHandler == null:
|
||||||
printerr('Cannot run without an commandHandler')
|
printerr('Cannot run without an commandHandler')
|
||||||
return false
|
return false
|
||||||
if nodeStartHandler == null :
|
if nodeStartHandler == null:
|
||||||
printerr('Cannot run without a nodeStartHandler')
|
printerr('Cannot run without a nodeStartHandler')
|
||||||
return false
|
return false
|
||||||
if nodeCompleteHandler == null :
|
if nodeCompleteHandler == null:
|
||||||
printerr('Cannot run without an nodeCompleteHandler')
|
printerr('Cannot run without an nodeCompleteHandler')
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
||||||
executionState = Constants.ExecutionState.Running
|
executionState = Constants.ExecutionState.Running
|
||||||
|
|
||||||
#execute instruction until something cool happens
|
#execute instruction until something cool happens
|
||||||
|
@ -140,14 +128,13 @@ func resume()->bool:
|
||||||
var currentInstruction = _currentNode.instructions[_state.programCounter]
|
var currentInstruction = _currentNode.instructions[_state.programCounter]
|
||||||
|
|
||||||
run_instruction(currentInstruction)
|
run_instruction(currentInstruction)
|
||||||
_state.programCounter+=1
|
_state.programCounter += 1
|
||||||
|
|
||||||
if _state.programCounter >= _currentNode.instructions.size():
|
if _state.programCounter >= _currentNode.instructions.size():
|
||||||
nodeCompleteHandler.call_func(_currentNode.nodeName)
|
nodeCompleteHandler.call_func(_currentNode.nodeName)
|
||||||
executionState = Constants.ExecutionState.Stopped
|
executionState = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
dialogueCompleteHandler.call_func()
|
dialogueCompleteHandler.call_func()
|
||||||
_dialogue.dlog('Run Complete')
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
@ -171,7 +158,7 @@ func run_instruction(instruction)->bool:
|
||||||
#pass it to client as line
|
#pass it to client as line
|
||||||
var key = instruction.operands[0].value
|
var key = instruction.operands[0].value
|
||||||
|
|
||||||
var line = Line.new(key)
|
var line = _program.strings[key]
|
||||||
|
|
||||||
#the second operand is the expression count
|
#the second operand is the expression count
|
||||||
# of format function
|
# of format function
|
||||||
|
@ -180,7 +167,6 @@ func run_instruction(instruction)->bool:
|
||||||
|
|
||||||
var pause : int = lineHandler.call_func(line)
|
var pause : int = lineHandler.call_func(line)
|
||||||
|
|
||||||
|
|
||||||
if pause == Constants.HandlerState.PauseExecution:
|
if pause == Constants.HandlerState.PauseExecution:
|
||||||
executionState = Constants.ExecutionState.Suspended
|
executionState = Constants.ExecutionState.Suspended
|
||||||
|
|
||||||
|
@ -190,7 +176,7 @@ func run_instruction(instruction)->bool:
|
||||||
if instruction.operands.size() > 1:
|
if instruction.operands.size() > 1:
|
||||||
pass#add format function
|
pass#add format function
|
||||||
|
|
||||||
var command = Command.new(commandText)
|
var command = Program.Command.new(commandText)
|
||||||
|
|
||||||
var pause = commandHandler.call_func(command) as int
|
var pause = commandHandler.call_func(command) as int
|
||||||
if pause == Constants.HandlerState.PauseExecution:
|
if pause == Constants.HandlerState.PauseExecution:
|
||||||
|
@ -275,7 +261,7 @@ func run_instruction(instruction)->bool:
|
||||||
|
|
||||||
Constants.ByteCode.Stop:
|
Constants.ByteCode.Stop:
|
||||||
#stop execution and repost it
|
#stop execution and repost it
|
||||||
nodeCompleteHandler.call_func(_currentNode.nodeName)
|
nodeCompleteHandler.call_func(_currentNode.name)
|
||||||
dialogueCompleteHandler.call_func()
|
dialogueCompleteHandler.call_func()
|
||||||
executionState = Constants.ExecutionState.Stopped
|
executionState = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
|
@ -290,7 +276,7 @@ func run_instruction(instruction)->bool:
|
||||||
else :
|
else :
|
||||||
name = instruction.operands[0].value
|
name = instruction.operands[0].value
|
||||||
|
|
||||||
var pause = nodeCompleteHandler.call_func(_currentNode.nodeName)
|
var pause = nodeCompleteHandler.call_func(_currentNode.name)
|
||||||
set_node(name)
|
set_node(name)
|
||||||
_state.programCounter-=1
|
_state.programCounter-=1
|
||||||
if pause == Constants.HandlerState.PauseExecution:
|
if pause == Constants.HandlerState.PauseExecution:
|
||||||
|
@ -300,13 +286,13 @@ func run_instruction(instruction)->bool:
|
||||||
# add an option to current state
|
# add an option to current state
|
||||||
var key = instruction.operands[0].value
|
var key = instruction.operands[0].value
|
||||||
|
|
||||||
var line = Line.new(key)
|
var line = _program.strings[key]
|
||||||
|
|
||||||
if instruction.operands.size() > 2:
|
if instruction.operands.size() > 2:
|
||||||
pass #formated text options
|
pass #formated text options
|
||||||
|
|
||||||
# line to show and node name
|
# 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:
|
Constants.ByteCode.ShowOptions:
|
||||||
#show options - stop if none
|
#show options - stop if none
|
||||||
|
@ -320,7 +306,7 @@ func run_instruction(instruction)->bool:
|
||||||
var choices : Array = []#Option
|
var choices : Array = []#Option
|
||||||
for optionIndex in range(_state.currentOptions.size()):
|
for optionIndex in range(_state.currentOptions.size()):
|
||||||
var option : SimpleEntry = _state.currentOptions[optionIndex]
|
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
|
#we cant continue until option chosen
|
||||||
executionState = Constants.ExecutionState.WaitingForOption
|
executionState = Constants.ExecutionState.WaitingForOption
|
||||||
|
@ -334,7 +320,7 @@ func run_instruction(instruction)->bool:
|
||||||
#bytecode messed up woopsise
|
#bytecode messed up woopsise
|
||||||
executionState = Constants.ExecutionState.Stopped
|
executionState = Constants.ExecutionState.Stopped
|
||||||
reset()
|
reset()
|
||||||
printerr('Unknown Bytecode %s '%instruction.operation)
|
printerr('Unknown Bytecode %s' % instruction.operation)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -353,7 +339,6 @@ class VmState:
|
||||||
else:
|
else:
|
||||||
stack.push_back(Value.new(value))
|
stack.push_back(Value.new(value))
|
||||||
|
|
||||||
|
|
||||||
func pop_value():
|
func pop_value():
|
||||||
return stack.pop_back()
|
return stack.pop_back()
|
||||||
|
|
||||||
|
@ -365,8 +350,8 @@ class VmState:
|
||||||
|
|
||||||
class SimpleEntry:
|
class SimpleEntry:
|
||||||
var key
|
var key
|
||||||
var value : String
|
var value
|
||||||
|
|
||||||
func _init(key,value:String):
|
func _init(key, value):
|
||||||
self.key = key
|
self.key = key
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
|
@ -1,78 +1,41 @@
|
||||||
title: Start
|
title: Start
|
||||||
tags:
|
tags:
|
||||||
colorID: 0
|
colorID: 0
|
||||||
position: -1892,-1013
|
position: 0, 0
|
||||||
---
|
---
|
||||||
<<load_situation The Revolver>>
|
<<a_custom_command>>
|
||||||
<<animation elevator door open>>
|
<<command_with multiple arguments>>
|
||||||
|
|
||||||
Masami: Gina, this way! #line:5d7a7c
|
// remove "to" to trigger error
|
||||||
Gina: Patience! I’m coming.
|
<<set $direction to 'this'>>
|
||||||
>Still, she didn’t pick up her pace and kept hesitantly looking around.<
|
<<set $one to 1>>
|
||||||
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: ...
|
|
||||||
|
|
||||||
<<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.
|
[[Go to the store|TheStore]]
|
||||||
Gina: So it seems.
|
[[Lets stay here and talk|Talk]]
|
||||||
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]]
|
|
||||||
===
|
===
|
||||||
title: Waking up
|
title: TheStore
|
||||||
tags:
|
tags:
|
||||||
colorID: 0
|
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]
|
[application]
|
||||||
|
|
||||||
config/name="YarnSpinner"
|
config/name="Wol"
|
||||||
run/main_scene="res://Dialogue.tscn"
|
run/main_scene="res://Dialogue.tscn"
|
||||||
config/icon="res://icon.png"
|
config/icon="res://icon.png"
|
||||||
|
|
||||||
|
|
Reference in a new issue