replaced a bunch of other stuff
This commit is contained in:
parent
e3bac32178
commit
611fc399ae
|
@ -17,18 +17,18 @@ const DUPLICATE_NODES_IN_PROGRAM = 0x08
|
||||||
const ERR_COMPILATION_FAILED = 0x10
|
const ERR_COMPILATION_FAILED = 0x10
|
||||||
|
|
||||||
var _errors : int
|
var _errors : int
|
||||||
var _lastError : int
|
var _last_error : int
|
||||||
|
|
||||||
#-----Class vars
|
#-----Class vars
|
||||||
var _currentNode : Program.WolNode
|
var _current_node : Program.WolNode
|
||||||
var _rawText : bool
|
var _raw_text : bool
|
||||||
var _fileName : String
|
var _file_name : String
|
||||||
var _containsImplicitStringTags : bool
|
var _contains_implicit_string_tags : bool
|
||||||
var _labelCount : int = 0
|
var _label_count : int = 0
|
||||||
|
|
||||||
#<String, Program.Line>
|
#<String, Program.Line>
|
||||||
var _stringTable : Dictionary = {}
|
var _string_table : Dictionary = {}
|
||||||
var _stringCount : int = 0
|
var _string_count : int = 0
|
||||||
#<int, Constants.TokenType>
|
#<int, Constants.TokenType>
|
||||||
var _tokens : Dictionary = {}
|
var _tokens : Dictionary = {}
|
||||||
|
|
||||||
|
@ -37,36 +37,36 @@ static func compile_string(source: String, filename: String):
|
||||||
var Compiler = load('res://addons/Wol/core/compiler/compiler.gd')
|
var Compiler = load('res://addons/Wol/core/compiler/compiler.gd')
|
||||||
|
|
||||||
var compiler = Compiler.new()
|
var compiler = Compiler.new()
|
||||||
compiler._fileName = filename
|
compiler._file_name = filename
|
||||||
|
|
||||||
#--------------Nodes
|
#--------------Nodes
|
||||||
var headerSep : RegEx = RegEx.new()
|
var header_sep : RegEx = RegEx.new()
|
||||||
headerSep.compile('---(\r\n|\r|\n)')
|
header_sep.compile('---(\r\n|\r|\n)')
|
||||||
var headerProperty : RegEx = RegEx.new()
|
var header_property : RegEx = RegEx.new()
|
||||||
headerProperty.compile('(?<field>.*): *(?<value>.*)')
|
header_property.compile('(?<field>.*): *(?<value>.*)')
|
||||||
|
|
||||||
assert(not not headerSep.search(source), 'No headers found')
|
assert(not not header_sep.search(source), 'No headers found')
|
||||||
|
|
||||||
var lineNumber: int = 0
|
var line_number: int = 0
|
||||||
|
|
||||||
var sourceLines : Array = source.split('\n',false)
|
var source_lines : Array = source.split('\n',false)
|
||||||
for i in range(sourceLines.size()):
|
for i in range(source_lines.size()):
|
||||||
sourceLines[i] = sourceLines[i].strip_edges(false,true)
|
source_lines[i] = source_lines[i].strip_edges(false,true)
|
||||||
|
|
||||||
var parsedNodes : Array = []
|
var parsed_nodes : Array = []
|
||||||
|
|
||||||
while lineNumber < sourceLines.size():
|
while line_number < source_lines.size():
|
||||||
|
|
||||||
var title : String
|
var title : String
|
||||||
var body : String
|
var body : String
|
||||||
|
|
||||||
#get title
|
#get title
|
||||||
while true:
|
while true:
|
||||||
var line : String = sourceLines[lineNumber]
|
var line : String = source_lines[line_number]
|
||||||
lineNumber+=1
|
line_number+=1
|
||||||
|
|
||||||
if !line.empty():
|
if !line.empty():
|
||||||
var result = headerProperty.search(line)
|
var result = header_property.search(line)
|
||||||
if result != null :
|
if result != null :
|
||||||
var field : String = result.get_string('field')
|
var field : String = result.get_string('field')
|
||||||
var value : String = result.get_string('value')
|
var value : String = result.get_string('value')
|
||||||
|
@ -74,125 +74,125 @@ static func compile_string(source: String, filename: String):
|
||||||
if field == 'title':
|
if field == 'title':
|
||||||
title = value
|
title = value
|
||||||
|
|
||||||
if(lineNumber >= sourceLines.size() || sourceLines[lineNumber] == '---'):
|
if(line_number >= source_lines.size() || source_lines[line_number] == '---'):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
lineNumber+=1
|
line_number+=1
|
||||||
|
|
||||||
#past header
|
#past header
|
||||||
var bodyLines : PoolStringArray = []
|
var body_lines : PoolStringArray = []
|
||||||
|
|
||||||
while lineNumber < sourceLines.size() && sourceLines[lineNumber]!='===':
|
while line_number < source_lines.size() && source_lines[line_number]!='===':
|
||||||
bodyLines.append(sourceLines[lineNumber])
|
body_lines.append(source_lines[line_number])
|
||||||
lineNumber+=1
|
line_number+=1
|
||||||
|
|
||||||
lineNumber+=1
|
line_number+=1
|
||||||
|
|
||||||
body = bodyLines.join('\n')
|
body = body_lines.join('\n')
|
||||||
var lexer = Lexer.new()
|
var lexer = Lexer.new()
|
||||||
|
|
||||||
var tokens : Array = lexer.tokenize(body)
|
var tokens : Array = lexer.tokenize(body)
|
||||||
var parser = Parser.new(tokens)
|
var parser = Parser.new(tokens)
|
||||||
|
|
||||||
var parserNode = parser.parse_node()
|
var parser_node = parser.parse_node()
|
||||||
|
|
||||||
parserNode.name = title
|
parser_node.name = title
|
||||||
parsedNodes.append(parserNode)
|
parsed_nodes.append(parser_node)
|
||||||
while lineNumber < sourceLines.size() && sourceLines[lineNumber].empty():
|
while line_number < source_lines.size() && source_lines[line_number].empty():
|
||||||
lineNumber+=1
|
line_number+=1
|
||||||
|
|
||||||
#--- End parsing nodes---
|
#--- End parsing nodes---
|
||||||
|
|
||||||
var program = Program.new()
|
var program = Program.new()
|
||||||
|
|
||||||
#compile nodes
|
#compile nodes
|
||||||
for node in parsedNodes:
|
for node in parsed_nodes:
|
||||||
compiler.compile_node(program, node)
|
compiler.compile_node(program, node)
|
||||||
|
|
||||||
for key in compiler._stringTable:
|
for key in compiler._string_table:
|
||||||
program.strings[key] = compiler._stringTable[key]
|
program.strings[key] = compiler._string_table[key]
|
||||||
|
|
||||||
return program
|
return program
|
||||||
|
|
||||||
func compile_node(program, parsedNode):
|
func compile_node(program, parsed_node):
|
||||||
if program.nodes.has(parsedNode.name):
|
if program.nodes.has(parsed_node.name):
|
||||||
emit_error(DUPLICATE_NODES_IN_PROGRAM)
|
emit_error(DUPLICATE_NODES_IN_PROGRAM)
|
||||||
printerr('Duplicate node in program: %s' % parsedNode.name)
|
printerr('Duplicate node in program: %s' % parsed_node.name)
|
||||||
else:
|
else:
|
||||||
var nodeCompiled = Program.WolNode.new()
|
var node_compiled = Program.WolNode.new()
|
||||||
|
|
||||||
nodeCompiled.name = parsedNode.name
|
node_compiled.name = parsed_node.name
|
||||||
nodeCompiled.tags = parsedNode.tags
|
node_compiled.tags = parsed_node.tags
|
||||||
|
|
||||||
#raw text
|
#raw text
|
||||||
if parsedNode.source != null && !parsedNode.source.empty():
|
if parsed_node.source != null && !parsed_node.source.empty():
|
||||||
nodeCompiled.sourceId = register_string(parsedNode.source,parsedNode.name,
|
node_compiled.source_id = register_string(parsed_node.source,parsed_node.name,
|
||||||
'line:'+parsedNode.name, 0, [])
|
'line:'+parsed_node.name, 0, [])
|
||||||
else:
|
else:
|
||||||
#compile node
|
#compile node
|
||||||
var startLabel : String = register_label()
|
var start_label : String = register_label()
|
||||||
emit(Constants.ByteCode.Label,nodeCompiled,[Program.Operand.new(startLabel)])
|
emit(Constants.ByteCode.Label,node_compiled,[Program.Operand.new(start_label)])
|
||||||
|
|
||||||
for statement in parsedNode.statements:
|
for statement in parsed_node.statements:
|
||||||
generate_statement(nodeCompiled,statement)
|
generate_statement(node_compiled,statement)
|
||||||
|
|
||||||
|
|
||||||
#add options
|
#add options
|
||||||
#todo: add parser flag
|
#todo: add parser flag
|
||||||
|
|
||||||
var danglingOptions = false
|
var dangling_options = false
|
||||||
for instruction in nodeCompiled.instructions :
|
for instruction in node_compiled.instructions :
|
||||||
if instruction.operation == Constants.ByteCode.AddOption:
|
if instruction.operation == Constants.ByteCode.AddOption:
|
||||||
danglingOptions = true
|
dangling_options = true
|
||||||
if instruction.operation == Constants.ByteCode.ShowOptions:
|
if instruction.operation == Constants.ByteCode.ShowOptions:
|
||||||
danglingOptions = false
|
dangling_options = false
|
||||||
|
|
||||||
if danglingOptions:
|
if dangling_options:
|
||||||
emit(Constants.ByteCode.ShowOptions, nodeCompiled)
|
emit(Constants.ByteCode.ShowOptions, node_compiled)
|
||||||
emit(Constants.ByteCode.RunNode, nodeCompiled)
|
emit(Constants.ByteCode.Run_node, node_compiled)
|
||||||
else:
|
else:
|
||||||
emit(Constants.ByteCode.Stop, nodeCompiled)
|
emit(Constants.ByteCode.Stop, node_compiled)
|
||||||
|
|
||||||
|
|
||||||
program.nodes[nodeCompiled.name] = nodeCompiled
|
program.nodes[node_compiled.name] = node_compiled
|
||||||
|
|
||||||
func register_string(text:String,nodeName:String,id:String='',lineNumber:int=-1,tags:Array=[])->String:
|
func register_string(text:String,node_name:String,id:String='',line_number:int=-1,tags:Array=[])->String:
|
||||||
var lineIdUsed : String
|
var line_id_used : String
|
||||||
|
|
||||||
var implicit : bool
|
var implicit : bool
|
||||||
|
|
||||||
if id.empty():
|
if id.empty():
|
||||||
lineIdUsed = '%s-%s-%d' % [self._fileName,nodeName,self._stringCount]
|
line_id_used = '%s-%s-%d' % [self._file_name,node_name,self._string_count]
|
||||||
self._stringCount+=1
|
self._string_count+=1
|
||||||
|
|
||||||
#use this when we generate implicit tags
|
#use this when we generate implicit tags
|
||||||
#they are not saved and are generated
|
#they are not saved and are generated
|
||||||
#aka dummy tags that change on each compilation
|
#aka dummy tags that change on each compilation
|
||||||
_containsImplicitStringTags = true
|
_contains_implicit_string_tags = true
|
||||||
|
|
||||||
implicit = true
|
implicit = true
|
||||||
else :
|
else :
|
||||||
lineIdUsed = id
|
line_id_used = id
|
||||||
implicit = false
|
implicit = false
|
||||||
|
|
||||||
var stringInfo = Program.Line.new(text,nodeName,lineNumber,_fileName,implicit,tags)
|
var string_info = Program.Line.new(text,node_name,line_number,_file_name,implicit,tags)
|
||||||
#add to string table and return id
|
#add to string table and return id
|
||||||
self._stringTable[lineIdUsed] = stringInfo
|
self._string_table[line_id_used] = string_info
|
||||||
|
|
||||||
return lineIdUsed
|
return line_id_used
|
||||||
|
|
||||||
func register_label(comment:String='')->String:
|
func register_label(comment:String='')->String:
|
||||||
_labelCount+=1
|
_label_count+=1
|
||||||
return 'L%s%s' %[ _labelCount , comment]
|
return 'L%s%s' %[ _label_count , comment]
|
||||||
|
|
||||||
func emit(bytecode, node = _currentNode, operands = []):
|
func emit(bytecode, node = _current_node, operands = []):
|
||||||
var instruction = Program.Instruction.new(null)
|
var instruction = Program.Instruction.new(null)
|
||||||
instruction.operation = bytecode
|
instruction.operation = bytecode
|
||||||
instruction.operands = operands
|
instruction.operands = operands
|
||||||
|
|
||||||
if node == null:
|
if node == null:
|
||||||
printerr('trying to emit to null node with byteCode: %s' % bytecode)
|
printerr('trying to emit to null node with byte_code: %s' % bytecode)
|
||||||
return
|
return
|
||||||
|
|
||||||
node.instructions.append(instruction)
|
node.instructions.append(instruction)
|
||||||
|
@ -240,61 +240,61 @@ func generate_custom_command(node,command):
|
||||||
if command.expression != null:
|
if command.expression != null:
|
||||||
generate_expression(node,command.expression)
|
generate_expression(node,command.expression)
|
||||||
else:
|
else:
|
||||||
var commandString = command.client_command
|
var command_string = command.client_command
|
||||||
if commandString == 'stop':
|
if command_string == 'stop':
|
||||||
emit(Constants.ByteCode.Stop,node)
|
emit(Constants.ByteCode.Stop,node)
|
||||||
else :
|
else :
|
||||||
emit(Constants.ByteCode.RunCommand,node,[Program.Operand.new(commandString)])
|
emit(Constants.ByteCode.RunCommand,node,[Program.Operand.new(command_string)])
|
||||||
|
|
||||||
#compile instructions for linetags and use them
|
#compile instructions for linetags and use them
|
||||||
# \#line:number
|
# \#line:number
|
||||||
func generate_line(node,statement,line:String):
|
func generate_line(node,statement,line:String):
|
||||||
var num : String = register_string(line, node.name, '', statement.lineNumber, []);
|
var num : String = register_string(line, node.name, '', statement.line_number, []);
|
||||||
emit(Constants.ByteCode.RunLine, node, [Program.Operand.new(num)])
|
emit(Constants.ByteCode.RunLine, node, [Program.Operand.new(num)])
|
||||||
|
|
||||||
func generate_shortcut_group(node,shortcutGroup):
|
func generate_shortcut_group(node,shortcut_group):
|
||||||
# print('generating shortcutoptopn group')
|
# print('generating shortcutoptopn group')
|
||||||
var end : String = register_label('group_end')
|
var end : String = register_label('group_end')
|
||||||
|
|
||||||
var labels : Array = []#String
|
var labels : Array = []#String
|
||||||
|
|
||||||
var optionCount : int = 0
|
var option_count : int = 0
|
||||||
|
|
||||||
for option in shortcutGroup.options:
|
for option in shortcut_group.options:
|
||||||
var opDestination : String = register_label('option_%s'%[optionCount+1])
|
var op_destination : String = register_label('option_%s'%[option_count+1])
|
||||||
labels.append(opDestination)
|
labels.append(op_destination)
|
||||||
|
|
||||||
var endofClause : String = ''
|
var endof_clause : String = ''
|
||||||
|
|
||||||
if option.condition != null :
|
if option.condition != null :
|
||||||
endofClause = register_label('conditional_%s'%optionCount)
|
endof_clause = register_label('conditional_%s'%option_count)
|
||||||
generate_expression(node,option.condition)
|
generate_expression(node,option.condition)
|
||||||
emit(Constants.ByteCode.JumpIfFalse,node,[Program.Operand.new(endofClause)])
|
emit(Constants.ByteCode.Jump_if_false,node,[Program.Operand.new(endof_clause)])
|
||||||
|
|
||||||
var labelLineId : String = ''#no tag TODO: ADD TAG SUPPORT
|
var label_line_id : String = ''#no tag TODO: ADD TAG SUPPORT
|
||||||
var labelStringId : String = register_string(option.label,node.nodeName,
|
var label_string_id : String = register_string(option.label,node.node_name,
|
||||||
labelLineId,option.lineNumber,[])
|
label_line_id,option.line_number,[])
|
||||||
|
|
||||||
emit(Constants.ByteCode.AddOption,node,[Program.Operand.new(labelStringId),Program.Operand.new(opDestination)])
|
emit(Constants.ByteCode.AddOption,node,[Program.Operand.new(label_string_id),Program.Operand.new(op_destination)])
|
||||||
|
|
||||||
if option.condition != null :
|
if option.condition != null :
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(endofClause)])
|
emit(Constants.ByteCode.Label,node,[Program.Operand.new(endof_clause)])
|
||||||
emit(Constants.ByteCode.Pop,node)
|
emit(Constants.ByteCode.Pop,node)
|
||||||
|
|
||||||
optionCount+=1
|
option_count+=1
|
||||||
|
|
||||||
emit(Constants.ByteCode.ShowOptions,node)
|
emit(Constants.ByteCode.ShowOptions,node)
|
||||||
emit(Constants.ByteCode.Jump,node)
|
emit(Constants.ByteCode.Jump,node)
|
||||||
|
|
||||||
optionCount = 0
|
option_count = 0
|
||||||
|
|
||||||
for option in shortcutGroup.options:
|
for option in shortcut_group.options:
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(labels[optionCount])])
|
emit(Constants.ByteCode.Label,node,[Program.Operand.new(labels[option_count])])
|
||||||
|
|
||||||
if option.node != null :
|
if option.node != null :
|
||||||
generate_block(node,option.node.statements)
|
generate_block(node,option.node.statements)
|
||||||
emit(Constants.ByteCode.JumpTo,node,[Program.Operand.new(end)])
|
emit(Constants.ByteCode.Jump_to,node,[Program.Operand.new(end)])
|
||||||
optionCount+=1
|
option_count+=1
|
||||||
|
|
||||||
#end of option group
|
#end of option group
|
||||||
emit(Constants.ByteCode.Label,node,[Program.Operand.new(end)])
|
emit(Constants.ByteCode.Label,node,[Program.Operand.new(end)])
|
||||||
|
@ -323,10 +323,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.JumpIfFalse,node,[Program.Operand.new(end_clause)])
|
emit(Constants.ByteCode.Jump_if_false,node,[Program.Operand.new(end_clause)])
|
||||||
|
|
||||||
generate_block(node,clause.statements)
|
generate_block(node,clause.statements)
|
||||||
emit(Constants.ByteCode.JumpTo,node,[Program.Operand.new(endif)])
|
emit(Constants.ByteCode.Jump_to,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)])
|
||||||
|
@ -347,23 +347,23 @@ func generate_option(node,option):
|
||||||
#jump to another node
|
#jump to another node
|
||||||
emit(Constants.ByteCode.RunNode,node,[Program.Operand.new(destination)])
|
emit(Constants.ByteCode.RunNode,node,[Program.Operand.new(destination)])
|
||||||
else :
|
else :
|
||||||
var lineID : String = ''#tags not supported TODO: ADD TAG SUPPORT
|
var line_iD : String = ''#tags not supported TODO: ADD TAG SUPPORT
|
||||||
var stringID = register_string(option.label,node.nodeName,lineID,option.lineNumber,[])
|
var string_iD = register_string(option.label,node.node_name,line_iD,option.line_number,[])
|
||||||
|
|
||||||
emit(Constants.ByteCode.AddOption,node,[Program.Operand.new(stringID),Program.Operand.new(destination)])
|
emit(Constants.ByteCode.AddOption,node,[Program.Operand.new(string_iD),Program.Operand.new(destination)])
|
||||||
|
|
||||||
|
|
||||||
#compile instructions for assigning values
|
#compile instructions for assigning values
|
||||||
func generate_assignment(node,assignment):
|
func generate_assignment(node,assignment):
|
||||||
# print('generating assign')
|
# print('generating assign')
|
||||||
#assignment
|
#assignment
|
||||||
if assignment.operation == Constants.TokenType.EqualToOrAssign:
|
if assignment.operation == Constants.TokenType.Equal_to_or_assign:
|
||||||
#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.PushVariable,node,[assignment.destination])
|
emit(Constants.ByteCode.Push_variable,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 +371,16 @@ func generate_assignment(node,assignment):
|
||||||
#stack contains oldvalue and result
|
#stack contains oldvalue and result
|
||||||
|
|
||||||
match assignment.operation:
|
match assignment.operation:
|
||||||
Constants.TokenType.AddAssign:
|
Constants.TokenType.Add_assign:
|
||||||
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.MinusAssign:
|
Constants.TokenType.Minus_assign:
|
||||||
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.MultiplyAssign:
|
Constants.TokenType.Multiply_assign:
|
||||||
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.DivideAssign:
|
Constants.TokenType.Divide_assign:
|
||||||
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 +388,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.StoreVariable,node,[Program.Operand.new(assignment.destination)])
|
emit(Constants.ByteCode.Store_variable,node,[Program.Operand.new(assignment.destination)])
|
||||||
|
|
||||||
#clean stack
|
#clean stack
|
||||||
emit(Constants.ByteCode.Pop,node)
|
emit(Constants.ByteCode.Pop,node)
|
||||||
|
@ -399,9 +399,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.ExpressionType.Value:
|
Constants.Expression_type.Value:
|
||||||
generate_value(node,expression.value)
|
generate_value(node,expression.value)
|
||||||
Constants.ExpressionType.FunctionCall:
|
Constants.Expression_type.Function_call:
|
||||||
#eval all parameters
|
#eval all parameters
|
||||||
for param in expression.params:
|
for param in expression.params:
|
||||||
generate_expression(node,param)
|
generate_expression(node,param)
|
||||||
|
@ -423,7 +423,7 @@ func generate_value(node,value):
|
||||||
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 : String = register_string(value.value.as_string(),
|
||||||
node.nodeName,'',value.lineNumber,[])
|
node.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())])
|
||||||
|
@ -434,27 +434,26 @@ func generate_value(node,value):
|
||||||
_:
|
_:
|
||||||
printerr('Unrecognized valuenode type: %s' % value.value.type)
|
printerr('Unrecognized valuenode type: %s' % value.value.type)
|
||||||
|
|
||||||
|
|
||||||
#get the error flags
|
#get the error flags
|
||||||
func get_errors()->int:
|
func get_errors()->int:
|
||||||
return _errors
|
return _errors
|
||||||
|
|
||||||
#get the last error code reported
|
#get the last error code reported
|
||||||
func get_last_error()->int:
|
func get_last_error()->int:
|
||||||
return _lastError
|
return _last_error
|
||||||
|
|
||||||
func clear_errors()->void:
|
func clear_errors()->void:
|
||||||
_errors = NO_ERROR
|
_errors = NO_ERROR
|
||||||
_lastError = NO_ERROR
|
_last_error = NO_ERROR
|
||||||
|
|
||||||
func emit_error(error : int)->void:
|
func emit_error(error : int)->void:
|
||||||
_lastError = error
|
_last_error = error
|
||||||
_errors |= _lastError
|
_errors |= _last_error
|
||||||
|
|
||||||
static func print_tokens(tokens:Array=[]):
|
static func print_tokens(tokens:Array=[]):
|
||||||
var list : PoolStringArray = []
|
var list : PoolStringArray = []
|
||||||
list.append('\n')
|
list.append('\n')
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
list.append('%s (%s line %s)\n'%[Constants.token_type_name(token.type),token.value,token.lineNumber])
|
list.append('%s (%s line %s)\n'%[Constants.token_type_name(token.type),token.value,token.line_number])
|
||||||
print('TOKENS:')
|
print('TOKENS:')
|
||||||
print(list.join(''))
|
print(list.join(''))
|
||||||
|
|
|
@ -188,20 +188,20 @@ func tokenize(text:String)->Array:
|
||||||
var lines : PoolStringArray = text.split(LINE_SEPARATOR)
|
var lines : PoolStringArray = text.split(LINE_SEPARATOR)
|
||||||
lines.append('')
|
lines.append('')
|
||||||
|
|
||||||
var lineNumber : int = 1
|
var line_number : int = 1
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
tokens+=tokenize_line(line,lineNumber)
|
tokens+=tokenize_line(line,line_number)
|
||||||
lineNumber+=1
|
line_number+=1
|
||||||
|
|
||||||
var endOfInput : Token = Token.new(Constants.TokenType.EndOfInput,_currentState,lineNumber,0)
|
var endOfInput : Token = Token.new(Constants.TokenType.EndOfInput,_currentState,line_number,0)
|
||||||
tokens.append(endOfInput)
|
tokens.append(endOfInput)
|
||||||
|
|
||||||
# print(tokens)
|
# print(tokens)
|
||||||
|
|
||||||
return tokens
|
return tokens
|
||||||
|
|
||||||
func tokenize_line(line:String, lineNumber : int)->Array:
|
func tokenize_line(line:String, line_number : int)->Array:
|
||||||
var tokenStack : Array = []
|
var tokenStack : Array = []
|
||||||
|
|
||||||
var freshLine = line.replace('\t',' ').replace('\r','')
|
var freshLine = line.replace('\t',' ').replace('\r','')
|
||||||
|
@ -214,7 +214,7 @@ func tokenize_line(line:String, lineNumber : 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,lineNumber,prevIndentation.key)
|
var indent : Token = Token.new(Constants.TokenType.Indent,_currentState,line_number,prevIndentation.key)
|
||||||
indent.value = '%*s' % [indentation - prevIndentation.key,'']
|
indent.value = '%*s' % [indentation - prevIndentation.key,'']
|
||||||
|
|
||||||
_shouldTrackIndent = false
|
_shouldTrackIndent = false
|
||||||
|
@ -226,7 +226,7 @@ func tokenize_line(line:String, lineNumber : int)->Array:
|
||||||
while indentation < _indentStack.front().key:
|
while indentation < _indentStack.front().key:
|
||||||
var top : IntBoolPair = _indentStack.pop_front()
|
var top : IntBoolPair = _indentStack.pop_front()
|
||||||
if top.value:
|
if top.value:
|
||||||
var deIndent : Token = Token.new(Constants.TokenType.Dedent,_currentState,lineNumber,0)
|
var deIndent : Token = Token.new(Constants.TokenType.Dedent,_currentState,line_number,0)
|
||||||
tokenStack.push_front(deIndent)
|
tokenStack.push_front(deIndent)
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ func tokenize_line(line:String, lineNumber : int)->Array:
|
||||||
tokenText = tokenText.replace('\\\\', '\\')
|
tokenText = tokenText.replace('\\\\', '\\')
|
||||||
tokenText = tokenText.replace('\\\'','\'')
|
tokenText = tokenText.replace('\\\'','\'')
|
||||||
|
|
||||||
var token : Token = Token.new(rule.tokenType,_currentState,lineNumber,column,tokenText)
|
var token : Token = Token.new(rule.tokenType,_currentState,line_number,column,tokenText)
|
||||||
token.delimitsText = rule.delimitsText
|
token.delimitsText = rule.delimitsText
|
||||||
|
|
||||||
tokenStack.push_front(token)
|
tokenStack.push_front(token)
|
||||||
|
@ -296,7 +296,7 @@ func tokenize_line(line:String, lineNumber : int)->Array:
|
||||||
if rule.enterState != null && rule.enterState.length() > 0:
|
if rule.enterState != null && rule.enterState.length() > 0:
|
||||||
|
|
||||||
if !_states.has(rule.enterState):
|
if !_states.has(rule.enterState):
|
||||||
printerr('State[%s] not known - line(%s) col(%s)'%[rule.enterState,lineNumber,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])
|
||||||
|
@ -310,7 +310,7 @@ func tokenize_line(line:String, lineNumber : int)->Array:
|
||||||
|
|
||||||
if !matched:
|
if !matched:
|
||||||
# TODO: Send out some helpful messages
|
# TODO: Send out some helpful messages
|
||||||
printerr('expectedTokens [%s] - line(%s) col(%s)'%['refineErrors.Lexer.tokenize_line',lineNumber,column])
|
printerr('expectedTokens [%s] - line(%s) col(%s)'%['refineErrors.Lexer.tokenize_line',line_number,column])
|
||||||
return []
|
return []
|
||||||
|
|
||||||
var lastWhiteSpace : RegExMatch = whitespace.search(line,column)
|
var lastWhiteSpace : RegExMatch = whitespace.search(line,column)
|
||||||
|
@ -342,7 +342,7 @@ class Token:
|
||||||
var type : int
|
var type : int
|
||||||
var value : String
|
var value : String
|
||||||
|
|
||||||
var lineNumber : int
|
var line_number : int
|
||||||
var column : int
|
var column : int
|
||||||
var text : String
|
var text : String
|
||||||
|
|
||||||
|
@ -350,15 +350,15 @@ class Token:
|
||||||
var paramCount : int
|
var paramCount : int
|
||||||
var lexerState : String
|
var lexerState : String
|
||||||
|
|
||||||
func _init(type:int,state: LexerState, lineNumber:int = -1,column:int = -1,value:String =''):
|
func _init(type:int,state: LexerState, line_number:int = -1,column:int = -1,value:String =''):
|
||||||
self.type = type
|
self.type = type
|
||||||
self.lexerState = state.stateName
|
self.lexerState = state.stateName
|
||||||
self.lineNumber = lineNumber
|
self.line_number = line_number
|
||||||
self.column = column
|
self.column = column
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
func _to_string():
|
func _to_string():
|
||||||
return '%s (%s) at %s:%s (state: %s)' % [Constants.token_type_name(type),value,lineNumber,column,lexerState]
|
return '%s (%s) at %s:%s (state: %s)' % [Constants.token_type_name(type),value,line_number,column,lexerState]
|
||||||
|
|
||||||
|
|
||||||
class LexerState:
|
class LexerState:
|
||||||
|
|
|
@ -56,20 +56,20 @@ func tokens():
|
||||||
|
|
||||||
class ParseNode:
|
class ParseNode:
|
||||||
var parent
|
var parent
|
||||||
var lineNumber = -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:
|
||||||
lineNumber = tokens.front().lineNumber
|
line_number = tokens.front().line_number
|
||||||
else:
|
else:
|
||||||
lineNumber = -1
|
line_number = -1
|
||||||
tags = []
|
tags = []
|
||||||
|
|
||||||
func tree_string(indent_level):
|
func tree_string(indent_level):
|
||||||
return 'NotImplemented'
|
return 'Not_implemented'
|
||||||
|
|
||||||
func tags_to_string(indent_level):
|
func tags_to_string(indent_level):
|
||||||
return '%s' % 'TAGS<tags_to_string>NOTIMPLEMENTED'
|
return '%s' % 'TAGS<tags_to_string>NOTIMPLEMENTED'
|
||||||
|
@ -93,7 +93,7 @@ class WolNode extends ParseNode:
|
||||||
var name = ''
|
var name = ''
|
||||||
var source = ''
|
var source = ''
|
||||||
|
|
||||||
var editorNodeTags = []
|
var editor_node_tags = []
|
||||||
var statements = []
|
var statements = []
|
||||||
|
|
||||||
func _init(name, parent, parser).(parent, parser):
|
func _init(name, parent, parser).(parent, parser):
|
||||||
|
@ -140,7 +140,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.AssignmentStatement
|
type = Type.Assignment_statement
|
||||||
|
|
||||||
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 +175,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.AssignmentStatement:
|
Type.Assignment_statement:
|
||||||
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 +194,7 @@ class CustomCommand extends ParseNode:
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
Expression,
|
Expression,
|
||||||
ClientCommand
|
Client_command
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = -1
|
var type = -1
|
||||||
|
@ -215,21 +215,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.LeftParen):
|
&& command_tokens[1].type == Constants.TokenType.Left_paren):
|
||||||
var p = get_script().new(command_tokens, parser.library)
|
var p = get_script().new(command_tokens, parser.library)
|
||||||
var expression = ExpressionNode.parse(self, p)
|
var expression = Expression_node.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.ClientCommand
|
type = Type.Client_command
|
||||||
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.ClientCommand:
|
Type.Client_command:
|
||||||
return tab(indent_level,'Command: %s' % client_command)
|
return tab(indent_level,'Command: %s' % client_command)
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
@ -246,10 +246,10 @@ class ShortcutOptionGroup extends ParseNode:
|
||||||
# expect one otherwise invalid
|
# expect one otherwise invalid
|
||||||
|
|
||||||
var index = 1
|
var index = 1
|
||||||
options.append(ShortCutOption.new(index, self, parser))
|
options.append(Short_cut_option.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(ShortCutOption.new(index, self, parser))
|
options.append(Short_cut_option.new(index, self, parser))
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
func tree_string(indent_level):
|
func tree_string(indent_level):
|
||||||
|
@ -267,7 +267,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 ShortCutOption extends ParseNode:
|
class Short_cut_option extends ParseNode:
|
||||||
var label = ''
|
var label = ''
|
||||||
var condition
|
var condition
|
||||||
var node
|
var node
|
||||||
|
@ -285,7 +285,7 @@ class ShortCutOption 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 = ExpressionNode.parse(self, parser)
|
condition = Expression_node.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]):
|
||||||
|
@ -397,14 +397,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 = ExpressionNode.parse(self, parser)
|
prime.expression = Expression_node.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.EndIf]) \
|
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.End_if]) \
|
||||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseToken]) \
|
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_token]) \
|
||||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseIf]):
|
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_if]):
|
||||||
|
|
||||||
statements.append(Statement.new(self, parser))
|
statements.append(Statement.new(self, parser))
|
||||||
|
|
||||||
|
@ -416,20 +416,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.ElseIf]):
|
while parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_if]):
|
||||||
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.ElseIf])
|
parser.expect_symbol([Constants.TokenType.Else_if])
|
||||||
clause_elif.expression = ExpressionNode.parse(self, parser)
|
clause_elif.expression = Expression_node.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.EndIf]) \
|
while not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.End_if]) \
|
||||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseToken]) \
|
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_token]) \
|
||||||
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.ElseIf]):
|
and not parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.Else_if]):
|
||||||
|
|
||||||
elif_statements.append(Statement.new(self, parser))
|
elif_statements.append(Statement.new(self, parser))
|
||||||
|
|
||||||
|
@ -442,21 +442,21 @@ 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.ElseToken, Constants.TokenType.EndCommand])):
|
Constants.TokenType.Else_token, 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.ElseToken])
|
parser.expect_symbol([Constants.TokenType.Else_token])
|
||||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||||
|
|
||||||
#parse until hit endif
|
#parse until hit endif
|
||||||
var clauseElse = Clause.new()
|
var clause_else = Clause.new()
|
||||||
var elStatements = []#statement
|
var el_statements = []#statement
|
||||||
while !parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.EndIf]):
|
while !parser.next_symbols_are([Constants.TokenType.BeginCommand, Constants.TokenType.End_if]):
|
||||||
elStatements.append(Statement.new(self, parser))
|
el_statements.append(Statement.new(self, parser))
|
||||||
|
|
||||||
clauseElse.statements = elStatements
|
clause_else.statements = el_statements
|
||||||
clauses.append(clauseElse)
|
clauses.append(clause_else)
|
||||||
|
|
||||||
#ignore dedent
|
#ignore dedent
|
||||||
while parser.next_symbol_is([Constants.TokenType.Dedent]):
|
while parser.next_symbol_is([Constants.TokenType.Dedent]):
|
||||||
|
@ -464,7 +464,7 @@ class IfStatement extends ParseNode:
|
||||||
|
|
||||||
#finish
|
#finish
|
||||||
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
parser.expect_symbol([Constants.TokenType.BeginCommand])
|
||||||
parser.expect_symbol([Constants.TokenType.EndIf])
|
parser.expect_symbol([Constants.TokenType.End_if])
|
||||||
parser.expect_symbol([Constants.TokenType.EndCommand])
|
parser.expect_symbol([Constants.TokenType.EndCommand])
|
||||||
|
|
||||||
|
|
||||||
|
@ -488,7 +488,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 ValueNode extends ParseNode:
|
class Value_node 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 +508,15 @@ class ValueNode 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.FalseToken:
|
Constants.TokenType.False_token:
|
||||||
value = Value.new(false)
|
value = Value.new(false)
|
||||||
Constants.TokenType.TrueToken:
|
Constants.TokenType.True_token:
|
||||||
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.ValueType.Variable
|
value.type = Constants.Value_type.Variable
|
||||||
value.variable = token.value
|
value.variable = token.value
|
||||||
Constants.TokenType.NullToken:
|
Constants.TokenType.Null_token:
|
||||||
value = Value.new(null)
|
value = Value.new(null)
|
||||||
_:
|
_:
|
||||||
printerr('%s, Invalid token type' % token.name)
|
printerr('%s, Invalid token type' % token.name)
|
||||||
|
@ -529,33 +529,33 @@ class ValueNode extends ParseNode:
|
||||||
# math (1 + 2 - 5 * 3 / 10 % 2)
|
# math (1 + 2 - 5 * 3 / 10 % 2)
|
||||||
# Identifiers
|
# Identifiers
|
||||||
# Values
|
# Values
|
||||||
class ExpressionNode extends ParseNode:
|
class Expression_node extends ParseNode:
|
||||||
var type
|
var type
|
||||||
var value
|
var value
|
||||||
var function
|
var function
|
||||||
var params = []#ExpressionNode
|
var params = []#Expression_node
|
||||||
|
|
||||||
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.ExpressionType.Value
|
self.type = Constants.Expression_type.Value
|
||||||
self.value = value
|
self.value = value
|
||||||
else:#function
|
else:#function
|
||||||
|
|
||||||
self.type = Constants.ExpressionType.FunctionCall
|
self.type = Constants.Expression_type.Function_call
|
||||||
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.ExpressionType.Value:
|
Constants.Expression_type.Value:
|
||||||
return value.tree_string(indent_level)
|
return value.tree_string(indent_level)
|
||||||
Constants.ExpressionType.FunctionCall:
|
Constants.Expression_type.Function_call:
|
||||||
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 paramSize:%s'%[(function) , params.size()])
|
#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,'}'))
|
||||||
|
|
||||||
|
@ -566,68 +566,68 @@ class ExpressionNode extends ParseNode:
|
||||||
#build a tree of expressions
|
#build a tree of expressions
|
||||||
static func parse(parent, parser):
|
static func parse(parent, parser):
|
||||||
var rpn = []
|
var rpn = []
|
||||||
var opStack = []
|
var op_stack = []
|
||||||
|
|
||||||
#track params
|
#track params
|
||||||
var funcStack = []
|
var func_stack = []
|
||||||
|
|
||||||
var validTypes = [
|
var valid_types = [
|
||||||
Constants.TokenType.Number,
|
Constants.TokenType.Number,
|
||||||
Constants.TokenType.Variable,
|
Constants.TokenType.Variable,
|
||||||
Constants.TokenType.Str,
|
Constants.TokenType.Str,
|
||||||
Constants.TokenType.LeftParen,
|
Constants.TokenType.Left_paren,
|
||||||
Constants.TokenType.RightParen,
|
Constants.TokenType.Right_paren,
|
||||||
Constants.TokenType.Identifier,
|
Constants.TokenType.Identifier,
|
||||||
Constants.TokenType.Comma,
|
Constants.TokenType.Comma,
|
||||||
Constants.TokenType.TrueToken,
|
Constants.TokenType.True_token,
|
||||||
Constants.TokenType.FalseToken,
|
Constants.TokenType.False_token,
|
||||||
Constants.TokenType.NullToken
|
Constants.TokenType.Null_token
|
||||||
]
|
]
|
||||||
validTypes += Operator.op_types()
|
valid_types += Operator.op_types()
|
||||||
validTypes.invert()
|
valid_types.invert()
|
||||||
|
|
||||||
var last
|
var last
|
||||||
|
|
||||||
#read expression content
|
#read expression content
|
||||||
while parser.tokens().size() > 0 && parser.next_symbol_is(validTypes):
|
while parser.tokens().size() > 0 && parser.next_symbol_is(valid_types):
|
||||||
var next = parser.expect_symbol(validTypes)
|
var next = parser.expect_symbol(valid_types)
|
||||||
|
|
||||||
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.FalseToken \
|
or next.type == Constants.TokenType.False_token \
|
||||||
or next.type == Constants.TokenType.TrueToken \
|
or next.type == Constants.TokenType.True_token \
|
||||||
or next.type == Constants.TokenType.NullToken:
|
or next.type == Constants.TokenType.Null_token:
|
||||||
|
|
||||||
#output primitives
|
#output primitives
|
||||||
rpn.append(next)
|
rpn.append(next)
|
||||||
elif next.type == Constants.TokenType.Identifier:
|
elif next.type == Constants.TokenType.Identifier:
|
||||||
opStack.push_back(next)
|
op_stack.push_back(next)
|
||||||
funcStack.push_back(next)
|
func_stack.push_back(next)
|
||||||
|
|
||||||
#next token is parent - left
|
#next token is parent - left
|
||||||
next = parser.expect_symbol([Constants.TokenType.LeftParen])
|
next = parser.expect_symbol([Constants.TokenType.Left_paren])
|
||||||
opStack.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 opStack.back().type != Constants.TokenType.LeftParen:
|
while op_stack.back().type != Constants.TokenType.Left_paren:
|
||||||
var p = opStack.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)
|
||||||
break
|
break
|
||||||
rpn.append(p)
|
rpn.append(p)
|
||||||
|
|
||||||
|
|
||||||
#next token in opStack 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.RightParen,
|
if parser.next_symbol_is([Constants.TokenType.Right_paren,
|
||||||
Constants.TokenType.Comma]):
|
Constants.TokenType.Comma]):
|
||||||
printerr('Expected Expression : %s' % parser.tokens().front().name)
|
printerr('Expected Expression : %s' % parser.tokens().front().name)
|
||||||
|
|
||||||
#find the closest function on stack
|
#find the closest function on stack
|
||||||
#increment parameters
|
#increment parameters
|
||||||
funcStack.back().paramCount+=1
|
func_stack.back().param_count+=1
|
||||||
|
|
||||||
elif Operator.is_op(next.type):
|
elif Operator.is_op(next.type):
|
||||||
#this is an operator
|
#this is an operator
|
||||||
|
@ -643,10 +643,10 @@ class ExpressionNode 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.LeftParen \
|
or last.type == Constants.TokenType.Left_paren \
|
||||||
or Operator.is_op(last.type):
|
or Operator.is_op(last.type):
|
||||||
#unary minus
|
#unary minus
|
||||||
next.type = Constants.TokenType.UnaryMinus
|
next.type = Constants.TokenType.Unary_minus
|
||||||
|
|
||||||
#cannot assign inside expression
|
#cannot assign inside expression
|
||||||
# x = a is the same as x == a
|
# x = a is the same as x == a
|
||||||
|
@ -655,42 +655,42 @@ class ExpressionNode extends ParseNode:
|
||||||
|
|
||||||
|
|
||||||
#operator precedence
|
#operator precedence
|
||||||
while (ExpressionNode.is_apply_precedence(next.type, opStack)):
|
while (Expression_node.is_apply_precedence(next.type, op_stack)):
|
||||||
var op = opStack.pop_back()
|
var op = op_stack.pop_back()
|
||||||
rpn.append(op)
|
rpn.append(op)
|
||||||
|
|
||||||
opStack.push_back(next)
|
op_stack.push_back(next)
|
||||||
|
|
||||||
elif next.type == Constants.TokenType.LeftParen:
|
elif next.type == Constants.TokenType.Left_paren:
|
||||||
#entered parenthesis sub expression
|
#entered parenthesis sub expression
|
||||||
opStack.push_back(next)
|
op_stack.push_back(next)
|
||||||
elif next.type == Constants.TokenType.RightParen:
|
elif next.type == Constants.TokenType.Right_paren:
|
||||||
#leaving sub expression
|
#leaving sub expression
|
||||||
# resolve order of operations
|
# resolve order of operations
|
||||||
while opStack.back().type != Constants.TokenType.LeftParen:
|
while op_stack.back().type != Constants.TokenType.Left_paren:
|
||||||
rpn.append(opStack.pop_back())
|
rpn.append(op_stack.pop_back())
|
||||||
if opStack.back() == null:
|
if op_stack.back() == null:
|
||||||
printerr('Unbalanced parenthasis #RightParen. Parser.ExpressionNode')
|
printerr('Unbalanced parenthasis #Right_paren. Parser.Expression_node')
|
||||||
|
|
||||||
|
|
||||||
opStack.pop_back()
|
op_stack.pop_back()
|
||||||
if opStack.back().type == Constants.TokenType.Identifier:
|
if op_stack.back().type == Constants.TokenType.Identifier:
|
||||||
#function call
|
#function call
|
||||||
#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.LeftParen:
|
if last.type != Constants.TokenType.Left_paren:
|
||||||
funcStack.back().paramCount+=1
|
func_stack.back().param_count+=1
|
||||||
|
|
||||||
rpn.append(opStack.pop_back())
|
rpn.append(op_stack.pop_back())
|
||||||
funcStack.pop_back()
|
func_stack.pop_back()
|
||||||
|
|
||||||
#record last token used
|
#record last token used
|
||||||
last = next
|
last = next
|
||||||
|
|
||||||
#no more tokens : pop operators to output
|
#no more tokens : pop operators to output
|
||||||
while opStack.size() > 0:
|
while op_stack.size() > 0:
|
||||||
rpn.append(opStack.pop_back())
|
rpn.append(op_stack.pop_back())
|
||||||
|
|
||||||
#if rpn is empty then this is not expression
|
#if rpn is empty then this is not expression
|
||||||
if rpn.size() == 0:
|
if rpn.size() == 0:
|
||||||
|
@ -698,7 +698,7 @@ class ExpressionNode extends ParseNode:
|
||||||
|
|
||||||
#build expression tree
|
#build expression tree
|
||||||
var first = rpn.front()
|
var first = rpn.front()
|
||||||
var evalStack = []#ExpressionNode
|
var eval_stack = []#Expression_node
|
||||||
|
|
||||||
while rpn.size() > 0:
|
while rpn.size() > 0:
|
||||||
|
|
||||||
|
@ -707,50 +707,50 @@ class ExpressionNode extends ParseNode:
|
||||||
#operation
|
#operation
|
||||||
var info = Operator.op_info(next.type)
|
var info = Operator.op_info(next.type)
|
||||||
|
|
||||||
if evalStack.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), evalStack.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 = []#ExpressionNode
|
var params = []#Expression_node
|
||||||
for i in range(info.arguments):
|
for i in range(info.arguments):
|
||||||
params.append(evalStack.pop_back())
|
params.append(eval_stack.pop_back())
|
||||||
|
|
||||||
params.invert()
|
params.invert()
|
||||||
|
|
||||||
var function = get_func_name(next.type)
|
var function = get_func_name(next.type)
|
||||||
|
|
||||||
var expression = ExpressionNode.new(parent, parser, null, function, params)
|
var expression = Expression_node.new(parent, parser, null, function, params)
|
||||||
|
|
||||||
evalStack.append(expression)
|
eval_stack.append(expression)
|
||||||
|
|
||||||
elif next.type == Constants.TokenType.Identifier:
|
elif next.type == Constants.TokenType.Identifier:
|
||||||
#function call
|
#function call
|
||||||
|
|
||||||
var function = next.value
|
var function = next.value
|
||||||
|
|
||||||
var params = []#ExpressionNode
|
var params = []#Expression_node
|
||||||
for i in range(next.paramCount):
|
for i in range(next.param_count):
|
||||||
|
|
||||||
params.append(evalStack.pop_back())
|
params.append(eval_stack.pop_back())
|
||||||
|
|
||||||
params.invert()
|
params.invert()
|
||||||
|
|
||||||
var expression = ExpressionNode.new(parent, parser, null, function, params)
|
var expression = Expression_node.new(parent, parser, null, function, params)
|
||||||
|
|
||||||
evalStack.append(expression)
|
eval_stack.append(expression)
|
||||||
else: #raw value
|
else: #raw value
|
||||||
var value = ValueNode.new(parent, parser, next)
|
var value = Value_node.new(parent, parser, next)
|
||||||
var expression = ExpressionNode.new(parent, parser, value)
|
var expression = Expression_node.new(parent, parser, value)
|
||||||
evalStack.append(expression)
|
eval_stack.append(expression)
|
||||||
|
|
||||||
|
|
||||||
#we should have a single root expression left
|
#we should have a single root expression left
|
||||||
#if more then we failed ---- NANI
|
#if more then we failed ---- NANI
|
||||||
if evalStack.size() != 1:
|
if eval_stack.size() != 1:
|
||||||
printerr('[%s] Error parsing expression (stack did not reduce correctly )' % first.name)
|
printerr('[%s] Error parsing expression (stack did not reduce correctly )' % first.name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return evalStack.pop_back()
|
return eval_stack.pop_back()
|
||||||
|
|
||||||
static func get_func_name(type):
|
static func get_func_name(type):
|
||||||
var string = ''
|
var string = ''
|
||||||
|
@ -760,27 +760,27 @@ class ExpressionNode extends ParseNode:
|
||||||
return key
|
return key
|
||||||
return string
|
return string
|
||||||
|
|
||||||
static func is_apply_precedence(type, operatorStack):
|
static func is_apply_precedence(type, operator_stack):
|
||||||
if operatorStack.size() == 0:
|
if operator_stack.size() == 0:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if not Operator.is_op(type):
|
if not Operator.is_op(type):
|
||||||
printerr('Unable to parse expression!')
|
printerr('Unable to parse expression!')
|
||||||
|
|
||||||
var second = operatorStack.back().type
|
var second = operator_stack.back().type
|
||||||
|
|
||||||
if not Operator.is_op(second):
|
if not Operator.is_op(second):
|
||||||
return false
|
return false
|
||||||
|
|
||||||
var firstInfo = Operator.op_info(type)
|
var first_info = Operator.op_info(type)
|
||||||
var secondInfo = Operator.op_info(second)
|
var second_info = Operator.op_info(second)
|
||||||
|
|
||||||
if (firstInfo.associativity == Associativity.Left &&
|
if (first_info.associativity == Associativity.Left &&
|
||||||
firstInfo.precedence <= secondInfo.precedence):
|
first_info.precedence <= second_info.precedence):
|
||||||
return true
|
return true
|
||||||
|
|
||||||
if (firstInfo.associativity == Associativity.Right &&
|
if (first_info.associativity == Associativity.Right &&
|
||||||
firstInfo.precedence < secondInfo.precedence):
|
first_info.precedence < second_info.precedence):
|
||||||
return true
|
return true
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
@ -796,7 +796,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 = ExpressionNode.parse(self, parser)
|
value = Expression_node.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,26 +817,26 @@ class Assignment extends ParseNode:
|
||||||
static func valid_ops():
|
static func valid_ops():
|
||||||
return [
|
return [
|
||||||
Constants.TokenType.EqualToOrAssign,
|
Constants.TokenType.EqualToOrAssign,
|
||||||
Constants.TokenType.AddAssign,
|
Constants.TokenType.Add_assign,
|
||||||
Constants.TokenType.MinusAssign,
|
Constants.TokenType.Minus_assign,
|
||||||
Constants.TokenType.DivideAssign,
|
Constants.TokenType.Divide_assign,
|
||||||
Constants.TokenType.MultiplyAssign
|
Constants.TokenType.Multiply_assign
|
||||||
]
|
]
|
||||||
|
|
||||||
class Operator extends ParseNode:
|
class Operator extends ParseNode:
|
||||||
|
|
||||||
var opType
|
var op_type
|
||||||
|
|
||||||
func _init(parent, parser, opType=null).(parent, parser):
|
func _init(parent, parser, op_type=null).(parent, parser):
|
||||||
|
|
||||||
if opType == null :
|
if op_type == null :
|
||||||
self.opType = parser.expect_symbol(Operator.op_types()).type
|
self.op_type = parser.expect_symbol(Operator.op_types()).type
|
||||||
else:
|
else:
|
||||||
self.opType = opType
|
self.op_type = op_type
|
||||||
|
|
||||||
func tree_string(indent_level):
|
func tree_string(indent_level):
|
||||||
var info = []
|
var info = []
|
||||||
info.append(tab(indent_level, opType))
|
info.append(tab(indent_level, op_type))
|
||||||
return info.join('')
|
return info.join('')
|
||||||
|
|
||||||
static func op_info(op):
|
static func op_info(op):
|
||||||
|
@ -848,22 +848,22 @@ class Operator extends ParseNode:
|
||||||
var TokenType = Constants.TokenType
|
var TokenType = Constants.TokenType
|
||||||
|
|
||||||
match op:
|
match op:
|
||||||
TokenType.Not, TokenType.UnaryMinus:
|
TokenType.Not, TokenType.Unary_minus:
|
||||||
return OperatorInfo.new(Associativity.Right, 30, 1)
|
return Operator_info.new(Associativity.Right, 30, 1)
|
||||||
TokenType.Multiply, TokenType.Divide, TokenType.Modulo:
|
TokenType.Multiply, TokenType.Divide, TokenType.Modulo:
|
||||||
return OperatorInfo.new(Associativity.Left, 20, 2)
|
return Operator_info.new(Associativity.Left, 20, 2)
|
||||||
TokenType.Add, TokenType.Minus:
|
TokenType.Add, TokenType.Minus:
|
||||||
return OperatorInfo.new(Associativity.Left, 15, 2)
|
return Operator_info.new(Associativity.Left, 15, 2)
|
||||||
TokenType.GreaterThan, TokenType.LessThan, TokenType.GreaterThanOrEqualTo, TokenType.LessThanOrEqualTo:
|
TokenType.GreaterThan, TokenType.LessThan, TokenType.GreaterThanOrEqualTo, TokenType.LessThanOrEqualTo:
|
||||||
return OperatorInfo.new(Associativity.Left, 10, 2)
|
return Operator_info.new(Associativity.Left, 10, 2)
|
||||||
TokenType.EqualTo, TokenType.EqualToOrAssign, TokenType.NotEqualTo:
|
TokenType.EqualTo, TokenType.EqualToOrAssign, TokenType.NotEqualTo:
|
||||||
return OperatorInfo.new(Associativity.Left, 5, 2)
|
return Operator_info.new(Associativity.Left, 5, 2)
|
||||||
TokenType.And:
|
TokenType.And:
|
||||||
return OperatorInfo.new(Associativity.Left, 4, 2)
|
return Operator_info.new(Associativity.Left, 4, 2)
|
||||||
TokenType.Or:
|
TokenType.Or:
|
||||||
return OperatorInfo.new(Associativity.Left, 3, 2)
|
return Operator_info.new(Associativity.Left, 3, 2)
|
||||||
TokenType.Xor:
|
TokenType.Xor:
|
||||||
return OperatorInfo.new(Associativity.Left, 2, 2)
|
return Operator_info.new(Associativity.Left, 2, 2)
|
||||||
_:
|
_:
|
||||||
printerr('Unknown operator: %s' % op.name)
|
printerr('Unknown operator: %s' % op.name)
|
||||||
return null
|
return null
|
||||||
|
@ -874,7 +874,7 @@ class Operator extends ParseNode:
|
||||||
static func op_types():
|
static func op_types():
|
||||||
return [
|
return [
|
||||||
Constants.TokenType.Not,
|
Constants.TokenType.Not,
|
||||||
Constants.TokenType.UnaryMinus,
|
Constants.TokenType.Unary_minus,
|
||||||
|
|
||||||
Constants.TokenType.Add,
|
Constants.TokenType.Add,
|
||||||
Constants.TokenType.Minus,
|
Constants.TokenType.Minus,
|
||||||
|
@ -897,7 +897,7 @@ class Operator extends ParseNode:
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class OperatorInfo:
|
class Operator_info:
|
||||||
var associativity
|
var associativity
|
||||||
var precedence = -1
|
var precedence = -1
|
||||||
var arguments = -1
|
var arguments = -1
|
||||||
|
|
Reference in a new issue