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