replaced a bunch of other stuff

This commit is contained in:
Bram Dingelstad 2021-11-20 14:51:10 +01:00
parent e3bac32178
commit 611fc399ae
3 changed files with 270 additions and 271 deletions

View file

@ -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(''))

View file

@ -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:

View file

@ -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